chore(wallet)_: Added a test for Market manager FetchTokenMarketValues

Added a nil/empty command test for circuit breaker
This commit is contained in:
Ivan Belyakov 2024-07-03 15:10:10 +02:00 committed by Andrea Maria Piana
parent a009855bbb
commit 4b19845592
6 changed files with 233 additions and 25 deletions

View File

@ -345,6 +345,7 @@ mock: ##@other Regenerate mocks
mockgen -package=mock_bridge -destination=services/wallet/bridge/mock_bridge/bridge.go -source=services/wallet/bridge/bridge.go mockgen -package=mock_bridge -destination=services/wallet/bridge/mock_bridge/bridge.go -source=services/wallet/bridge/bridge.go
mockgen -package=mock_client -destination=rpc/chain/mock/client/client.go -source=rpc/chain/client.go mockgen -package=mock_client -destination=rpc/chain/mock/client/client.go -source=rpc/chain/client.go
mockgen -package=mock_token -destination=services/wallet/token/mock/token/tokenmanager.go -source=services/wallet/token/token.go mockgen -package=mock_token -destination=services/wallet/token/mock/token/tokenmanager.go -source=services/wallet/token/token.go
mockgen -package=mock_thirdparty -destination=services/wallet/thirdparty/mock/types.go -source=services/wallet/thirdparty/types.go
mockgen -package=mock_balance_persistence -destination=services/wallet/token/mock/balance_persistence/balance_persistence.go -source=services/wallet/token/balance_persistence.go mockgen -package=mock_balance_persistence -destination=services/wallet/token/mock/balance_persistence/balance_persistence.go -source=services/wallet/token/balance_persistence.go
mockgen -package=mock_network -destination=rpc/network/mock/network.go -source=rpc/network/network.go mockgen -package=mock_network -destination=rpc/network/mock/network.go -source=rpc/network/network.go
mockgen -package=mock_rpcclient -destination=rpc/mock/client/client.go -source=rpc/client.go mockgen -package=mock_rpcclient -destination=rpc/mock/client/client.go -source=rpc/client.go

View File

@ -131,7 +131,3 @@ func (cb *CircuitBreaker) Execute(cmd *Command) CommandResult {
return result return result
} }
func (cb *CircuitBreaker) Config() Config {
return cb.config
}

View File

@ -201,9 +201,10 @@ func TestCircuitBreaker_CommandCancel(t *testing.T) {
prov1Called := 0 prov1Called := 0
prov2Called := 0 prov2Called := 0
var ctx context.Context
expectedErr := errors.New("provider 1 failed") expectedErr := errors.New("provider 1 failed")
// These are executed sequentially
cmd := NewCommand(context.TODO(), nil) cmd := NewCommand(ctx, nil)
cmd.Add(NewFunctor(func() ([]interface{}, error) { cmd.Add(NewFunctor(func() ([]interface{}, error) {
prov1Called++ prov1Called++
cmd.Cancel() cmd.Cancel()
@ -215,9 +216,17 @@ func TestCircuitBreaker_CommandCancel(t *testing.T) {
}, circuitName+"2")) }, circuitName+"2"))
result := cb.Execute(cmd) result := cb.Execute(cmd)
t.Log(result.Error())
require.True(t, errors.Is(result.Error(), expectedErr)) require.True(t, errors.Is(result.Error(), expectedErr))
assert.Equal(t, 1, prov1Called) assert.Equal(t, 1, prov1Called)
assert.Equal(t, 0, prov2Called) assert.Equal(t, 0, prov2Called)
} }
func TestCircuitBreaker_EmptyOrNilCommand(t *testing.T) {
cb := NewCircuitBreaker(Config{})
cmd := NewCommand(context.TODO(), nil)
result := cb.Execute(cmd)
require.Error(t, result.Error())
result = cb.Execute(nil)
require.Error(t, result.Error())
}

View File

