diff --git a/rpc/storage.go b/rpc/storage.go index 6d31e699a3..b884cf38e1 100644 --- a/rpc/storage.go +++ b/rpc/storage.go @@ -3,7 +3,6 @@ package rpc import ( "errors" - "github.com/NethermindEth/juno/core" "github.com/NethermindEth/juno/core/felt" "github.com/NethermindEth/juno/core/trie" diff --git a/rpc/storage_test.go b/rpc/storage_test.go index 8a7fea9302..ce55f59595 100644 --- a/rpc/storage_test.go +++ b/rpc/storage_test.go @@ -340,6 +340,106 @@ func TestStorageProof(t *testing.T) { }) } +func TestStorageProofErrorHandling(t *testing.T) { + mockCtrl := gomock.NewController(t) + t.Cleanup(mockCtrl.Finish) + + mockReader := mocks.NewMockReader(mockCtrl) + mockState := mocks.NewMockStateHistoryReader(mockCtrl) + mockTrie := mocks.NewMockTrieReader(mockCtrl) + handler := rpc.New(mockReader, nil, nil, "", utils.NewNopZapLogger()) + nopCloser := func() error { return nil } + + key := new(felt.Felt).SetUint64(1) + blockLatest := rpc.BlockID{Latest: true} + expectedErr := errors.New("expected error") + + t.Run("error handling HeadState", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(nil, nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, []felt.Felt{*key}, nil, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling Head()", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, []felt.Felt{*key}, nil, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling HeadTrie", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(&core.Block{Header: &core.Header{Hash: new(felt.Felt), Number: 0}}, nil).Times(1) + mockReader.EXPECT().HeadTrie().Return(nil, nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, []felt.Felt{*key}, nil, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling StateAndClassRoot", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(&core.Block{Header: &core.Header{Hash: new(felt.Felt), Number: 0}}, nil).Times(1) + mockReader.EXPECT().HeadTrie().Return(mockTrie, nopCloser, nil).Times(1) + mockTrie.EXPECT().StateAndClassRoot().Return(nil, nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, []felt.Felt{*key}, nil, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling getClassesProof", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(&core.Block{Header: &core.Header{Hash: new(felt.Felt), Number: 0}}, nil).Times(1) + mockReader.EXPECT().HeadTrie().Return(mockTrie, nopCloser, nil).Times(1) + mockTrie.EXPECT().StateAndClassRoot().Return(new(felt.Felt), new(felt.Felt), nil).Times(1) + mockTrie.EXPECT().ClassTrie().Return(nil, nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, []felt.Felt{*key}, nil, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling getContractsProof", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(&core.Block{Header: &core.Header{Hash: new(felt.Felt), Number: 0}}, nil).Times(1) + mockReader.EXPECT().HeadTrie().Return(mockTrie, nopCloser, nil).Times(1) + mockTrie.EXPECT().StateAndClassRoot().Return(new(felt.Felt), new(felt.Felt), nil).Times(1) + mockTrie.EXPECT().ClassTrie().Return(new(trie.Trie), nopCloser, nil).Times(1) + mockTrie.EXPECT().StorageTrie().Return(nil, nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, nil, []felt.Felt{*key}, nil) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) + t.Run("error handling getContractsStorageProofs", func(t *testing.T) { + mockReader.EXPECT().HeadState().Return(mockState, nopCloser, nil).Times(1) + mockReader.EXPECT().Head().Return(&core.Block{Header: &core.Header{Hash: new(felt.Felt), Number: 0}}, nil).Times(1) + mockReader.EXPECT().HeadTrie().Return(mockTrie, nopCloser, nil).Times(1) + mockTrie.EXPECT().StateAndClassRoot().Return(new(felt.Felt), new(felt.Felt), nil).Times(1) + mockTrie.EXPECT().ClassTrie().Return(new(trie.Trie), nopCloser, nil).Times(1) + mockTrie.EXPECT().StorageTrie().Return(new(trie.Trie), nopCloser, nil).Times(1) + mockTrie.EXPECT().StorageTrieForAddr(key).Return(nil, expectedErr).Times(1) + + proof, rpcErr := handler.StorageProof(blockLatest, nil, nil, []rpc.StorageKeys{{Contract: *key, Keys: []felt.Felt{*key}}}) + require.Nil(t, proof) + require.NotNil(t, rpcErr) + require.Equal(t, "Internal error", rpcErr.Message) + require.Equal(t, expectedErr, rpcErr.Data.(error)) + }) +} + func TestStorageRoots(t *testing.T) { t.Parallel() diff --git a/utils/slices_test.go b/utils/slices_test.go index 9ef6fcff66..91c98823c6 100644 --- a/utils/slices_test.go +++ b/utils/slices_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestMap(t *testing.T) { @@ -73,3 +74,46 @@ func TestAnyOf(t *testing.T) { assert.False(t, AnyOf("9", "1", "2", "3", "4", "5", "6")) }) } + +func TestUnique(t *testing.T) { + t.Run("nil slice", func(t *testing.T) { + var input []int + actual := Unique(input) + assert.Nil(t, actual) + }) + t.Run("empty slice returns nil", func(t *testing.T) { + input := []int{} + actual := Unique(input) + assert.Nil(t, actual) + }) + t.Run("slice with data", func(t *testing.T) { + expected := []int{1, 2, 3} + input := expected + input = append(input, expected...) + actual := Unique(input) + assert.Equal(t, expected, actual) + }) + t.Run("panic when called on pointers", func(t *testing.T) { + defer func() { + r := recover() + assert.NotNil(t, r) + assert.Contains(t, r.(string), "Unique() cannot be used with a slice of pointers") + }() + input := []*int{new(int), new(int)} + Unique(input) + }) + t.Run("with key function", func(t *testing.T) { + type thing struct { + id int + name string + } + + things := []thing{ + {1, "one"}, {1, "two"}, {2, "one"}, {2, "two"}, + } + + require.Len(t, UniqueFunc(things, func(t thing) int { return t.id }), 2) + require.Len(t, UniqueFunc(things, func(t thing) string { return t.name }), 2) + require.Equal(t, things, UniqueFunc(things, func(t thing) thing { return t })) + }) +}