From 427f9c9d40c4732dabfb64481c1a466e48e47669 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Thu, 12 Sep 2019 17:27:07 +1000 Subject: [PATCH] Expand config test coverage --- config/config.go | 5 +- config/config_test.go | 323 +++++++++++++++++++++++++++++++++--------- 2 files changed, 259 insertions(+), 69 deletions(-) diff --git a/config/config.go b/config/config.go index 9446db63..34f679ed 100644 --- a/config/config.go +++ b/config/config.go @@ -873,12 +873,13 @@ func (c *Config) CheckExchangeConfigValues() error { c.Exchanges[i].AuthenticatedAPISupport = nil c.Exchanges[i].AuthenticatedWebsocketAPISupport = nil c.Exchanges[i].APIKey = nil - c.Exchanges[i].APIAuthPEMKey = nil c.Exchanges[i].APISecret = nil + c.Exchanges[i].ClientID = nil + c.Exchanges[i].APIAuthPEMKeySupport = nil + c.Exchanges[i].APIAuthPEMKey = nil c.Exchanges[i].APIURL = nil c.Exchanges[i].APIURLSecondary = nil c.Exchanges[i].WebsocketURL = nil - c.Exchanges[i].ClientID = nil } if c.Exchanges[i].Features == nil { diff --git a/config/config_test.go b/config/config_test.go index 9da4e113..17865bb3 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1173,111 +1173,300 @@ func TestUpdateExchangeConfig(t *testing.T) { // TestCheckExchangeConfigValues logic test func TestCheckExchangeConfigValues(t *testing.T) { - checkExchangeConfigValues := Config{} - err := checkExchangeConfigValues.LoadConfig(ConfigTestFile) + var cfg Config + err := cfg.LoadConfig(ConfigTestFile) if err != nil { - t.Errorf( - "Test failed. checkExchangeConfigValues.LoadConfig: %s", err.Error(), - ) - } - err = checkExchangeConfigValues.CheckExchangeConfigValues() - if err != nil { - t.Errorf( - "Test failed. checkExchangeConfigValues.CheckExchangeConfigValues: %s", - err.Error(), - ) + t.Fatal(err) } - checkExchangeConfigValues.Exchanges[0].Name = "GDAX" - err = checkExchangeConfigValues.CheckExchangeConfigValues() + // Test our default test config and report any errors + err = cfg.CheckExchangeConfigValues() if err != nil { - t.Errorf("Test failed. checkExchangeConfigValues.CheckExchangeConfigValues: %s", - err.Error(), - ) + t.Fatal(err) } - if checkExchangeConfigValues.Exchanges[0].Name != "CoinbasePro" { + + cfg.Exchanges[0].Name = "GDAX" + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + if cfg.Exchanges[0].Name != "CoinbasePro" { t.Error("exchange name should have been updated from GDAX to CoinbasePRo") } - checkExchangeConfigValues.Exchanges[0].WebsocketResponseMaxLimit = 0 - checkExchangeConfigValues.Exchanges[0].WebsocketResponseCheckTimeout = 0 - checkExchangeConfigValues.Exchanges[0].WebsocketOrderbookBufferLimit = 0 - checkExchangeConfigValues.Exchanges[0].HTTPTimeout = 0 - err = checkExchangeConfigValues.CheckExchangeConfigValues() + // Test API settings migration + sptr := func(s string) *string { return &s } + bptr := func(b bool) *bool { return &b } + int64ptr := func(i int64) *int64 { return &i } + + cfg.Exchanges[0].APIKey = sptr("awesomeKey") + cfg.Exchanges[0].APISecret = sptr("meowSecret") + cfg.Exchanges[0].ClientID = sptr("clientIDerino") + cfg.Exchanges[0].APIAuthPEMKey = sptr("-----BEGIN EC PRIVATE KEY-----\nASDF\n-----END EC PRIVATE KEY-----\n") + cfg.Exchanges[0].APIAuthPEMKeySupport = bptr(true) + cfg.Exchanges[0].AuthenticatedAPISupport = bptr(true) + cfg.Exchanges[0].AuthenticatedWebsocketAPISupport = bptr(true) + cfg.Exchanges[0].WebsocketURL = sptr("wss://1337") + cfg.Exchanges[0].APIURL = sptr(APIURLNonDefaultMessage) + cfg.Exchanges[0].APIURLSecondary = sptr(APIURLNonDefaultMessage) + err = cfg.CheckExchangeConfigValues() if err != nil { - t.Errorf("Test failed. checkExchangeConfigValues.CheckExchangeConfigValues: %s", - err.Error(), - ) + t.Error(err) } - if checkExchangeConfigValues.Exchanges[0].WebsocketResponseMaxLimit == 0 { - t.Fatalf("Test failed. Expected exchange %s to have updated WebsocketResponseMaxLimit value", checkExchangeConfigValues.Exchanges[0].Name) + // Ensure that all of our previous settings are migrated + if cfg.Exchanges[0].API.Credentials.Key != "awesomeKey" || + cfg.Exchanges[0].API.Credentials.Secret != "meowSecret" || + cfg.Exchanges[0].API.Credentials.ClientID != "clientIDerino" || + !strings.Contains(cfg.Exchanges[0].API.Credentials.PEMKey, "ASDF") || + !cfg.Exchanges[0].API.PEMKeySupport || + !cfg.Exchanges[0].API.AuthenticatedSupport || + !cfg.Exchanges[0].API.AuthenticatedWebsocketSupport || + cfg.Exchanges[0].API.Endpoints.WebsocketURL != "wss://1337" || + cfg.Exchanges[0].API.Endpoints.URL != APIURLNonDefaultMessage || + cfg.Exchanges[0].API.Endpoints.URLSecondary != APIURLNonDefaultMessage { + t.Error("unexpected values") } - if checkExchangeConfigValues.Exchanges[0].WebsocketOrderbookBufferLimit == 0 { - t.Fatalf("Test failed. Expected exchange %s to have updated WebsocketOrderbookBufferLimit value", checkExchangeConfigValues.Exchanges[0].Name) + if cfg.Exchanges[0].APIKey != nil || + cfg.Exchanges[0].APISecret != nil || + cfg.Exchanges[0].ClientID != nil || + cfg.Exchanges[0].APIAuthPEMKey != nil || + cfg.Exchanges[0].APIAuthPEMKeySupport != nil || + cfg.Exchanges[0].AuthenticatedAPISupport != nil || + cfg.Exchanges[0].AuthenticatedWebsocketAPISupport != nil || + cfg.Exchanges[0].WebsocketURL != nil || + cfg.Exchanges[0].APIURL != nil || + cfg.Exchanges[0].APIURLSecondary != nil { + t.Error("unexpected values") } - if checkExchangeConfigValues.Exchanges[0].HTTPTimeout == 0 { - t.Fatalf("Test failed. Expected exchange %s to have updated HTTPTimeout value", checkExchangeConfigValues.Exchanges[0].Name) + // Test feature and endpoint migrations migrations + cfg.Exchanges[0].Features = nil + cfg.Exchanges[0].SupportsAutoPairUpdates = bptr(true) + cfg.Exchanges[0].Websocket = bptr(true) + cfg.Exchanges[0].API.Endpoints.URL = "" + cfg.Exchanges[0].API.Endpoints.URLSecondary = "" + cfg.Exchanges[0].API.Endpoints.WebsocketURL = "" + + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + + if !cfg.Exchanges[0].Features.Enabled.AutoPairUpdates || + !cfg.Exchanges[0].Features.Enabled.Websocket || + !cfg.Exchanges[0].Features.Supports.RESTCapabilities.AutoPairUpdates { + t.Error("unexpected values") + } + + if cfg.Exchanges[0].API.Endpoints.URL != APIURLNonDefaultMessage || + cfg.Exchanges[0].API.Endpoints.URLSecondary != APIURLNonDefaultMessage || + cfg.Exchanges[0].API.Endpoints.WebsocketURL != WebsocketURLNonDefaultMessage { + t.Error("unexpected values") + } + + // Test currency pair migration + setupPairs := func(emptyAssets bool) { + cfg.Exchanges[0].CurrencyPairs = nil + p := currency.Pairs{ + currency.NewPairDelimiter("BTC-USD", "-"), + } + cfg.Exchanges[0].PairsLastUpdated = int64ptr(1234567) + + if !emptyAssets { + cfg.Exchanges[0].AssetTypes = sptr("spot") + } + + cfg.Exchanges[0].AvailablePairs = &p + cfg.Exchanges[0].EnabledPairs = &p + cfg.Exchanges[0].ConfigCurrencyPairFormat = ¤cy.PairFormat{ + Uppercase: true, + Delimiter: "-", + } + cfg.Exchanges[0].RequestCurrencyPairFormat = ¤cy.PairFormat{ + Uppercase: false, + Delimiter: "~", + } + } + + setupPairs(false) + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + + setupPairs(true) + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + + if cfg.Exchanges[0].CurrencyPairs.LastUpdated != 1234567 { + t.Error("last updated has wrong value") + } + + pFmt := cfg.Exchanges[0].CurrencyPairs.ConfigFormat + if pFmt.Delimiter != "-" || + !pFmt.Uppercase { + t.Error("unexpected config format values") + } + + pFmt = cfg.Exchanges[0].CurrencyPairs.RequestFormat + if pFmt.Delimiter != "~" || + pFmt.Uppercase { + t.Error("unexpected request format values") + } + + if cfg.Exchanges[0].CurrencyPairs.AssetTypes.JoinToString(",") != "spot" || + !cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat { + t.Error("unexpected results") + } + + pairs := cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, true) + if len(pairs) == 0 || pairs.Join() != "BTC-USD" { + t.Error("pairs not set properly") + } + + pairs = cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, false) + if len(pairs) == 0 || pairs.Join() != "BTC-USD" { + t.Error("pairs not set properly") + } + + // Ensure that all old settings are flushed + if cfg.Exchanges[0].PairsLastUpdated != nil || + cfg.Exchanges[0].ConfigCurrencyPairFormat != nil || + cfg.Exchanges[0].RequestCurrencyPairFormat != nil || + cfg.Exchanges[0].AssetTypes != nil || + cfg.Exchanges[0].AvailablePairs != nil || + cfg.Exchanges[0].EnabledPairs != nil { + t.Error("unexpected results") + } + + // Test AutoPairUpdates + cfg.Exchanges[0].Features.Supports.RESTCapabilities.AutoPairUpdates = false + cfg.Exchanges[0].Features.Supports.WebsocketCapabilities.AutoPairUpdates = false + cfg.Exchanges[0].CurrencyPairs.LastUpdated = 0 + cfg.CheckExchangeConfigValues() + + // Test HTTP rate limiter negative values + cfg.Exchanges[0].HTTPRateLimiter = &HTTPRateLimitConfig{ + Unauthenticated: HTTPRateConfig{ + Duration: -1, + Rate: -1, + }, + Authenticated: HTTPRateConfig{ + Duration: -1, + Rate: -1, + }, + } + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + + if cfg.Exchanges[0].HTTPRateLimiter.Authenticated.Duration != 0 || + cfg.Exchanges[0].HTTPRateLimiter.Authenticated.Rate != 0 || + cfg.Exchanges[0].HTTPRateLimiter.Unauthenticated.Duration != 0 || + cfg.Exchanges[0].HTTPRateLimiter.Unauthenticated.Rate != 0 { + t.Error("unexpected results") + } + + // Test exchange pair consistency error + cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat = false + backup := cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot] + cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot] = nil + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + if cfg.Exchanges[0].Enabled { + t.Error("exchange should have been disabled") + } + + // Restore to previous state + cfg.Exchanges[0].Enabled = true + cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat = true + cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot] = backup + + // Test websocket and HTTP timeout values + cfg.Exchanges[0].WebsocketResponseMaxLimit = 0 + cfg.Exchanges[0].WebsocketResponseCheckTimeout = 0 + cfg.Exchanges[0].WebsocketOrderbookBufferLimit = 0 + cfg.Exchanges[0].HTTPTimeout = 0 + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } + + if cfg.Exchanges[0].WebsocketResponseMaxLimit == 0 { + t.Errorf("expected exchange %s to have updated WebsocketResponseMaxLimit value", + cfg.Exchanges[0].Name) + } + if cfg.Exchanges[0].WebsocketOrderbookBufferLimit == 0 { + t.Errorf("expected exchange %s to have updated WebsocketOrderbookBufferLimit value", + cfg.Exchanges[0].Name) + } + if cfg.Exchanges[0].HTTPTimeout == 0 { + t.Errorf("expected exchange %s to have updated HTTPTimeout value", + cfg.Exchanges[0].Name) } v := &APICredentialsValidatorConfig{ RequiresKey: true, RequiresSecret: true, } - checkExchangeConfigValues.Exchanges[0].API.CredentialsValidator = v - checkExchangeConfigValues.Exchanges[0].API.Credentials.Key = "Key" - checkExchangeConfigValues.Exchanges[0].API.Credentials.Secret = "Secret" - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport = true - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport = true - checkExchangeConfigValues.CheckExchangeConfigValues() - if checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport || - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport { + cfg.Exchanges[0].API.CredentialsValidator = v + cfg.Exchanges[0].API.Credentials.Key = "Key" + cfg.Exchanges[0].API.Credentials.Secret = "Secret" + cfg.Exchanges[0].API.AuthenticatedSupport = true + cfg.Exchanges[0].API.AuthenticatedWebsocketSupport = true + cfg.CheckExchangeConfigValues() + if cfg.Exchanges[0].API.AuthenticatedSupport || + cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected authenticated endpoints to be false from invalid API keys") } v.RequiresKey = false v.RequiresClientID = true - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport = true - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport = true - checkExchangeConfigValues.Exchanges[0].API.Credentials.ClientID = DefaultAPIClientID - checkExchangeConfigValues.Exchanges[0].API.Credentials.Secret = "TESTYTEST" - checkExchangeConfigValues.CheckExchangeConfigValues() - if checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport || - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport { + cfg.Exchanges[0].API.AuthenticatedSupport = true + cfg.Exchanges[0].API.AuthenticatedWebsocketSupport = true + cfg.Exchanges[0].API.Credentials.ClientID = DefaultAPIClientID + cfg.Exchanges[0].API.Credentials.Secret = "TESTYTEST" + cfg.CheckExchangeConfigValues() + if cfg.Exchanges[0].API.AuthenticatedSupport || + cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected AuthenticatedAPISupport to be false from invalid API keys") } v.RequiresKey = true - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport = true - checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport = true - checkExchangeConfigValues.Exchanges[0].API.Credentials.Key = "meow" - checkExchangeConfigValues.Exchanges[0].API.Credentials.Secret = "test123" - checkExchangeConfigValues.Exchanges[0].API.Credentials.ClientID = "clientIDerino" - checkExchangeConfigValues.CheckExchangeConfigValues() - if !checkExchangeConfigValues.Exchanges[0].API.AuthenticatedSupport || - !checkExchangeConfigValues.Exchanges[0].API.AuthenticatedWebsocketSupport { + cfg.Exchanges[0].API.AuthenticatedSupport = true + cfg.Exchanges[0].API.AuthenticatedWebsocketSupport = true + cfg.Exchanges[0].API.Credentials.Key = "meow" + cfg.Exchanges[0].API.Credentials.Secret = "test123" + cfg.Exchanges[0].API.Credentials.ClientID = "clientIDerino" + cfg.CheckExchangeConfigValues() + if !cfg.Exchanges[0].API.AuthenticatedSupport || + !cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected AuthenticatedAPISupport and AuthenticatedWebsocketAPISupport to be false from invalid API keys") } - checkExchangeConfigValues.Exchanges[0].Enabled = true - checkExchangeConfigValues.Exchanges[0].Name = "" - checkExchangeConfigValues.CheckExchangeConfigValues() - if checkExchangeConfigValues.Exchanges[0].Enabled { + // Test empty exchange name for an enabled exchange + cfg.Exchanges[0].Enabled = true + cfg.Exchanges[0].Name = "" + cfg.CheckExchangeConfigValues() + if cfg.Exchanges[0].Enabled { t.Errorf( - "Test failed. checkExchangeConfigValues.CheckExchangeConfigValues Error", + "Test failed. Exchange with no name should be empty", ) } - checkExchangeConfigValues.Exchanges = checkExchangeConfigValues.Exchanges[:0] - cryptos := currency.NewCurrenciesFromStringArray([]string{"TESTYTEST"}) - checkExchangeConfigValues.Cryptocurrencies = &cryptos - err = checkExchangeConfigValues.CheckExchangeConfigValues() + // Test no enabled exchanges + cfg.Exchanges = cfg.Exchanges[:1] + cfg.Exchanges[0].Enabled = false + err = cfg.CheckExchangeConfigValues() if err == nil { - t.Errorf( - "Test failed. checkExchangeConfigValues.CheckExchangeConfigValues Error", - ) + t.Error("no enabled exchanges should throw an error") } }