@ -4,38 +4,31 @@ import (
"errors" "errors"
"testing" "testing"
"github.com/golang/mock/gomock"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/status-im/status-go/services/wallet/thirdparty" "github.com/status-im/status-go/services/wallet/thirdparty"
mock_thirdparty "github.com/status-im/status-go/services/wallet/thirdparty/mock"
) )
type MockPriceProvider struct { type MockPriceProvider struct {
mock_thirdparty.MockMarketDataProvider
mockPrices map[string]map[string]float64 mockPrices map[string]map[string]float64
} }
func NewMockPriceProvider() *MockPriceProvider { func NewMockPriceProvider(ctrl *gomock.Controller) *MockPriceProvider {
return &MockPriceProvider{} return &MockPriceProvider{
MockMarketDataProvider: *mock_thirdparty.NewMockMarketDataProvider(ctrl),
}
} }
func (mpp *MockPriceProvider) setMockPrices(prices map[string]map[string]float64) { func (mpp *MockPriceProvider) setMockPrices(prices map[string]map[string]float64) {
mpp.mockPrices = prices mpp.mockPrices = prices
} }
func (mpp *MockPriceProvider) FetchHistoricalDailyPrices(symbol string, currency string, limit int, allData bool, aggregate int) ([]thirdparty.HistoricalPrice, error) {
return nil, errors.New("not implmented")
}
func (mpp *MockPriceProvider) FetchHistoricalHourlyPrices(symbol string, currency string, limit int, aggregate int) ([]thirdparty.HistoricalPrice, error) {
return nil, errors.New("not implmented")
}
func (mpp *MockPriceProvider) FetchTokenMarketValues(symbols []string, currency string) (map[string]thirdparty.TokenMarketValues, error) {
return nil, errors.New("not implmented")
}
func (mpp *MockPriceProvider) FetchTokenDetails(symbols []string) (map[string]thirdparty.TokenDetails, error) {
return nil, errors.New("not implmented")
}
func (mpp *MockPriceProvider) ID() string { func (mpp *MockPriceProvider) ID() string {
return "MockPriceProvider" return "MockPriceProvider"
} }
@ -85,7 +78,9 @@ var mockPrices = map[string]map[string]float64{
} }
func TestPrice(t *testing.T) { func TestPrice(t *testing.T) {
priceProvider := NewMockPriceProvider() ctrl := gomock.NewController(t)
defer ctrl.Finish()
priceProvider := NewMockPriceProvider(ctrl)
priceProvider.setMockPrices(mockPrices) priceProvider.setMockPrices(mockPrices)
manager := setupTestPrice(t, []thirdparty.MarketDataProvider{priceProvider, priceProvider}) manager := setupTestPrice(t, []thirdparty.MarketDataProvider{priceProvider, priceProvider})
@ -128,7 +123,9 @@ func TestPrice(t *testing.T) {
} }
func TestFetchPriceErrorFirstProvider(t *testing.T) { func TestFetchPriceErrorFirstProvider(t *testing.T) {
priceProvider := NewMockPriceProvider() ctrl := gomock.NewController(t)
defer ctrl.Finish()
priceProvider := NewMockPriceProvider(ctrl)
priceProvider.setMockPrices(mockPrices) priceProvider.setMockPrices(mockPrices)
priceProviderWithError := &MockPriceProviderWithError{} priceProviderWithError := &MockPriceProviderWithError{}
symbols := []string{"BTC", "ETH"} symbols := []string{"BTC", "ETH"}
@ -143,3 +140,46 @@ func TestFetchPriceErrorFirstProvider(t *testing.T) {
} }
} }
} }
func TestFetchTokenMarketValues(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
symbols := []string{"BTC", "ETH"}
currency := "EUR"
expectedMarketValues := map[string]thirdparty.TokenMarketValues{
"BTC": {
MKTCAP: 1000000000,
HIGHDAY: 1.23456,
LOWDAY: 1.00000,
CHANGEPCTHOUR: 0.1,
CHANGEPCTDAY: 0.2,
CHANGEPCT24HOUR: 0.3,
CHANGE24HOUR: 0.4,
},
"ETH": {
MKTCAP: 2000000000,
HIGHDAY: 4.56789,
LOWDAY: 4.00000,
CHANGEPCTHOUR: 0.5,
CHANGEPCTDAY: 0.6,
CHANGEPCT24HOUR: 0.7,
CHANGE24HOUR: 0.8,
},
}
// Can't use fake provider, because the key {receiver, method} will be different, no match
provider := mock_thirdparty.NewMockMarketDataProvider(ctrl)
provider.EXPECT().ID().Return("MockPriceProvider").AnyTimes()
provider.EXPECT().FetchTokenMarketValues(symbols, currency).Return(expectedMarketValues, nil)
manager := setupTestPrice(t, []thirdparty.MarketDataProvider{provider})
marketValues, err := manager.FetchTokenMarketValues(symbols, currency)
require.NoError(t, err)
require.Equal(t, expectedMarketValues, marketValues)
// Test error
provider.EXPECT().FetchTokenMarketValues(symbols, currency).Return(nil, errors.New("error"))
marketValues, err = manager.FetchTokenMarketValues(symbols, currency)
require.Error(t, err)
require.Nil(t, marketValues)
}

View File

@ -138,7 +138,7 @@ func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[
} }
for _, symbol := range smbls { for _, symbol := range smbls {
item[symbol] = container.Raw[utils.GetRealSymbol(symbol)][utils.GetRealSymbol(currency)] item[symbol] = container.Raw[utils.GetRealSymbol(symbol)][realCurrency]
} }
} }
return item, nil return item, nil

162
services/wallet/thirdparty/mock/types.go vendored Normal file
View File

