Increase exchange.go test coverage to 100%

This commit is contained in:
Adrian Gallagher
2019-10-01 16:12:49 +10:00
parent 6951b4c342
commit 580190638c
2 changed files with 386 additions and 81 deletions

View File

@@ -79,11 +79,9 @@ func (e *Base) SetClientProxyAddress(addr string) error {
err)
}
err = e.Requester.SetProxy(proxy)
if err != nil {
return fmt.Errorf("exchange.go - setting proxy address error %s",
err)
}
// No needs to check err here as the only err condition is an empty
// string which is already checked above
e.Requester.SetProxy(proxy)
if e.Websocket != nil {
err = e.Websocket.SetProxyAddress(addr)
@@ -253,12 +251,10 @@ func (e *Base) SetCurrencyPairFormat() {
}
e.Config.CurrencyPairs.UseGlobalFormat = e.CurrencyPairs.UseGlobalFormat
if e.Config.CurrencyPairs.UseGlobalFormat {
if e.Config.CurrencyPairs.ConfigFormat == nil {
e.Config.CurrencyPairs.ConfigFormat = e.CurrencyPairs.ConfigFormat
}
if e.Config.CurrencyPairs.RequestFormat == nil {
e.Config.CurrencyPairs.RequestFormat = e.CurrencyPairs.RequestFormat
}
@@ -268,7 +264,6 @@ func (e *Base) SetCurrencyPairFormat() {
if e.Config.CurrencyPairs.ConfigFormat != nil {
e.Config.CurrencyPairs.ConfigFormat = nil
}
if e.Config.CurrencyPairs.RequestFormat != nil {
e.Config.CurrencyPairs.RequestFormat = nil
}
@@ -401,6 +396,7 @@ func (e *Base) SetAPIKeys(apiKey, apiSecret, clientID string) {
e.API.AuthenticatedSupport = false
e.API.AuthenticatedWebsocketSupport = false
log.Warnf(log.ExchangeSys, warningBase64DecryptSecretKeyFailed, e.Name)
return
}
e.API.Credentials.Secret = string(result)
} else {

View File

@@ -115,11 +115,122 @@ func TestSetClientProxyAddress(t *testing.T) {
t.Error("Test failed. SetClientProxyAddress error", err)
}
// calling this again will cause the ws check to fail
err = newBase.SetClientProxyAddress("www.valid.com")
if err == nil {
t.Error("trying to set the same proxy addr should thrown an err for ws")
}
if newBase.Websocket.GetProxyAddress() != "www.valid.com" {
t.Error("Test failed. SetClientProxyAddress error", err)
}
}
func TestSetFeatureDefaults(t *testing.T) {
t.Parallel()
// Test nil features with basic support capabilities
b := Base{
Config: &config.ExchangeConfig{
CurrencyPairs: &currency.PairsManager{},
},
Features: Features{
Supports: FeaturesSupported{
REST: true,
RESTCapabilities: ProtocolFeatures{
TickerBatching: true,
},
Websocket: true,
},
},
}
b.SetFeatureDefaults()
if !b.Config.Features.Supports.REST && b.Config.CurrencyPairs.LastUpdated == 0 {
t.Error("incorrect values")
}
// Test upgrade when SupportsAutoPairUpdates is enabled
bptr := func(a bool) *bool { return &a }
b.Config.Features = nil
b.Config.SupportsAutoPairUpdates = bptr(true)
b.SetFeatureDefaults()
if !b.Config.Features.Supports.RESTCapabilities.AutoPairUpdates &&
!b.Features.Enabled.AutoPairUpdates {
t.Error("incorrect values")
}
// Test non migrated features config
b.Config.Features.Supports.REST = false
b.Config.Features.Supports.RESTCapabilities.TickerBatching = false
b.Config.Features.Supports.Websocket = false
b.SetFeatureDefaults()
if !b.Features.Supports.REST ||
!b.Features.Supports.RESTCapabilities.TickerBatching ||
!b.Features.Supports.Websocket {
t.Error("incorrect values")
}
}
func TestSetAPICredentialDefaults(t *testing.T) {
t.Parallel()
b := Base{
Config: &config.ExchangeConfig{},
}
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
b.API.CredentialsValidator.RequiresBase64DecodeSecret = true
b.API.CredentialsValidator.RequiresClientID = true
b.API.CredentialsValidator.RequiresPEM = true
b.SetAPICredentialDefaults()
if !b.Config.API.CredentialsValidator.RequiresKey ||
!b.Config.API.CredentialsValidator.RequiresSecret ||
!b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret ||
!b.Config.API.CredentialsValidator.RequiresClientID ||
!b.Config.API.CredentialsValidator.RequiresPEM {
t.Error("incorrect values")
}
}
func TestSetHTTPRateLimiter(t *testing.T) {
t.Parallel()
b := Base{
Config: &config.ExchangeConfig{},
Requester: request.New("asdf",
request.NewRateLimit(time.Second*5, 10),
request.NewRateLimit(time.Second*10, 15),
common.NewHTTPClientWithTimeout(DefaultHTTPTimeout)),
}
b.SetHTTPRateLimiter()
if b.Requester.GetRateLimit(true).Duration.String() != "5s" &&
b.Requester.GetRateLimit(true).Rate != 10 &&
b.Requester.GetRateLimit(false).Duration.String() != "10s" &&
b.Requester.GetRateLimit(false).Rate != 15 {
t.Error("rate limiter not set properly")
}
b.Config.HTTPRateLimiter = &config.HTTPRateLimitConfig{
Unauthenticated: config.HTTPRateConfig{
Duration: time.Second * 100,
Rate: 100,
},
Authenticated: config.HTTPRateConfig{
Duration: time.Second * 110,
Rate: 150,
},
}
b.SetHTTPRateLimiter()
if b.Requester.GetRateLimit(true).Duration.String() != "1m50s" &&
b.Requester.GetRateLimit(true).Rate != 150 &&
b.Requester.GetRateLimit(false).Duration.String() != "1m40s" &&
b.Requester.GetRateLimit(false).Rate != 100 {
t.Error("rate limiter not set properly")
}
}
func TestSetAutoPairDefaults(t *testing.T) {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigTestFile, true)
@@ -183,42 +294,33 @@ func TestGetLastPairsUpdateTime(t *testing.T) {
}
func TestSetAssetTypes(t *testing.T) {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigTestFile, true)
if err != nil {
t.Fatalf("Test failed. TestSetAssetTypes failed to load config file. Error: %s", err)
}
t.Parallel()
b := Base{
Name: "TESTNAME",
Config: &config.ExchangeConfig{
CurrencyPairs: &currency.PairsManager{},
},
CurrencyPairs: currency.PairsManager{
AssetTypes: asset.Items{
asset.Spot,
asset.Binary,
asset.Futures,
},
},
}
b.Name = "ANX"
b.CurrencyPairs.AssetTypes = asset.Items{asset.Spot}
exch, err := cfg.GetExchangeConfig(b.Name)
if err != nil {
t.Fatalf("Test failed. TestSetAssetTypes load config failed. Error %s", err)
}
exch.CurrencyPairs.AssetTypes = asset.New("")
err = cfg.UpdateExchangeConfig(exch)
if err != nil {
t.Fatalf("Test failed. TestSetAssetTypes update config failed. Error %s", err)
}
exch, err = cfg.GetExchangeConfig(b.Name)
if err != nil {
t.Fatalf("Test failed. TestSetAssetTypes load config failed. Error %s", err)
}
b.Config = exch
if exch.CurrencyPairs.AssetTypes.JoinToString(",") != "" {
t.Fatal("Test failed. TestSetAssetTypes assetTypes != ''")
}
b.SetAssetTypes()
if !common.StringDataCompare(b.CurrencyPairs.AssetTypes.Strings(), asset.Spot.String()) {
t.Fatal("Test failed. TestSetAssetTypes assetTypes is not set")
if len(b.GetAssetTypes()) != 3 {
t.Error("incorrect assets len")
}
b.CurrencyPairs.AssetTypes = append(b.CurrencyPairs.AssetTypes,
asset.PerpetualSwap)
b.Config.CurrencyPairs.AssetTypes = asset.Items{
asset.Index,
}
b.SetAssetTypes()
if len(b.GetAssetTypes()) != 4 {
t.Error("incorrect assets len")
}
}
@@ -241,49 +343,99 @@ func TestGetAssetTypes(t *testing.T) {
}
}
func TestSetCurrencyPairFormat(t *testing.T) {
t.Skip()
// TO-DO
func TestGetClientBankAccounts(t *testing.T) {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigTestFile, true)
if err != nil {
t.Fatalf("Test failed. TestSetCurrencyPairFormat failed to load config file. Error: %s", err)
t.Fatal(err)
}
var b Base
var r config.BankAccount
r, err = b.GetClientBankAccounts("Kraken", "USD")
if err != nil {
t.Error(err)
}
if r.BankName != "test" {
t.Error("incorrect bank name")
}
r, err = b.GetClientBankAccounts("MEOW", "USD")
if err == nil {
t.Error("an error should of been thrown for a non-existent exchange")
}
}
func TestGetExchangeBankAccounts(t *testing.T) {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigTestFile, true)
if err != nil {
t.Fatal(err)
}
var b Base
var r config.BankAccount
r, err = b.GetExchangeBankAccounts("Bitfinex", "USD")
if err != nil {
t.Error(err)
}
if r.BankName != "Deutsche Bank Privat Und Geschaeftskunden AG" {
t.Error("incorrect bank name")
}
_, err = b.GetExchangeBankAccounts("MEOW", "USD")
if err == nil {
t.Error("an error should of been thrown for a non-existent exchange")
}
}
func TestSetCurrencyPairFormat(t *testing.T) {
t.Parallel()
b := Base{
Name: "TESTNAME",
Config: &config.ExchangeConfig{},
}
b.Name = "ANX"
exch, err := cfg.GetExchangeConfig(b.Name)
if err != nil {
t.Fatalf("Test failed. TestSetCurrencyPairFormat load config failed. Error %s", err)
}
b.Config = exch
b.SetCurrencyPairFormat()
if exch.CurrencyPairs.Get(asset.Spot).ConfigFormat.Delimiter != "-" && !exch.CurrencyPairs.ConfigFormat.Uppercase {
t.Fatal("Test failed. TestSetCurrencyPairFormat exch values are not nil")
if b.Config.CurrencyPairs == nil {
t.Error("CurrencyPairs shouldn't be nil")
}
exch.CurrencyPairs.ConfigFormat = nil
exch.CurrencyPairs.RequestFormat = nil
err = cfg.UpdateExchangeConfig(exch)
if err != nil {
t.Fatalf("Test failed. TestSetCurrencyPairFormat update config failed. Error %s", err)
// Test global format logic
b.Config.CurrencyPairs.UseGlobalFormat = true
b.CurrencyPairs.UseGlobalFormat = true
pFmt := &currency.PairFormat{
Delimiter: "#",
}
exch, err = cfg.GetExchangeConfig(b.Name)
if err != nil {
t.Fatalf("Test failed. TestSetCurrencyPairFormat load config failed. Error %s", err)
}
if exch.CurrencyPairs.ConfigFormat != nil && exch.CurrencyPairs.RequestFormat != nil {
t.Fatal("Test failed. TestSetCurrencyPairFormat exch values are not nil")
}
b.CurrencyPairs.RequestFormat = pFmt
b.CurrencyPairs.ConfigFormat = pFmt
b.SetCurrencyPairFormat()
if exch.CurrencyPairs.Get(asset.Spot).ConfigFormat.Delimiter != "-" && !exch.CurrencyPairs.ConfigFormat.Uppercase {
t.Fatal("Test failed. TestSetCurrencyPairFormat exch values are not nil")
if b.GetPairFormat(asset.Spot, true).Delimiter != "#" {
t.Error("incorrect pair format delimiter")
}
// Test individual asset type formatting logic
b.CurrencyPairs.UseGlobalFormat = false
// This will generate a nil pair store
b.CurrencyPairs.AssetTypes = asset.Items{asset.Index}
// Store non-nil pair stores
b.CurrencyPairs.Store(asset.Spot, currency.PairStore{
ConfigFormat: &currency.PairFormat{
Delimiter: "~",
},
})
b.CurrencyPairs.Store(asset.Futures, currency.PairStore{
ConfigFormat: &currency.PairFormat{
Delimiter: ":)",
},
})
b.SetCurrencyPairFormat()
if b.GetPairFormat(asset.Spot, false).Delimiter != "~" {
t.Error("incorrect pair format delimiter")
}
if b.GetPairFormat(asset.Futures, false).Delimiter != ":)" {
t.Error("incorrect pair format delimiter")
}
}
@@ -316,16 +468,79 @@ func TestGetAuthenticatedAPISupport(t *testing.T) {
func TestGetName(t *testing.T) {
t.Parallel()
GetName := Base{
b := Base{
Name: "TESTNAME",
}
name := GetName.GetName()
name := b.GetName()
if name != "TESTNAME" {
t.Error("Test Failed - Exchange GetName() returned incorrect name")
}
}
func TestGetFeatures(t *testing.T) {
t.Parallel()
// Test GetEnabledFeatures
var b Base
if b.GetEnabledFeatures().AutoPairUpdates {
t.Error("auto pair updates should be disabled")
}
b.Features.Enabled.AutoPairUpdates = true
if !b.GetEnabledFeatures().AutoPairUpdates {
t.Error("auto pair updates should be enabled")
}
// Test GetSupportedFeatures
b.Features.Supports.RESTCapabilities.AutoPairUpdates = true
if !b.GetSupportedFeatures().RESTCapabilities.AutoPairUpdates {
t.Error("auto pair updates should be supported")
}
if b.GetSupportedFeatures().RESTCapabilities.TickerBatching {
t.Error("ticker batching shouldn't be supported")
}
}
func TestGetPairFormat(t *testing.T) {
t.Parallel()
// Test global formatting
var b Base
b.CurrencyPairs.UseGlobalFormat = true
b.CurrencyPairs.ConfigFormat = &currency.PairFormat{
Uppercase: true,
}
b.CurrencyPairs.RequestFormat = &currency.PairFormat{
Delimiter: "~",
}
pFmt := b.GetPairFormat(asset.Spot, true)
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
t.Error("incorrect pair format values")
}
pFmt = b.GetPairFormat(asset.Spot, false)
if pFmt.Delimiter != "" && pFmt.Uppercase {
t.Error("incorrect pair format values")
}
// Test individual asset pair store formatting
b.CurrencyPairs.UseGlobalFormat = false
b.CurrencyPairs.Store(asset.Spot, currency.PairStore{
ConfigFormat: &pFmt,
RequestFormat: &currency.PairFormat{
Delimiter: "/",
Uppercase: true,
},
})
pFmt = b.GetPairFormat(asset.Spot, false)
if pFmt.Delimiter != "" && pFmt.Uppercase {
t.Error("incorrect pair format values")
}
pFmt = b.GetPairFormat(asset.Spot, true)
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
t.Error("incorrect pair format values")
}
}
func TestGetEnabledPairs(t *testing.T) {
t.Parallel()
@@ -606,7 +821,7 @@ func TestIsEnabled(t *testing.T) {
func TestSetAPIKeys(t *testing.T) {
t.Parallel()
SetAPIKeys := Base{
b := Base{
Name: "TESTNAME",
Enabled: false,
API: API{
@@ -615,9 +830,80 @@ func TestSetAPIKeys(t *testing.T) {
},
}
SetAPIKeys.SetAPIKeys("RocketMan", "Digereedoo", "007")
if SetAPIKeys.API.Credentials.Key != "RocketMan" && SetAPIKeys.API.Credentials.Secret != "Digereedoo" && SetAPIKeys.API.Credentials.ClientID != "007" {
t.Error("Test Failed - SetAPIKeys() unable to set API credentials")
b.SetAPIKeys("RocketMan", "Digereedoo", "007")
if b.API.Credentials.Key != "RocketMan" && b.API.Credentials.Secret != "Digereedoo" && b.API.Credentials.ClientID != "007" {
t.Error("invalid API credentials")
}
// Invalid secret
b.API.CredentialsValidator.RequiresBase64DecodeSecret = true
b.API.AuthenticatedSupport = true
b.SetAPIKeys("RocketMan", "%%", "007")
if b.API.AuthenticatedSupport || b.API.AuthenticatedWebsocketSupport {
t.Error("invalid secret should disable authenticated API support")
}
// valid secret
b.API.CredentialsValidator.RequiresBase64DecodeSecret = true
b.API.AuthenticatedSupport = true
b.SetAPIKeys("RocketMan", "aGVsbG8gd29ybGQ=", "007")
if !b.API.AuthenticatedSupport && b.API.Credentials.Secret != "hello world" {
t.Error("invalid secret should disable authenticated API support")
}
}
func TestSetupDefaults(t *testing.T) {
t.Parallel()
var b Base
cfg := config.ExchangeConfig{
HTTPTimeout: time.Duration(-1),
API: config.APIConfig{
AuthenticatedSupport: true,
},
}
if err := b.SetupDefaults(&cfg); err != nil {
t.Error(err)
}
if cfg.HTTPTimeout.String() != "15s" {
t.Error("HTTP timeout should be set to 15s")
}
// Test custom HTTP timeout is set
cfg.HTTPTimeout = time.Second * 30
if err := b.SetupDefaults(&cfg); err != nil {
t.Error(err)
}
if cfg.HTTPTimeout.String() != "30s" {
t.Error("HTTP timeout should be set to 30s")
}
// Test asset types
p := currency.NewPairDelimiter(defaultTestCurrencyPair, "-")
b.CurrencyPairs.Store(asset.Spot,
currency.PairStore{
Enabled: currency.Pairs{
p,
},
},
)
if err := b.SetupDefaults(&cfg); err != nil {
t.Error(err)
}
ps := cfg.CurrencyPairs.Get(asset.Spot)
if !ps.Enabled.Contains(p, true) {
t.Error("default pair should be stored in the configs pair store")
}
// Test websocket support
b.Websocket = wshandler.New()
b.Features.Supports.Websocket = true
if err := b.SetupDefaults(&cfg); err != nil {
t.Error(err)
}
b.Websocket.Setup(nil, nil, nil, "", true, false, "", "", false)
if !b.IsWebsocketEnabled() {
t.Error("websocket should be enabled")
}
}
@@ -628,16 +914,39 @@ func TestAllowAuthenticatedRequest(t *testing.T) {
SkipAuthCheck: true,
}
// Test SkipAuthCheck
if r := b.AllowAuthenticatedRequest(); !r {
t.Error("skip auth check should allow authenticated requests")
}
// Test credentials failure
b.SkipAuthCheck = false
b.API.CredentialsValidator.RequiresKey = true
if r := b.AllowAuthenticatedRequest(); r {
t.Error("should fail with an empty key")
}
// Test bot usage with authenticated API support disabled, but with
// valid credentials
b.LoadedByConfig = true
b.API.Credentials.Key = "k3y"
if r := b.AllowAuthenticatedRequest(); r {
t.Error("should fail when authenticated support is disabled")
}
// Test enabled authenticated API support and loaded by config
// but invalid credentials
b.API.AuthenticatedSupport = true
b.API.Credentials.Key = ""
if r := b.AllowAuthenticatedRequest(); r {
t.Error("should fail with invalid credentials")
}
// Finally a valid one
b.API.Credentials.Key = "k3y"
if r := b.AllowAuthenticatedRequest(); !r {
t.Error("show allow an authenticated request")
}
}
func TestValidateAPICredentials(t *testing.T) {
@@ -742,12 +1051,12 @@ func TestUpdatePairs(t *testing.T) {
t.Fatal("Test failed. TestUpdatePairs failed to load config")
}
anxCfg, err := cfg.GetExchangeConfig("ANX")
anxCfg, err := cfg.GetExchangeConfig(defaultTestExchange)
if err != nil {
t.Fatal("Test failed. TestUpdatePairs failed to load config")
}
UAC := Base{Name: "ANX"}
UAC := Base{Name: defaultTestExchange}
UAC.Config = anxCfg
exchangeProducts := currency.NewPairsFromStrings([]string{"ltc", "btc", "usd", "aud", ""})
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, true, false)
@@ -770,7 +1079,7 @@ func TestUpdatePairs(t *testing.T) {
// Test updating exchange products
exchangeProducts = currency.NewPairsFromStrings([]string{"ltc", "btc", "usd", "aud"})
UAC.Name = "ANX"
UAC.Name = defaultTestExchange
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, false)
if err != nil {
t.Errorf("Test Failed - Exchange UpdatePairs() error: %s", err)
@@ -965,7 +1274,7 @@ func TestSupportsWithdrawPermissions(t *testing.T) {
func TestFormatWithdrawPermissions(t *testing.T) {
t.Parallel()
UAC := Base{Name: "ANX"}
UAC := Base{Name: defaultTestExchange}
UAC.Features.Supports.WithdrawPermissions = AutoWithdrawCrypto |
AutoWithdrawCryptoWithAPIPermission |
AutoWithdrawCryptoWithSetup |