Repository: NethermindEth/juno
Pull request #377 (2022-08-29 16:15:24)

Test RPC input types
## Description

Add tests for UnmarshalJSON of `BlockId`, `StorageKey`, and `RpcFelt`.

## Types of changes

- Other (please describe):  Add tests



codecov[bot]: # [Codecov](https://codecov.io/gh/NethermindEth/juno/pull/377?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) Report
> Merging [#377](https://codecov.io/gh/NethermindEth/juno/pull/377?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) (f727842) into [main](https://codecov.io/gh/NethermindEth/juno/commit/32dc226578f6802f13fb1cb8aab49c272ea65c7e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) (32dc226) will **increase** coverage by `0.79%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##             main     #377      +/-   ##
==========================================
+ Coverage   92.12%   92.91%   +0.79%     
==========================================
  Files          66       66              
  Lines        7084     7087       +3     
==========================================
+ Hits         6526     6585      +59     
+ Misses        554      498      -56     
  Partials        4        4              
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `92.91% <100.00%> (+0.79%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/NethermindEth/juno/pull/377?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth) | Coverage Δ | |
|---|---|---|
| [internal/rpc/starknet/types.go](https://codecov.io/gh/NethermindEth/juno/pull/377/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-aW50ZXJuYWwvcnBjL3N0YXJrbmV0L3R5cGVzLmdv) | `20.76% <100.00%> (+20.76%)` | :arrow_up: |
| [pkg/felt/felt.go](https://codecov.io/gh/NethermindEth/juno/pull/377/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-cGtnL2ZlbHQvZmVsdC5nbw==) | `100.00% <0.00%> (ø)` | |
| [pkg/crypto/weierstrass/weierstrass.go](https://codecov.io/gh/NethermindEth/juno/pull/377/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-cGtnL2NyeXB0by93ZWllcnN0cmFzcy93ZWllcnN0cmFzcy5nbw==) | `100.00% <0.00%> (ø)` | |
| [internal/rpc/starknet/utils.go](https://codecov.io/gh/NethermindEth/juno/pull/377/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth#diff-aW50ZXJuYWwvcnBjL3N0YXJrbmV0L3V0aWxzLmdv) | `24.13% <0.00%> (+24.13%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=NethermindEth)


Patch:
diff --git a/internal/rpc/starknet/types.go b/internal/rpc/starknet/types.go
index 02432499..307916dd 100644
--- a/internal/rpc/starknet/types.go
+++ b/internal/rpc/starknet/types.go
@@ -15,7 +15,8 @@ import (
 var ErrInvalidBlockId = errors.New("invalid block id")
 
 const (
-	blockIdHash BlockIdType = iota
+	blockIdUnknown BlockIdType = iota
+	blockIdHash
 	blockIdTag
 	blockIdNumber
 )
@@ -38,8 +39,8 @@ func (id *BlockId) tag() (string, bool) {
 }
 
 func (id *BlockId) number() (uint64, bool) {
-	n, ok := id.value.(int64)
-	return uint64(n), ok
+	n, ok := id.value.(uint64)
+	return n, ok
 }
 
 func (id *BlockId) UnmarshalJSON(data []byte) error {
@@ -52,14 +53,11 @@ func (id *BlockId) UnmarshalJSON(data []byte) error {
 	switch t := token.(type) {
 	case json.Number:
 		value, err := t.Int64()
-		if err != nil {
-			return err
-		}
-		if value < 0 {
+		if err != nil || value < 0 {
 			return ErrInvalidBlockId
 		}
 		id.idType = blockIdNumber
-		id.value = value
+		id.value = uint64(value)
 	case string:
 		if isBlockTag(t) {
 			id.idType = blockIdTag


Test patch:
diff --git a/internal/rpc/starknet/types_test.go b/internal/rpc/starknet/types_test.go
new file mode 100644
index 00000000..72901a87
--- /dev/null
+++ b/internal/rpc/starknet/types_test.go
@@ -0,0 +1,268 @@
+package starknet
+
+import (
+	"errors"
+	"io"
+	"testing"
+
+	gocmp "github.com/google/go-cmp/cmp"
+
+	"github.com/NethermindEth/juno/pkg/felt"
+	"gotest.tools/assert"
+)
+
+func TestBlockId_UnmarshalJSON(t *testing.T) {
+	tests := []struct {
+		name string
+		data []byte
+		want BlockId
+		err  error
+	}{
+		{
+			name: "empty data",
+			data: []byte{},
+			want: BlockId{},
+			err:  io.EOF,
+		},
+		{
+			name: "empty string",
+			data: []byte(`""`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+		{
+			name: "negative number",
+			data: []byte(`-1`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+		{
+			name: "float number",
+			data: []byte(`1.1`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+		{
+			name: "zero string",
+			data: []byte(`"0"`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+		{
+			name: "zero number",
+			data: []byte(`0`),
+			want: BlockId{
+				value:  uint64(0),
+				idType: blockIdNumber,
+			},
+			err: nil,
+		},
+		{
+			name: "positive number",
+			data: []byte(`1`),
+			want: BlockId{
+				value:  uint64(1),
+				idType: blockIdNumber,
+			},
+			err: nil,
+		},
+		{
+			name: "pending tag",
+			data: []byte(`"pending"`),
+			want: BlockId{
+				idType: blockIdTag,
+				value:  "pending",
+			},
+			err: nil,
+		},
+		{
+			name: "latest tag",
+			data: []byte(`"latest"`),
+			want: BlockId{
+				idType: blockIdTag,
+				value:  "latest",
+			},
+			err: nil,
+		},
+		{
+			name: "block hash",
+			data: []byte(`"0x07d328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"`),
+			want: BlockId{
+				idType: blockIdHash,
+				value:  new(felt.Felt).SetHex("0x07d328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"),
+			},
+			err: nil,
+		},
+		{
+			name: "invalid block hash",
+			data: []byte(`"0x7d328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+		{
+			name: "unexpected JSON type",
+			data: []byte(`{}`),
+			want: BlockId{},
+			err:  ErrInvalidBlockId,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var got BlockId
+			if err := got.UnmarshalJSON(tt.data); !errors.Is(err, tt.err) {
+				t.Errorf("BlockId.UnmarshalJSON() = %v, want %v", err, tt.err)
+			}
+			assert.DeepEqual(t, got, tt.want, gocmp.Comparer(func(x, y BlockId) bool {
+				switch x.idType {
+				case blockIdHash:
+					xh, xok := x.hash()
+					yh, yok := y.hash()
+					if !xok || !yok {
+						t.Fatal("invalid block id")
+					}
+					return xh.Equal(yh)
+				case blockIdTag:
+					xt, xok := x.tag()
+					yt, yok := x.tag()
+					if !xok || !yok {
+						t.Fatal("invalid block id")
+					}
+					return xt == yt
+				case blockIdNumber:
+					xn, xok := x.number()
+					yn, yok := y.number()
+					if !xok || !yok {
+						t.Fatal("invalid block id")
+					}
+					return xn == yn
+				case blockIdUnknown:
+					return y.idType == blockIdUnknown && x.value == nil && y.value == nil
+				}
+				return false
+			}))
+		})
+	}
+}
+
+func TestStorageKey_UnmarshalJSON(t *testing.T) {
+	tests := []struct {
+		name string
+		data []byte
+		want StorageKey
+		err  bool
+	}{
+		{
+			name: "empty data",
+			data: []byte{},
+			want: "",
+			err:  true,
+		},
+		{
+			// NOTE: This storage key is invalid because it is greater than prime P on the Stark
+			// curve and also does not match the storage key regular expression provided by the RPC
+			// specification.
+			name: "invalid storage key",
+			data: []byte(`"0x0ad328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"`),
+			want: "",
+			err:  true,
+		},
+		{
+			name: "valid storage key",
+			data: []byte(`"0x01d328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"`),
+			want: "0x01d328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b",
+			err:  false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var got StorageKey
+			if err := got.UnmarshalJSON(tt.data); (err != nil) != tt.err {
+				t.Errorf("StorageKey.UnmarshalJSON(), unexpected error: %v", err)
+			}
+			assert.DeepEqual(t, got, tt.want)
+		})
+	}
+}
+
+func TestStorageKeyToFelt(t *testing.T) {
+	tests := []struct {
+		storageKey StorageKey
+		want       *felt.Felt
+	}{
+		{
+			storageKey: "0x07352d792298a2578d6ef20e80bce32473fff67b9b12b1bc431982287190291a",
+			want:       new(felt.Felt).SetHex("0x07352d792298a2578d6ef20e80bce32473fff67b9b12b1bc431982287190291a"),
+		},
+		{
+			storageKey: "0x00898cca7dbf84c2213f3a00e84775013bc991bc104d3a00952ce4bc166a4a1a",
+			want:       new(felt.Felt).SetHex("0x00898cca7dbf84c2213f3a00e84775013bc991bc104d3a00952ce4bc166a4a1a"),
+		},
+		{
+			storageKey: "0x0000000000000000000000000000000000000000000000000000000000000005",
+			want:       new(felt.Felt).SetHex("0x0000000000000000000000000000000000000000000000000000000000000005"),
+		},
+	}
+	for _, tt := range tests {
+		assert.Check(t, tt.storageKey.Felt().Equal(tt.want))
+	}
+}
+
+func TestRpcFelt_UnmarshalJSON(t *testing.T) {
+	tests := []struct {
+		name string
+		data []byte
+		want RpcFelt
+		err  bool
+	}{
+		{
+			name: "empty data",
+			data: []byte{},
+			want: "",
+			err:  true,
+		},
+		{
+			name: "invalid felt",
+			data: []byte(`"0xad328a71faf48c5c3857e99f20a77b18522480956d1cd5bff1ff2df3c8b427b"`),
+			want: "",
+			err:  true,
+		},
+		{
+			name: "valid felt",
+			data: []byte(`"0x02c2bb91714f8448ed814bdac274ab6fcdbafc22d835f9e847e5bee8c2e5444e"`),
+			want: "0x02c2bb91714f8448ed814bdac274ab6fcdbafc22d835f9e847e5bee8c2e5444e",
+			err:  false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			var got RpcFelt
+			if err := got.UnmarshalJSON(tt.data); (err != nil) != tt.err {
+				t.Errorf("RpcFelt.UnmarshalJSON(), unexpected error: %v", err)
+			}
+			assert.DeepEqual(t, got, tt.want)
+		})
+	}
+}
+
+func TestRpcFeltToFelt(t *testing.T) {
+	tests := []struct {
+		rpcFelt RpcFelt
+		want    *felt.Felt
+	}{
+		{
+			rpcFelt: "0x045c61314be4da85f0e13df53d18062e002c04803218f08061e4b274d4b38537",
+			want:    new(felt.Felt).SetHex("0x045c61314be4da85f0e13df53d18062e002c04803218f08061e4b274d4b38537"),
+		},
+		{
+			rpcFelt: "0x0320e37cf7c972458a3edf08ab51f2ab7596857706af174a3d5be4e46f16c63e",
+			want:    new(felt.Felt).SetHex("0x0320e37cf7c972458a3edf08ab51f2ab7596857706af174a3d5be4e46f16c63e"),
+		},
+		{
+			rpcFelt: "0x048636a22c6c74f5631b00c66ac3c8ab4714aa308ddd214af4089ccdfcee0f81",
+			want:    new(felt.Felt).SetHex("0x048636a22c6c74f5631b00c66ac3c8ab4714aa308ddd214af4089ccdfcee0f81"),
+		},
+	}
+	for _, tt := range tests {
+		assert.Check(t, tt.rpcFelt.Felt().Equal(tt.want))
+	}
+}