github.com/status-im/status-go@v1.1.0/services/wallet/collectibles/manager_test.go (about)

     1  package collectibles
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/big"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/golang/mock/gomock"
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"github.com/ethereum/go-ethereum/common"
    15  	"github.com/status-im/status-go/circuitbreaker"
    16  	mock_client "github.com/status-im/status-go/rpc/chain/mock/client"
    17  	mock_rpcclient "github.com/status-im/status-go/rpc/mock/client"
    18  	"github.com/status-im/status-go/services/wallet/bigint"
    19  	mock_collectibles "github.com/status-im/status-go/services/wallet/collectibles/mock"
    20  	walletCommon "github.com/status-im/status-go/services/wallet/common"
    21  	"github.com/status-im/status-go/services/wallet/thirdparty"
    22  	mock_thirdparty "github.com/status-im/status-go/services/wallet/thirdparty/mock"
    23  )
    24  
    25  type CopyableMockChainClient struct {
    26  	*mock_client.MockClientInterface
    27  	cb *circuitbreaker.CircuitBreaker
    28  }
    29  
    30  func (c *CopyableMockChainClient) Copy() interface{} {
    31  	return &CopyableMockChainClient{
    32  		MockClientInterface: c.MockClientInterface,
    33  	}
    34  }
    35  
    36  func (c *CopyableMockChainClient) GetCircuitBreaker() *circuitbreaker.CircuitBreaker {
    37  	return c.cb
    38  }
    39  
    40  func (c *CopyableMockChainClient) SetCircuitBreaker(cb *circuitbreaker.CircuitBreaker) {
    41  	c.cb = cb
    42  }
    43  
    44  func TestManager_FetchAllAssetsByOwner(t *testing.T) {
    45  	mockCtrl := gomock.NewController(t)
    46  	defer mockCtrl.Finish()
    47  
    48  	ctx := context.TODO()
    49  	chainID := walletCommon.ChainID(1)
    50  	owner := common.HexToAddress("0x1234567890abcdef")
    51  	cursor := ""
    52  	limit := 1
    53  	timestamp := time.Now().Nanosecond()
    54  	providerID := fmt.Sprintf("circuit_%d", timestamp)
    55  
    56  	chainClient := &CopyableMockChainClient{
    57  		MockClientInterface: mock_client.NewMockClientInterface(mockCtrl),
    58  	}
    59  	chainClient.EXPECT().CallContract(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(limit)
    60  	chainClient.EXPECT().CodeAt(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil).Times(limit)
    61  	rpcClient := mock_rpcclient.NewMockClientInterface(mockCtrl)
    62  	rpcClient.EXPECT().EthClient(gomock.Any()).Return(chainClient, nil).AnyTimes()
    63  	mockProvider1 := mock_thirdparty.NewMockCollectibleAccountOwnershipProvider(mockCtrl)
    64  	// We use 2 providers as the last one is not using hystrix
    65  	mockProvider2 := mock_thirdparty.NewMockCollectibleAccountOwnershipProvider(mockCtrl)
    66  
    67  	mockProviders := thirdparty.CollectibleProviders{
    68  		AccountOwnershipProviders: []thirdparty.CollectibleAccountOwnershipProvider{mockProvider1, mockProvider2},
    69  	}
    70  
    71  	// Generate many collectibles, but none support toeknURI method, but circuit must not be tripped
    72  	var items []thirdparty.FullCollectibleData
    73  	for i := 0; i < limit; i++ {
    74  		items = append(items, thirdparty.FullCollectibleData{
    75  			CollectibleData: thirdparty.CollectibleData{
    76  				ID: thirdparty.CollectibleUniqueID{
    77  					ContractID: thirdparty.ContractID{
    78  						Address: common.HexToAddress(fmt.Sprintf("0x%064x", i)),
    79  					},
    80  					TokenID: &bigint.BigInt{
    81  						Int: big.NewInt(int64(i)),
    82  					},
    83  				},
    84  			},
    85  		})
    86  	}
    87  	mockAssetContainer := &thirdparty.FullCollectibleDataContainer{
    88  		Items: items,
    89  	}
    90  
    91  	mockProvider1.EXPECT().IsChainSupported(chainID).Return(true).AnyTimes()
    92  	mockProvider1.EXPECT().IsConnected().Return(true).AnyTimes()
    93  	mockProvider1.EXPECT().ID().Return(providerID).AnyTimes()
    94  	mockProvider1.EXPECT().FetchAllAssetsByOwner(gomock.Any(), chainID, owner, cursor, limit).Return(mockAssetContainer, nil)
    95  
    96  	mockProvider2.EXPECT().IsChainSupported(chainID).Return(true).AnyTimes()
    97  	mockProvider2.EXPECT().IsConnected().Return(true).AnyTimes()
    98  	mockProvider2.EXPECT().ID().Return(providerID).AnyTimes()
    99  
   100  	manager := NewManager(nil, rpcClient, nil, mockProviders, nil, nil)
   101  	manager.statuses = &sync.Map{}
   102  	collectiblesDataDB := mock_collectibles.NewMockCollectibleDataStorage(mockCtrl)
   103  	collectiblesDataDB.EXPECT().SetData(gomock.Any(), gomock.Any()).Return(nil)
   104  	collectionsDataDB := mock_collectibles.NewMockCollectionDataStorage(mockCtrl)
   105  	collectionsDataDB.EXPECT().SetData(gomock.Any(), gomock.Any()).Return(nil)
   106  	manager.collectiblesDataDB = collectiblesDataDB
   107  	manager.collectionsDataDB = collectionsDataDB
   108  
   109  	assetContainer, err := manager.FetchAllAssetsByOwner(ctx, chainID, owner, cursor, limit, providerID)
   110  
   111  	assert.NoError(t, err)
   112  	assert.Equal(t, mockAssetContainer, assetContainer)
   113  
   114  	// Make sure the main circuit is not tripped
   115  	circuitName := getCircuitName(mockProvider1, chainID)
   116  	assert.True(t, circuitbreaker.CircuitExists(circuitName))
   117  	assert.False(t, circuitbreaker.IsCircuitOpen(circuitName))
   118  }