@ -0,0 +1,162 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: services/wallet/thirdparty/types.go
// Package mock_thirdparty is a generated GoMock package.
package mock_thirdparty
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
thirdparty "github.com/status-im/status-go/services/wallet/thirdparty"
)
// MockMarketDataProvider is a mock of MarketDataProvider interface.
type MockMarketDataProvider struct {
ctrl *gomock.Controller
recorder *MockMarketDataProviderMockRecorder
}
// MockMarketDataProviderMockRecorder is the mock recorder for MockMarketDataProvider.
type MockMarketDataProviderMockRecorder struct {
mock *MockMarketDataProvider
}
// NewMockMarketDataProvider creates a new mock instance.
func NewMockMarketDataProvider(ctrl *gomock.Controller) *MockMarketDataProvider {
mock := &MockMarketDataProvider{ctrl: ctrl}
mock.recorder = &MockMarketDataProviderMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockMarketDataProvider) EXPECT() *MockMarketDataProviderMockRecorder {
return m.recorder
}
// FetchHistoricalDailyPrices mocks base method.
func (m *MockMarketDataProvider) FetchHistoricalDailyPrices(symbol, currency string, limit int, allData bool, aggregate int) ([]thirdparty.HistoricalPrice, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchHistoricalDailyPrices", symbol, currency, limit, allData, aggregate)
ret0, _ := ret[0].([]thirdparty.HistoricalPrice)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchHistoricalDailyPrices indicates an expected call of FetchHistoricalDailyPrices.
func (mr *MockMarketDataProviderMockRecorder) FetchHistoricalDailyPrices(symbol, currency, limit, allData, aggregate interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchHistoricalDailyPrices", reflect.TypeOf((*MockMarketDataProvider)(nil).FetchHistoricalDailyPrices), symbol, currency, limit, allData, aggregate)
}
// FetchHistoricalHourlyPrices mocks base method.
func (m *MockMarketDataProvider) FetchHistoricalHourlyPrices(symbol, currency string, limit, aggregate int) ([]thirdparty.HistoricalPrice, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchHistoricalHourlyPrices", symbol, currency, limit, aggregate)
ret0, _ := ret[0].([]thirdparty.HistoricalPrice)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchHistoricalHourlyPrices indicates an expected call of FetchHistoricalHourlyPrices.
func (mr *MockMarketDataProviderMockRecorder) FetchHistoricalHourlyPrices(symbol, currency, limit, aggregate interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchHistoricalHourlyPrices", reflect.TypeOf((*MockMarketDataProvider)(nil).FetchHistoricalHourlyPrices), symbol, currency, limit, aggregate)
}
// FetchPrices mocks base method.
func (m *MockMarketDataProvider) FetchPrices(symbols, currencies []string) (map[string]map[string]float64, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchPrices", symbols, currencies)
ret0, _ := ret[0].(map[string]map[string]float64)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchPrices indicates an expected call of FetchPrices.
func (mr *MockMarketDataProviderMockRecorder) FetchPrices(symbols, currencies interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchPrices", reflect.TypeOf((*MockMarketDataProvider)(nil).FetchPrices), symbols, currencies)
}
// FetchTokenDetails mocks base method.
func (m *MockMarketDataProvider) FetchTokenDetails(symbols []string) (map[string]thirdparty.TokenDetails, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchTokenDetails", symbols)
ret0, _ := ret[0].(map[string]thirdparty.TokenDetails)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchTokenDetails indicates an expected call of FetchTokenDetails.
func (mr *MockMarketDataProviderMockRecorder) FetchTokenDetails(symbols interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchTokenDetails", reflect.TypeOf((*MockMarketDataProvider)(nil).FetchTokenDetails), symbols)
}
// FetchTokenMarketValues mocks base method.
func (m *MockMarketDataProvider) FetchTokenMarketValues(symbols []string, currency string) (map[string]thirdparty.TokenMarketValues, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchTokenMarketValues", symbols, currency)
ret0, _ := ret[0].(map[string]thirdparty.TokenMarketValues)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchTokenMarketValues indicates an expected call of FetchTokenMarketValues.
func (mr *MockMarketDataProviderMockRecorder) FetchTokenMarketValues(symbols, currency interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchTokenMarketValues", reflect.TypeOf((*MockMarketDataProvider)(nil).FetchTokenMarketValues), symbols, currency)
}
// ID mocks base method.
func (m *MockMarketDataProvider) ID() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID")
ret0, _ := ret[0].(string)
return ret0
}
// ID indicates an expected call of ID.
func (mr *MockMarketDataProviderMockRecorder) ID() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockMarketDataProvider)(nil).ID))
}
// MockDecoderProvider is a mock of DecoderProvider interface.
type MockDecoderProvider struct {
ctrl *gomock.Controller
recorder *MockDecoderProviderMockRecorder
}
// MockDecoderProviderMockRecorder is the mock recorder for MockDecoderProvider.
type MockDecoderProviderMockRecorder struct {
mock *MockDecoderProvider
}
// NewMockDecoderProvider creates a new mock instance.
func NewMockDecoderProvider(ctrl *gomock.Controller) *MockDecoderProvider {
mock := &MockDecoderProvider{ctrl: ctrl}
mock.recorder = &MockDecoderProviderMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockDecoderProvider) EXPECT() *MockDecoderProviderMockRecorder {
return m.recorder
}
// Run mocks base method.
func (m *MockDecoderProvider) Run(data string) (*thirdparty.DataParsed, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Run", data)
ret0, _ := ret[0].(*thirdparty.DataParsed)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Run indicates an expected call of Run.
func (mr *MockDecoderProviderMockRecorder) Run(data interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockDecoderProvider)(nil).Run), data)
}