From 63257ce4ca99604965279a3a6dd9c425877488f7 Mon Sep 17 00:00:00 2001 From: Scott Date: Wed, 7 Jul 2021 12:42:03 +1000 Subject: [PATCH] Improvement: Speeding up slow tests (#707) * Speeds up tests * Reduces time.Sleeps, lowers CreateTestBot complexity. Breaks things * Removal of unecessary config reads. Parallel tests. Lower times * Speeds up recent trades results * mini update * zoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooom * Removes the dupes * Lint * post cherrypick * Fix rare kraken data race * Fixes banking global issues. Fixes postgres trades * rmline for appveyor test * Expands timeout in event that channel is closed before send * Fix data race * No rows, no bows and definitely no shows * Removes parallel from createsnapshot tests * Extends timedmutext test a smidge. Exchange fatality * Shorter end timeframe and bigger candle --- backtester/backtest/backtest.go | 73 ++- backtester/backtest/backtest_test.go | 402 ++++++++---- backtester/backtest/backtest_types.go | 2 + backtester/data/kline/api/api_test.go | 82 ++- backtester/data/kline/live/live.go | 6 +- backtester/data/kline/live/live_test.go | 76 +-- .../eventhandlers/exchange/exchange_test.go | 69 +- common/timedmutex/timed_mutex_test.go | 17 +- communications/slack/slack_test.go | 49 +- communications/smsglobal/smsglobal_test.go | 71 +- .../smtpservice/smtpservice_test.go | 7 +- communications/telegram/telegram_test.go | 26 +- config/config.go | 2 +- config/config_encryption_test.go | 20 +- config/config_test.go | 619 +++++++++++------- database/database.go | 2 +- database/database_test.go | 4 +- database/database_types.go | 7 +- database/drivers/postgres/postgres.go | 6 + database/repository/audit/audit_test.go | 3 - .../datahistoryjob/datahistoryjob_test.go | 10 +- database/repository/trade/trade.go | 10 +- database/repository/trade/trade_test.go | 10 +- engine/apiserver_test.go | 7 - engine/communication_manager_test.go | 2 - engine/database_connection.go | 41 +- engine/database_connection_test.go | 20 +- engine/datahistory_manager.go | 4 +- engine/datahistory_manager_test.go | 4 +- engine/engine_test.go | 72 +- engine/event_manager_test.go | 8 +- engine/exchange_manager_test.go | 2 +- engine/helpers_test.go | 213 ++++-- engine/order_manager_test.go | 2 +- engine/portfolio_manager_test.go | 2 +- engine/rpcserver_test.go | 333 +++++++--- engine/sync_manager_test.go | 9 + engine/websocketroutine_manager_test.go | 2 +- engine/withdraw_manager_test.go | 42 +- exchanges/bitfinex/bitfinex_test.go | 10 +- exchanges/bitfinex/bitfinex_wrapper.go | 2 +- exchanges/bitmex/bitmex_test.go | 68 +- exchanges/bitmex/bitmex_wrapper.go | 2 +- exchanges/btcmarkets/btcmarkets_test.go | 2 +- exchanges/coinbene/coinbene_test.go | 2 +- exchanges/exchange_test.go | 36 +- exchanges/ftx/ftx_test.go | 6 +- exchanges/ftx/ftx_wrapper.go | 2 +- exchanges/gateio/gateio_test.go | 2 +- exchanges/gemini/gemini_test.go | 2 +- exchanges/hitbtc/hitbtc_wrapper.go | 2 +- exchanges/huobi/huobi_test.go | 27 +- exchanges/kline/kline_test.go | 40 +- exchanges/kraken/kraken_test.go | 81 ++- exchanges/kraken/kraken_websocket.go | 13 +- exchanges/lakebtc/lakebtc_test.go | 2 +- exchanges/lbank/lbank_test.go | 2 +- exchanges/lbank/lbank_wrapper.go | 2 +- exchanges/okcoin/okcoin_test.go | 2 - exchanges/okex/okex_test.go | 2 - exchanges/stream/buffer/buffer_test.go | 14 +- exchanges/stream/stream_match_test.go | 1 + exchanges/stream/websocket_test.go | 24 +- exchanges/trade/trade_test.go | 5 +- gctscript/vm/vm_test.go | 1 - portfolio/banking/banking.go | 31 +- portfolio/banking/banking_test.go | 138 ++-- portfolio/banking/banking_types.go | 15 +- portfolio/portfolio_test.go | 49 +- portfolio/withdraw/validate_test.go | 34 +- 70 files changed, 1834 insertions(+), 1121 deletions(-) diff --git a/backtester/backtest/backtest.go b/backtester/backtest/backtest.go index f65fb13f..f36a5325 100644 --- a/backtester/backtest/backtest.go +++ b/backtester/backtest/backtest.go @@ -86,13 +86,6 @@ func NewFromConfig(cfg *config.Config, templatePath, output string, bot *engine. return nil, err } - e, err := bt.setupExchangeSettings(cfg) - if err != nil { - return nil, err - } - - bt.Exchange = &e - buyRule := config.MinMax{ MinimumSize: cfg.PortfolioSettings.BuySide.MinimumSize, MaximumSize: cfg.PortfolioSettings.BuySide.MaximumSize, @@ -158,22 +151,6 @@ func NewFromConfig(cfg *config.Config, templatePath, output string, bot *engine. if err != nil { return nil, err } - for i := range e.CurrencySettings { - var lookup *settings.Settings - lookup, err = p.SetupCurrencySettingsMap(e.CurrencySettings[i].ExchangeName, e.CurrencySettings[i].AssetType, e.CurrencySettings[i].CurrencyPair) - if err != nil { - return nil, err - } - lookup.Fee = e.CurrencySettings[i].TakerFee - lookup.Leverage = e.CurrencySettings[i].Leverage - lookup.BuySideSizing = e.CurrencySettings[i].BuySide - lookup.SellSideSizing = e.CurrencySettings[i].SellSide - lookup.InitialFunds = e.CurrencySettings[i].InitialFunds - lookup.ComplianceManager = compliance.Manager{ - Snapshots: []compliance.Snapshot{}, - } - } - bt.Portfolio = p bt.Strategy, err = strategies.LoadStrategyByName(cfg.StrategySettings.Name, cfg.StrategySettings.SimultaneousSignalProcessing) if err != nil { @@ -197,6 +174,29 @@ func NewFromConfig(cfg *config.Config, templatePath, output string, bot *engine. bt.Statistic = stats reports.Statistics = stats + e, err := bt.setupExchangeSettings(cfg) + if err != nil { + return nil, err + } + + bt.Exchange = &e + for i := range e.CurrencySettings { + var lookup *settings.Settings + lookup, err = p.SetupCurrencySettingsMap(e.CurrencySettings[i].ExchangeName, e.CurrencySettings[i].AssetType, e.CurrencySettings[i].CurrencyPair) + if err != nil { + return nil, err + } + lookup.Fee = e.CurrencySettings[i].TakerFee + lookup.Leverage = e.CurrencySettings[i].Leverage + lookup.BuySideSizing = e.CurrencySettings[i].BuySide + lookup.SellSideSizing = e.CurrencySettings[i].SellSide + lookup.InitialFunds = e.CurrencySettings[i].InitialFunds + lookup.ComplianceManager = compliance.Manager{ + Snapshots: []compliance.Snapshot{}, + } + } + bt.Portfolio = p + cfg.PrintSetting() return bt, nil @@ -418,7 +418,6 @@ func getFees(exch gctexchange.IBotExchange, fPair currency.Pair) (makerFee, take // loadData will create kline data from the sources defined in start config files. It can exist from databases, csv or API endpoints // it can also be generated from trade data which will be converted into kline data func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange, fPair currency.Pair, a asset.Item) (*kline.DataFromKline, error) { - log.Infof(log.BackTester, "loading data for %v %v %v...\n", exch.GetName(), a, fPair) if exch == nil { return nil, engine.ErrExchangeNotFound } @@ -429,7 +428,6 @@ func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange, cfg.DataSettings.CSVData == nil { return nil, errNoDataSource } - resp := &kline.DataFromKline{} if (cfg.DataSettings.APIData != nil && cfg.DataSettings.DatabaseData != nil) || (cfg.DataSettings.APIData != nil && cfg.DataSettings.LiveData != nil) || (cfg.DataSettings.APIData != nil && cfg.DataSettings.CSVData != nil) || @@ -444,6 +442,8 @@ func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange, return nil, err } + log.Infof(log.BackTester, "loading data for %v %v %v...\n", exch.GetName(), a, fPair) + resp := &kline.DataFromKline{} switch { case cfg.DataSettings.CSVData != nil: if cfg.DataSettings.Interval <= 0 { @@ -941,18 +941,15 @@ func (bt *BackTest) loadLiveDataLoop(resp *kline.DataFromKline, cfg *config.Conf return } resp.Item = *candles - err = bt.loadLiveData(resp, cfg, exch, fPair, a, startDate, dataType) - if err != nil { - log.Error(log.BackTester, err) - return - } - loadNewDataTicker := time.NewTicker(time.Second * 30) + loadNewDataTimer := time.NewTimer(time.Second * 5) for { select { case <-bt.shutdown: return - case <-loadNewDataTicker.C: + case <-loadNewDataTimer.C: + log.Infof(log.BackTester, "fetching data for %v %v %v %v", exch.GetName(), a, fPair, cfg.DataSettings.Interval) + loadNewDataTimer.Reset(time.Second * 30) err = bt.loadLiveData(resp, cfg, exch, fPair, a, startDate, dataType) if err != nil { log.Error(log.BackTester, err) @@ -963,6 +960,15 @@ func (bt *BackTest) loadLiveDataLoop(resp *kline.DataFromKline, cfg *config.Conf } func (bt *BackTest) loadLiveData(resp *kline.DataFromKline, cfg *config.Config, exch gctexchange.IBotExchange, fPair currency.Pair, a asset.Item, startDate time.Time, dataType int64) error { + if resp == nil { + return errNilData + } + if cfg == nil { + return errNilConfig + } + if exch == nil { + return errNilExchange + } candles, err := live.LoadData( exch, dataType, @@ -972,6 +978,7 @@ func (bt *BackTest) loadLiveData(resp *kline.DataFromKline, cfg *config.Config, if err != nil { return err } + resp.Item.Candles = append(resp.Item.Candles, candles.Candles...) _, err = exch.FetchOrderbook(fPair, a) if err != nil { @@ -983,7 +990,7 @@ func (bt *BackTest) loadLiveData(resp *kline.DataFromKline, cfg *config.Config, return nil } endDate := candles.Candles[len(candles.Candles)-1].Time.Add(cfg.DataSettings.Interval) - if resp.Range.Ranges == nil { + if resp.Range == nil || resp.Range.Ranges == nil { dataRange, err := gctkline.CalculateCandleDateRanges( startDate, endDate, diff --git a/backtester/backtest/backtest_test.go b/backtester/backtest/backtest_test.go index 874c444e..253600a9 100644 --- a/backtester/backtest/backtest_test.go +++ b/backtester/backtest/backtest_test.go @@ -20,10 +20,13 @@ import ( "github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/statistics" "github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/statistics/currencystatistics" "github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies" - "github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/base" "github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/dollarcostaverage" "github.com/thrasher-corp/gocryptotrader/backtester/report" + "github.com/thrasher-corp/gocryptotrader/common/convert" + gctconfig "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" + "github.com/thrasher-corp/gocryptotrader/database" + "github.com/thrasher-corp/gocryptotrader/database/drivers" "github.com/thrasher-corp/gocryptotrader/engine" gctexchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -32,42 +35,54 @@ import ( const testExchange = "Bitstamp" -func newBotWithExchange() (*engine.Engine, gctexchange.IBotExchange) { - bot, err := engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) +func newBotWithExchange() *engine.Engine { + bot := &engine.Engine{ + Config: &gctconfig.Config{ + Exchanges: []gctconfig.ExchangeConfig{ + { + Name: testExchange, + Enabled: true, + WebsocketTrafficTimeout: time.Second, + CurrencyPairs: ¤cy.PairsManager{ + Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USD)}, + Enabled: []currency.Pair{currency.NewPair(currency.BTC, currency.USD)}, + ConfigFormat: ¤cy.PairFormat{}, + RequestFormat: ¤cy.PairFormat{}, + }, + }, + }, + }, + }, + }, + } + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { log.Fatal(err) } - bot.ExchangeManager = engine.SetupExchangeManager() - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - log.Fatal(err) - } - exch := bot.GetExchangeByName(testExchange) - if exch == nil { - log.Fatal("expected not nil") - } - return bot, exch + exch.SetDefaults() + em.Add(exch) + bot.ExchangeManager = em + return bot } func TestNewFromConfig(t *testing.T) { t.Parallel() _, err := NewFromConfig(nil, "", "", nil) - if err == nil { - t.Error("expected error for nil config") + if !errors.Is(err, errNilConfig) { + t.Errorf("received %v, expected %v", err, errNilConfig) } - cfg := &config.Config{ - GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"), - } + cfg := &config.Config{} _, err = NewFromConfig(cfg, "", "", nil) if !errors.Is(err, errNilBot) { t.Errorf("expected: %v, received %v", errNilBot, err) } - bot, _ := newBotWithExchange() + bot := newBotWithExchange() _, err = NewFromConfig(cfg, "", "", bot) if !errors.Is(err, config.ErrNoCurrencySettings) { t.Errorf("expected: %v, received %v", config.ErrNoCurrencySettings, err) @@ -97,6 +112,12 @@ func TestNewFromConfig(t *testing.T) { t.Errorf("expected: %v, received %v", engine.ErrExchangeNotFound, err) } + cfg.StrategySettings = config.StrategySettings{ + Name: dollarcostaverage.Name, + CustomSettings: map[string]interface{}{ + "hello": "moto", + }, + } cfg.CurrencySettings[0].ExchangeName = testExchange _, err = NewFromConfig(cfg, "", "", bot) if !errors.Is(err, errNoDataSource) { @@ -105,7 +126,6 @@ func TestNewFromConfig(t *testing.T) { cfg.CurrencySettings[0].Base = "BTC" cfg.CurrencySettings[0].Quote = "USD" - cfg.DataSettings.APIData = &config.APIData{ StartDate: time.Time{}, EndDate: time.Time{}, @@ -121,7 +141,7 @@ func TestNewFromConfig(t *testing.T) { t.Errorf("expected: %v, received %v", config.ErrStartEndUnset, err) } - cfg.DataSettings.APIData.StartDate = time.Now().Add(-time.Hour) + cfg.DataSettings.APIData.StartDate = time.Now().Add(-time.Minute) cfg.DataSettings.APIData.EndDate = time.Now() cfg.DataSettings.APIData.InclusiveEndDate = true _, err = NewFromConfig(cfg, "", "", bot) @@ -129,19 +149,7 @@ func TestNewFromConfig(t *testing.T) { t.Errorf("expected: %v, received %v", errIntervalUnset, err) } - cfg.DataSettings.Interval = gctkline.FifteenMin.Duration() - - _, err = NewFromConfig(cfg, "", "", bot) - if !errors.Is(err, base.ErrStrategyNotFound) { - t.Errorf("expected: %v, received %v", base.ErrStrategyNotFound, err) - } - - cfg.StrategySettings = config.StrategySettings{ - Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ - "hello": "moto", - }, - } + cfg.DataSettings.Interval = gctkline.OneMin.Duration() cfg.CurrencySettings[0].MakerFee = 1337 cfg.CurrencySettings[0].TakerFee = 1337 _, err = NewFromConfig(cfg, "", "", bot) @@ -150,140 +158,246 @@ func TestNewFromConfig(t *testing.T) { } } -func TestLoadData(t *testing.T) { +func TestLoadDataAPI(t *testing.T) { t.Parallel() - cfg := &config.Config{ - GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"), - } - cfg.CurrencySettings = []config.CurrencySettings{ - { - ExchangeName: "test", - Asset: "test", - Base: "test", - Quote: "test", - }, - } - cfg.CurrencySettings[0].ExchangeName = "binance" - cfg.CurrencySettings[0].Asset = asset.Spot.String() - cfg.CurrencySettings[0].Base = "BTC" - cfg.CurrencySettings[0].Quote = "USDT" - cfg.CurrencySettings[0].InitialFunds = 1337 - cfg.DataSettings.APIData = &config.APIData{ - StartDate: time.Time{}, - EndDate: time.Time{}, - } - cfg.DataSettings.APIData.StartDate = time.Now().Add(-time.Hour) - cfg.DataSettings.APIData.EndDate = time.Now() - cfg.DataSettings.Interval = gctkline.FifteenMin.Duration() - cfg.DataSettings.DataType = common.CandleStr - cfg.StrategySettings = config.StrategySettings{ - Name: dollarcostaverage.Name, - CustomSettings: map[string]interface{}{ - "hello": "moto", - }, - } - cfg.CurrencySettings[0].MakerFee = 1337 - cfg.CurrencySettings[0].TakerFee = 1337 - bot, exch := newBotWithExchange() - - _, err := NewFromConfig(cfg, "", "", bot) - if err != nil { - t.Error(err) - } bt := BackTest{ Reports: &report.Data{}, + Bot: &engine.Engine{}, } + cp := currency.NewPair(currency.BTC, currency.USDT) + cfg := &config.Config{ + CurrencySettings: []config.CurrencySettings{ + { + ExchangeName: "Binance", + Asset: asset.Spot.String(), + Base: cp.Base.String(), + Quote: cp.Quote.String(), + InitialFunds: 1337, + Leverage: config.Leverage{}, + BuySide: config.MinMax{}, + SellSide: config.MinMax{}, + MakerFee: 1337, + TakerFee: 1337, + }, + }, + DataSettings: config.DataSettings{ + DataType: common.CandleStr, + Interval: gctkline.OneMin.Duration(), + APIData: &config.APIData{ + StartDate: time.Now().Add(-time.Minute), + EndDate: time.Now(), + }}, + StrategySettings: config.StrategySettings{ + Name: dollarcostaverage.Name, + CustomSettings: map[string]interface{}{ + "hello": "moto", + }, + }, + } + em := engine.ExchangeManager{} + exch, err := em.NewExchangeByName("Binance") + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} - cp := currency.NewPair(currency.BTC, currency.USD) _, err = bt.loadData(cfg, exch, cp, asset.Spot) if err != nil { t.Error(err) } +} - cfg.DataSettings.APIData = nil - cfg.DataSettings.DatabaseData = &config.DatabaseData{ - StartDate: time.Now().Add(-time.Hour), - EndDate: time.Now(), - ConfigOverride: nil, - InclusiveEndDate: true, +func TestLoadDataDatabase(t *testing.T) { + t.Parallel() + bt := BackTest{ + Reports: &report.Data{}, + Bot: &engine.Engine{ + Config: &gctconfig.Config{Database: database.Config{}}, + }, } - cfg.DataSettings.DataType = common.CandleStr - cfg.DataSettings.Interval = gctkline.FifteenMin.Duration() + cp := currency.NewPair(currency.BTC, currency.USDT) + cfg := &config.Config{ + CurrencySettings: []config.CurrencySettings{ + { + ExchangeName: "Binance", + Asset: asset.Spot.String(), + Base: cp.Base.String(), + Quote: cp.Quote.String(), + InitialFunds: 1337, + Leverage: config.Leverage{}, + BuySide: config.MinMax{}, + SellSide: config.MinMax{}, + MakerFee: 1337, + TakerFee: 1337, + }, + }, + DataSettings: config.DataSettings{ + DataType: common.CandleStr, + Interval: gctkline.OneMin.Duration(), + DatabaseData: &config.DatabaseData{ + ConfigOverride: &database.Config{ + Enabled: true, + Driver: "sqlite3", + ConnectionDetails: drivers.ConnectionDetails{ + Database: "gocryptotrader.db", + }, + }, + StartDate: time.Now().Add(-time.Minute), + EndDate: time.Now(), + InclusiveEndDate: true, + }}, + StrategySettings: config.StrategySettings{ + Name: dollarcostaverage.Name, + CustomSettings: map[string]interface{}{ + "hello": "moto", + }, + }, + } + em := engine.ExchangeManager{} + exch, err := em.NewExchangeByName("Binance") + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} - bt.Bot = bot _, err = bt.loadData(cfg, exch, cp, asset.Spot) if err != nil && !strings.Contains(err.Error(), "unable to retrieve data from GoCryptoTrader database") { t.Error(err) } +} - cfg.DataSettings.DatabaseData = nil - cfg.DataSettings.CSVData = &config.CSVData{ - FullPath: "test", +func TestLoadDataCSV(t *testing.T) { + t.Parallel() + bt := BackTest{ + Reports: &report.Data{}, + Bot: &engine.Engine{}, } + cp := currency.NewPair(currency.BTC, currency.USDT) + cfg := &config.Config{ + CurrencySettings: []config.CurrencySettings{ + { + ExchangeName: "Binance", + Asset: asset.Spot.String(), + Base: cp.Base.String(), + Quote: cp.Quote.String(), + InitialFunds: 1337, + Leverage: config.Leverage{}, + BuySide: config.MinMax{}, + SellSide: config.MinMax{}, + MakerFee: 1337, + TakerFee: 1337, + }, + }, + DataSettings: config.DataSettings{ + DataType: common.CandleStr, + Interval: gctkline.OneMin.Duration(), + CSVData: &config.CSVData{ + FullPath: "test", + }}, + StrategySettings: config.StrategySettings{ + Name: dollarcostaverage.Name, + CustomSettings: map[string]interface{}{ + "hello": "moto", + }, + }, + } + em := engine.ExchangeManager{} + exch, err := em.NewExchangeByName("Binance") + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} _, err = bt.loadData(cfg, exch, cp, asset.Spot) if err != nil && !strings.Contains(err.Error(), "The system cannot find the file specified.") && !strings.Contains(err.Error(), "no such file or directory") { t.Error(err) } - cfg.DataSettings.CSVData = nil - cfg.DataSettings.LiveData = &config.LiveData{ - APIKeyOverride: "test", - APISecretOverride: "test", - APIClientIDOverride: "test", - API2FAOverride: "test", - APISubaccountOverride: "test", - RealOrders: true, +} + +func TestLoadDataLive(t *testing.T) { + t.Parallel() + bt := BackTest{ + Reports: &report.Data{}, + Bot: &engine.Engine{}, + shutdown: make(chan struct{}), } + cp := currency.NewPair(currency.BTC, currency.USDT) + cfg := &config.Config{ + CurrencySettings: []config.CurrencySettings{ + { + ExchangeName: "Binance", + Asset: asset.Spot.String(), + Base: cp.Base.String(), + Quote: cp.Quote.String(), + InitialFunds: 1337, + Leverage: config.Leverage{}, + BuySide: config.MinMax{}, + SellSide: config.MinMax{}, + MakerFee: 1337, + TakerFee: 1337, + }, + }, + DataSettings: config.DataSettings{ + DataType: common.CandleStr, + Interval: gctkline.OneMin.Duration(), + LiveData: &config.LiveData{ + APIKeyOverride: "test", + APISecretOverride: "test", + APIClientIDOverride: "test", + API2FAOverride: "test", + RealOrders: true, + }}, + StrategySettings: config.StrategySettings{ + Name: dollarcostaverage.Name, + CustomSettings: map[string]interface{}{ + "hello": "moto", + }, + }, + } + em := engine.ExchangeManager{} + exch, err := em.NewExchangeByName("Binance") + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} _, err = bt.loadData(cfg, exch, cp, asset.Spot) if err != nil { t.Error(err) } -} - -func TestLoadDatabaseData(t *testing.T) { - t.Parallel() - cp := currency.NewPair(currency.BTC, currency.USD) - _, err := loadDatabaseData(nil, "", cp, "", -1) - if err != nil && !strings.Contains(err.Error(), "nil config data received") { - t.Error(err) - } - cfg := &config.Config{ - DataSettings: config.DataSettings{ - DatabaseData: &config.DatabaseData{ - StartDate: time.Time{}, - EndDate: time.Time{}, - ConfigOverride: nil, - }, - }, - GoCryptoTraderConfigPath: filepath.Join("..", "..", "testdata", "configtest.json"), - } - _, err = loadDatabaseData(cfg, "", cp, "", -1) - if !errors.Is(err, config.ErrStartEndUnset) { - t.Errorf("expected %v, received %v", config.ErrStartEndUnset, err) - } - cfg.DataSettings.DatabaseData.StartDate = time.Now().Add(-time.Hour) - cfg.DataSettings.DatabaseData.EndDate = time.Now() - _, err = loadDatabaseData(cfg, "", cp, "", -1) - if !errors.Is(err, errIntervalUnset) { - t.Errorf("expected %v, received %v", errIntervalUnset, err) - } - - cfg.DataSettings.Interval = gctkline.OneDay.Duration() - _, err = loadDatabaseData(cfg, "", cp, "", -1) - if err != nil && !strings.Contains(err.Error(), "could not retrieve database data") { - t.Error(err) - } - - cfg.DataSettings.DataType = common.CandleStr - _, err = loadDatabaseData(cfg, "", cp, "", common.DataCandle) - if err != nil && !strings.Contains(err.Error(), "exchange, base, quote, asset, interval, start & end cannot be empty") { - t.Error(err) - } - _, err = loadDatabaseData(cfg, testExchange, cp, asset.Spot, common.DataCandle) - if err != nil && !strings.Contains(err.Error(), "database support is disabled") { - t.Error(err) - } + bt.Stop() } func TestLoadLiveData(t *testing.T) { @@ -399,7 +513,7 @@ func TestFullCycle(t *testing.T) { if err != nil { t.Error(err) } - bot, _ := newBotWithExchange() + bot := newBotWithExchange() bt := BackTest{ Bot: bot, @@ -493,7 +607,7 @@ func TestFullCycleMulti(t *testing.T) { if err != nil { t.Error(err) } - bot, _ := newBotWithExchange() + bot := newBotWithExchange() bt := BackTest{ Bot: bot, diff --git a/backtester/backtest/backtest_types.go b/backtester/backtest/backtest_types.go index 59722dc5..a7803fcf 100644 --- a/backtester/backtest/backtest_types.go +++ b/backtester/backtest/backtest_types.go @@ -23,6 +23,8 @@ var ( errIntervalUnset = errors.New("candle interval unset") errUnhandledDatatype = errors.New("unhandled datatype") errLiveDataTimeout = errors.New("no data returned in 5 minutes, shutting down") + errNilData = errors.New("nil data received") + errNilExchange = errors.New("nil exchange received") ) // BackTest is the main holder of all backtesting functionality diff --git a/backtester/data/kline/api/api_test.go b/backtester/data/kline/api/api_test.go index 9971d509..05b20eed 100644 --- a/backtester/data/kline/api/api_test.go +++ b/backtester/data/kline/api/api_test.go @@ -2,59 +2,42 @@ package api import ( "errors" - "log" - "os" - "path/filepath" "testing" "time" "github.com/thrasher-corp/gocryptotrader/backtester/common" + "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/engine" - exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline" ) const testExchange = "binance" -var ( - bot *engine.Engine - exch exchange.IBotExchange -) - -func TestMain(m *testing.M) { - var err error - bot, err = engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) - if err != nil { - log.Fatal(err) - } - - bot.ExchangeManager = engine.SetupExchangeManager() - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - log.Fatal(err) - } - exch = bot.GetExchangeByName(testExchange) - if exch == nil { - log.Fatal("expected binance") - } - os.Exit(m.Run()) -} - func TestLoadCandles(t *testing.T) { t.Parallel() - tt1 := time.Now().Add(-time.Hour).Round(gctkline.OneHour.Duration()) - tt2 := time.Now().Round(gctkline.OneHour.Duration()) - interval := gctkline.OneHour + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + cp := currency.NewPair(currency.BTC, currency.USDT) + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + tt1 := time.Now().Add(-time.Minute).Round(gctkline.OneMin.Duration()) + tt2 := time.Now().Round(gctkline.OneMin.Duration()) + interval := gctkline.OneMin a := asset.Spot - p := currency.NewPair(currency.BTC, currency.USDT) var data *gctkline.Item - var err error - data, err = LoadData(common.DataCandle, tt1, tt2, interval.Duration(), exch, p, a) + data, err = LoadData(common.DataCandle, tt1, tt2, interval.Duration(), exch, cp, a) if err != nil { t.Fatal(err) } @@ -62,7 +45,7 @@ func TestLoadCandles(t *testing.T) { t.Error("expected candles") } - _, err = LoadData(-1, tt1, tt2, interval.Duration(), exch, p, a) + _, err = LoadData(-1, tt1, tt2, interval.Duration(), exch, cp, a) if !errors.Is(err, common.ErrInvalidDataType) { t.Errorf("expected '%v' received '%v'", err, common.ErrInvalidDataType) } @@ -70,14 +53,27 @@ func TestLoadCandles(t *testing.T) { func TestLoadTrades(t *testing.T) { t.Parallel() - interval := gctkline.FifteenMin - tt1 := time.Now().Add(-time.Minute * 30).Round(interval.Duration()) + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + cp := currency.NewPair(currency.BTC, currency.USDT) + b := exch.GetBase() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + interval := gctkline.OneMin + tt1 := time.Now().Add(-time.Minute * 2).Round(interval.Duration()) tt2 := time.Now().Round(interval.Duration()) a := asset.Spot - p := currency.NewPair(currency.BTC, currency.USDT) - var err error var data *gctkline.Item - data, err = LoadData(common.DataTrade, tt1, tt2, interval.Duration(), exch, p, a) + data, err = LoadData(common.DataTrade, tt1, tt2, interval.Duration(), exch, cp, a) if err != nil { t.Fatal(err) } diff --git a/backtester/data/kline/live/live.go b/backtester/data/kline/live/live.go index bda490d5..9f33f794 100644 --- a/backtester/data/kline/live/live.go +++ b/backtester/data/kline/live/live.go @@ -22,7 +22,7 @@ func LoadData(exch exchange.IBotExchange, dataType int64, interval time.Duration candles, err = exch.GetHistoricCandles( fPair, a, - time.Now().Add(-interval), // multiplied by 2 to ensure the latest candle is always included + time.Now().Add(-interval*2), // multiplied by 2 to ensure the latest candle is always included time.Now(), kline.Interval(interval)) if err != nil { @@ -30,9 +30,7 @@ func LoadData(exch exchange.IBotExchange, dataType int64, interval time.Duration } case common.DataTrade: var trades []trade.Data - trades, err = exch.GetRecentTrades( - fPair, - a) + trades, err = exch.GetHistoricTrades(fPair, a, time.Now().Add(-interval*2), time.Now()) // multiplied by 2 to ensure the latest candle is always included if err != nil { return nil, err } diff --git a/backtester/data/kline/live/live_test.go b/backtester/data/kline/live/live_test.go index d87b71ec..aa9abf27 100644 --- a/backtester/data/kline/live/live_test.go +++ b/backtester/data/kline/live/live_test.go @@ -2,47 +2,48 @@ package live import ( "errors" - "log" - "path/filepath" "testing" "github.com/thrasher-corp/gocryptotrader/backtester/common" - "github.com/thrasher-corp/gocryptotrader/config" + "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/engine" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" gctkline "github.com/thrasher-corp/gocryptotrader/exchanges/kline" ) -const testExchange = "FTX" +const testExchange = "binance" func TestLoadCandles(t *testing.T) { t.Parallel() - interval := gctkline.FifteenMin - bot := new(engine.Engine) - bot.Config = &config.Config{} - err := bot.Config.LoadConfig(filepath.Join("..", "..", "..", "..", "testdata", "configtest.json"), true) - if err != nil { - t.Fatalf("SetupTest: Failed to load config: %s", err) - } - bot.ExchangeManager = engine.SetupExchangeManager() - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - log.Fatal(err) - } - exch := bot.ExchangeManager.GetExchangeByName(testExchange) + interval := gctkline.OneHour + cp1 := currency.NewPair(currency.BTC, currency.USDT) a := asset.Spot - p := currency.NewPair(currency.BTC, currency.USD) + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } + pFormat := ¤cy.PairFormat{Uppercase: true} + b := exch.GetBase() + exch.SetDefaults() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp1}, + Enabled: currency.Pairs{cp1}, + AssetEnabled: convert.BoolPtr(true), + RequestFormat: pFormat, + ConfigFormat: pFormat, + } var data *gctkline.Item - data, err = LoadData(exch, common.DataCandle, interval.Duration(), p, a) + data, err = LoadData(exch, common.DataCandle, interval.Duration(), cp1, a) if err != nil { t.Fatal(err) } if len(data.Candles) == 0 { t.Error("expected candles") } - - _, err = LoadData(exch, -1, interval.Duration(), p, a) + _, err = LoadData(exch, -1, interval.Duration(), cp1, a) if !errors.Is(err, common.ErrInvalidDataType) { t.Errorf("expected '%v' received '%v'", err, common.ErrInvalidDataType) } @@ -50,28 +51,27 @@ func TestLoadCandles(t *testing.T) { func TestLoadTrades(t *testing.T) { t.Parallel() - interval := gctkline.FifteenMin - bot, err := engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) - if err != nil { - t.Error(err) - } - bot.ExchangeManager = engine.SetupExchangeManager() - - err = bot.LoadExchange(testExchange, false, nil) + interval := gctkline.OneMin + cp1 := currency.NewPair(currency.BTC, currency.USDT) + a := asset.Spot + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { t.Fatal(err) } - exch := bot.GetExchangeByName(testExchange) - if exch == nil { - t.Fatal("expected binance") + pFormat := ¤cy.PairFormat{Uppercase: true} + b := exch.GetBase() + exch.SetDefaults() + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp1}, + Enabled: currency.Pairs{cp1}, + AssetEnabled: convert.BoolPtr(true), + RequestFormat: pFormat, + ConfigFormat: pFormat, } - a := asset.Spot - p := currency.NewPair(currency.BTC, currency.USDT) var data *gctkline.Item - data, err = LoadData(exch, common.DataTrade, interval.Duration(), p, a) + data, err = LoadData(exch, common.DataTrade, interval.Duration(), cp1, a) if err != nil { t.Fatal(err) } diff --git a/backtester/eventhandlers/exchange/exchange_test.go b/backtester/eventhandlers/exchange/exchange_test.go index 01938832..316e05c0 100644 --- a/backtester/eventhandlers/exchange/exchange_test.go +++ b/backtester/eventhandlers/exchange/exchange_test.go @@ -2,7 +2,6 @@ package exchange import ( "errors" - "path/filepath" "strings" "testing" "time" @@ -132,14 +131,15 @@ func TestSizeOrder(t *testing.T) { func TestPlaceOrder(t *testing.T) { t.Parallel() - bot, err := engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) + bot := &engine.Engine{} + var err error + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { t.Fatal(err) } - em := engine.SetupExchangeManager() + exch.SetDefaults() + em.Add(exch) bot.ExchangeManager = em bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false) if err != nil { @@ -149,10 +149,7 @@ func TestPlaceOrder(t *testing.T) { if err != nil { t.Error(err) } - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - t.Error(err) - } + e := Exchange{} _, err = e.placeOrder(1, 1, false, true, nil, nil) if !errors.Is(err, common.ErrNilEvent) { @@ -185,15 +182,15 @@ func TestPlaceOrder(t *testing.T) { func TestExecuteOrder(t *testing.T) { t.Parallel() - bot, err := engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) + bot := &engine.Engine{} + var err error + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { t.Fatal(err) } - - em := engine.SetupExchangeManager() + exch.SetDefaults() + em.Add(exch) bot.ExchangeManager = em bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false) if err != nil { @@ -203,20 +200,10 @@ func TestExecuteOrder(t *testing.T) { if err != nil { t.Error(err) } - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - t.Error(err) - } - b := bot.GetExchangeByName(testExchange) p := currency.NewPair(currency.BTC, currency.USDT) a := asset.Spot - _, err = b.FetchOrderbook(p, a) - if err != nil { - t.Fatal(err) - } - - limits, err := b.GetOrderExecutionLimits(a, p) + _, err = exch.FetchOrderbook(p, a) if err != nil { t.Fatal(err) } @@ -235,7 +222,6 @@ func TestExecuteOrder(t *testing.T) { Leverage: config.Leverage{}, MinimumSlippageRate: 0, MaximumSlippageRate: 1, - Limits: limits, } e := Exchange{ CurrencySettings: []Settings{cs}, @@ -292,38 +278,37 @@ func TestExecuteOrder(t *testing.T) { func TestExecuteOrderBuySellSizeLimit(t *testing.T) { t.Parallel() - bot, err := engine.NewFromSettings(&engine.Settings{ - ConfigFile: filepath.Join("..", "..", "..", "testdata", "configtest.json"), - EnableDryRun: true, - }, nil) + bot := &engine.Engine{} + var err error + em := engine.SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { t.Fatal(err) } - em := engine.SetupExchangeManager() + exch.SetDefaults() + em.Add(exch) bot.ExchangeManager = em bot.OrderManager, err = engine.SetupOrderManager(em, &engine.CommunicationManager{}, &bot.ServicesWG, false) if err != nil { t.Error(err) } - err = bot.OrderManager.Start() if err != nil { t.Error(err) } - err = bot.LoadExchange(testExchange, false, nil) - if err != nil { - t.Error(err) - } - b := bot.GetExchangeByName(testExchange) - p := currency.NewPair(currency.BTC, currency.USDT) a := asset.Spot - _, err = b.FetchOrderbook(p, a) + _, err = exch.FetchOrderbook(p, a) if err != nil { t.Fatal(err) } - limits, err := b.GetOrderExecutionLimits(a, p) + err = exch.UpdateOrderExecutionLimits(asset.Spot) + if err != nil { + t.Fatal(err) + } + + limits, err := exch.GetOrderExecutionLimits(a, p) if err != nil { t.Fatal(err) } diff --git a/common/timedmutex/timed_mutex_test.go b/common/timedmutex/timed_mutex_test.go index bf9c3941..7bc9ac65 100644 --- a/common/timedmutex/timed_mutex_test.go +++ b/common/timedmutex/timed_mutex_test.go @@ -14,10 +14,10 @@ func BenchmarkTimedMutexTime(b *testing.B) { func TestConsistencyOfPanicFreeUnlock(t *testing.T) { t.Parallel() - duration := 20 * time.Millisecond + duration := 20 * time.Microsecond tm := NewTimedMutex(duration) for i := 1; i <= 50; i++ { - testUnlockTime := time.Duration(i) * time.Millisecond + testUnlockTime := time.Duration(i) * time.Microsecond tm.LockForDuration() time.Sleep(testUnlockTime) tm.UnlockIfLocked() @@ -26,9 +26,9 @@ func TestConsistencyOfPanicFreeUnlock(t *testing.T) { func TestUnlockAfterTimeout(t *testing.T) { t.Parallel() - tm := NewTimedMutex(time.Second) + tm := NewTimedMutex(time.Nanosecond) tm.LockForDuration() - time.Sleep(2 * time.Second) + time.Sleep(time.Millisecond * 200) wasUnlocked := tm.UnlockIfLocked() if wasUnlocked { t.Error("Mutex should have been unlocked by timeout, not command") @@ -37,9 +37,8 @@ func TestUnlockAfterTimeout(t *testing.T) { func TestUnlockBeforeTimeout(t *testing.T) { t.Parallel() - tm := NewTimedMutex(2 * time.Second) + tm := NewTimedMutex(20 * time.Millisecond) tm.LockForDuration() - time.Sleep(time.Second) wasUnlocked := tm.UnlockIfLocked() if !wasUnlocked { t.Error("Mutex should have been unlocked by command, not timeout") @@ -53,7 +52,7 @@ func TestUnlockBeforeTimeout(t *testing.T) { // the unlock occurs without this test panicking func TestUnlockAtSameTimeAsTimeout(t *testing.T) { t.Parallel() - duration := time.Second + duration := time.Millisecond tm := NewTimedMutex(duration) tm.LockForDuration() time.Sleep(duration) @@ -80,7 +79,7 @@ func TestMultipleUnlocks(t *testing.T) { func TestJustWaitItOut(t *testing.T) { t.Parallel() - tm := NewTimedMutex(1 * time.Second) + tm := NewTimedMutex(1 * time.Millisecond) tm.LockForDuration() - time.Sleep(2 * time.Second) + time.Sleep(2 * time.Millisecond) } diff --git a/communications/slack/slack_test.go b/communications/slack/slack_test.go index 5b1563c0..465d1ada 100644 --- a/communications/slack/slack_test.go +++ b/communications/slack/slack_test.go @@ -8,12 +8,6 @@ import ( "github.com/thrasher-corp/gocryptotrader/config" ) -const ( - verificationToken = "" -) - -var s Slack - type group struct { ID string `json:"id"` Name string `json:"name"` @@ -21,18 +15,17 @@ type group struct { } func TestSetup(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig("../../testdata/configtest.json", true) - if err != nil { - t.Fatal(err) - } - + t.Parallel() + var s Slack + cfg := &config.Config{Communications: base.CommunicationsConfig{}} commsCfg := cfg.GetCommunicationsConfig() s.Setup(&commsCfg) s.Verbose = true } func TestConnect(t *testing.T) { + t.Parallel() + var s Slack err := s.Connect() if err == nil { t.Error("slack Connect() error cannot be nil") @@ -41,6 +34,7 @@ func TestConnect(t *testing.T) { func TestPushEvent(t *testing.T) { t.Parallel() + var s Slack err := s.PushEvent(base.Event{}) if err == nil { t.Error("slack PushEvent() error cannot be nil") @@ -49,6 +43,7 @@ func TestPushEvent(t *testing.T) { func TestBuildURL(t *testing.T) { t.Parallel() + var s Slack v := s.BuildURL("lol123") if v != "https://slack.com/api/rtm.start?token=lol123" { t.Error("slack BuildURL() error") @@ -56,6 +51,8 @@ func TestBuildURL(t *testing.T) { } func TestGetChannelsString(t *testing.T) { + t.Parallel() + var s Slack s.Details.Channels = append(s.Details.Channels, struct { ID string `json:"id"` Name string `json:"name"` @@ -78,6 +75,8 @@ func TestGetChannelsString(t *testing.T) { } func TestGetUsernameByID(t *testing.T) { + t.Parallel() + var s Slack username := s.GetUsernameByID("1337") if username != "" { t.Error("slack GetUsernameByID() error") @@ -99,6 +98,8 @@ func TestGetUsernameByID(t *testing.T) { } func TestGetIDByName(t *testing.T) { + t.Parallel() + var s Slack id, err := s.GetIDByName("batman") if err == nil || id != "" { t.Error("slack GetIDByName() error") @@ -116,6 +117,8 @@ func TestGetIDByName(t *testing.T) { } func TestGetGroupIDByName(t *testing.T) { + t.Parallel() + var s Slack id, err := s.GetGroupIDByName("batman") if err == nil || id != "" { t.Error("slack GetGroupIDByName() error") @@ -133,6 +136,8 @@ func TestGetGroupIDByName(t *testing.T) { } func TestGetChannelIDByName(t *testing.T) { + t.Parallel() + var s Slack id, err := s.GetChannelIDByName("1337") if err == nil || id != "" { t.Error("slack GetChannelIDByName() error") @@ -156,6 +161,8 @@ func TestGetChannelIDByName(t *testing.T) { } func TestGetUsersInGroup(t *testing.T) { + t.Parallel() + var s Slack username := s.GetUsersInGroup("supergroup") if len(username) != 0 { t.Error("slack GetUsersInGroup() error") @@ -175,6 +182,8 @@ func TestGetUsersInGroup(t *testing.T) { } func TestNewConnection(t *testing.T) { + t.Parallel() + var s Slack err := s.NewConnection() if err == nil { t.Error("slack NewConnection() error") @@ -182,6 +191,8 @@ func TestNewConnection(t *testing.T) { } func TestWebsocketConnect(t *testing.T) { + t.Parallel() + var s Slack err := s.WebsocketConnect() if err == nil { t.Error("slack WebsocketConnect() error") @@ -189,6 +200,8 @@ func TestWebsocketConnect(t *testing.T) { } func TestHandlePresenceChange(t *testing.T) { + t.Parallel() + var s Slack var pres PresenceChange pres.User = "1337" pres.Presence = "Present" @@ -206,6 +219,8 @@ func TestHandlePresenceChange(t *testing.T) { } func TestHandleMessageResponse(t *testing.T) { + t.Parallel() + var s Slack var data WebsocketResponse data.ReplyTo = 1 @@ -242,6 +257,8 @@ func TestHandleMessageResponse(t *testing.T) { } func TestHandleErrorResponse(t *testing.T) { + t.Parallel() + var s Slack var data WebsocketResponse err := s.handleErrorResponse(data) if err == nil { @@ -256,10 +273,14 @@ func TestHandleErrorResponse(t *testing.T) { } func TestHandleHelloResponse(t *testing.T) { + t.Parallel() + var s Slack s.handleHelloResponse() } func TestHandleReconnectResponse(t *testing.T) { + t.Parallel() + var s Slack err := s.handleReconnectResponse([]byte(`{"malformedjson}`)) if err == nil { t.Error("slack handleReconnectResponse(), unmarshalled malformed json") @@ -280,6 +301,8 @@ func TestHandleReconnectResponse(t *testing.T) { } func TestWebsocketSend(t *testing.T) { + t.Parallel() + var s Slack err := s.WebsocketSend("test", "Hello World!") if err == nil { t.Error("slack WebsocketSend(), Sent message through nil websocket") @@ -287,6 +310,8 @@ func TestWebsocketSend(t *testing.T) { } func TestHandleMessage(t *testing.T) { + t.Parallel() + var s Slack msg := &Message{} err := s.HandleMessage(msg) if err == nil { diff --git a/communications/smsglobal/smsglobal_test.go b/communications/smsglobal/smsglobal_test.go index 0db1298f..26743c29 100644 --- a/communications/smsglobal/smsglobal_test.go +++ b/communications/smsglobal/smsglobal_test.go @@ -7,19 +7,17 @@ import ( "github.com/thrasher-corp/gocryptotrader/config" ) -var s SMSGlobal - func TestSetup(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig("../../testdata/configtest.json", true) - if err != nil { - t.Fatal(err) - } + t.Parallel() + var s SMSGlobal + cfg := &config.Config{Communications: base.CommunicationsConfig{}} commsCfg := cfg.GetCommunicationsConfig() s.Setup(&commsCfg) } func TestConnect(t *testing.T) { + t.Parallel() + var s SMSGlobal err := s.Connect() if err != nil { t.Error("SMSGlobal Connect() error", err) @@ -27,6 +25,8 @@ func TestConnect(t *testing.T) { } func TestPushEvent(t *testing.T) { + t.Parallel() + var s SMSGlobal err := s.PushEvent(base.Event{}) if err != nil { t.Error("SMSGlobal PushEvent() error", err) @@ -34,6 +34,15 @@ func TestPushEvent(t *testing.T) { } func TestGetEnabledContacts(t *testing.T) { + t.Parallel() + s := SMSGlobal{ + Contacts: []Contact{ + { + Name: "test123", + Enabled: true, + }, + }, + } v := s.GetEnabledContacts() if v != 1 { t.Error("SMSGlobal GetEnabledContacts() error") @@ -41,7 +50,17 @@ func TestGetEnabledContacts(t *testing.T) { } func TestGetContactByNumber(t *testing.T) { - _, err := s.GetContactByNumber("1231424") + t.Parallel() + s := SMSGlobal{ + Contacts: []Contact{ + { + Name: "test123", + Enabled: true, + Number: "1337", + }, + }, + } + _, err := s.GetContactByNumber("1337") if err != nil { t.Error("SMSGlobal GetContactByNumber() error", err) } @@ -52,7 +71,16 @@ func TestGetContactByNumber(t *testing.T) { } func TestGetContactByName(t *testing.T) { - _, err := s.GetContactByName("StyleGherkin") + t.Parallel() + s := SMSGlobal{ + Contacts: []Contact{ + { + Name: "test123", + Enabled: true, + }, + }, + } + _, err := s.GetContactByName("test123") if err != nil { t.Error("SMSGlobal GetContactByName() error", err) } @@ -63,11 +91,15 @@ func TestGetContactByName(t *testing.T) { } func TestAddContact(t *testing.T) { + t.Parallel() + s := SMSGlobal{ + Contacts: []Contact{}, + } err := s.AddContact(Contact{Name: "bra", Number: "2876", Enabled: true}) if err != nil { t.Error("SMSGlobal AddContact() error", err) } - err = s.AddContact(Contact{Name: "StyleGherkin", Number: "1231424", Enabled: true}) + err = s.AddContact(Contact{Name: "bra", Number: "2876", Enabled: true}) if err == nil { t.Error("SMSGlobal AddContact() error") } @@ -75,10 +107,23 @@ func TestAddContact(t *testing.T) { if err == nil { t.Error("SMSGlobal AddContact() error") } + if len(s.Contacts) == 0 { + t.Error("failed to add contacts") + } } func TestRemoveContact(t *testing.T) { - err := s.RemoveContact(Contact{Name: "StyleGherkin", Number: "1231424", Enabled: true}) + t.Parallel() + s := SMSGlobal{ + Contacts: []Contact{ + { + Name: "test123", + Enabled: true, + Number: "1337", + }, + }, + } + err := s.RemoveContact(Contact{Name: "test123", Number: "1337", Enabled: true}) if err != nil { t.Error("SMSGlobal RemoveContact() error", err) } @@ -89,6 +134,8 @@ func TestRemoveContact(t *testing.T) { } func TestSendMessageToAll(t *testing.T) { + t.Parallel() + var s SMSGlobal err := s.SendMessageToAll("Hello,World!") if err != nil { t.Error("SMSGlobal SendMessageToAll() error", err) @@ -96,6 +143,8 @@ func TestSendMessageToAll(t *testing.T) { } func TestSendMessage(t *testing.T) { + t.Parallel() + var s SMSGlobal err := s.SendMessage("1337", "Hello!") if err != nil { t.Error("SMSGlobal SendMessage() error", err) diff --git a/communications/smtpservice/smtpservice_test.go b/communications/smtpservice/smtpservice_test.go index f1996348..af05ffdf 100644 --- a/communications/smtpservice/smtpservice_test.go +++ b/communications/smtpservice/smtpservice_test.go @@ -10,11 +10,8 @@ import ( var s SMTPservice func TestSetup(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig("../../testdata/configtest.json", true) - if err != nil { - t.Fatal(err) - } + t.Parallel() + cfg := &config.Config{Communications: base.CommunicationsConfig{}} commsCfg := cfg.GetCommunicationsConfig() s.Setup(&commsCfg) } diff --git a/communications/telegram/telegram_test.go b/communications/telegram/telegram_test.go index d50ba75e..5a0bf396 100644 --- a/communications/telegram/telegram_test.go +++ b/communications/telegram/telegram_test.go @@ -11,15 +11,18 @@ const ( testErrNotFound = "Not Found" ) -var T Telegram - func TestSetup(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig("../../testdata/configtest.json", true) - if err != nil { - t.Fatal(err) - } + t.Parallel() + cfg := &config.Config{Communications: base.CommunicationsConfig{ + TelegramConfig: base.TelegramConfig{ + Name: "Telegram", + Enabled: false, + Verbose: false, + VerificationToken: "testest", + }, + }} commsCfg := cfg.GetCommunicationsConfig() + var T Telegram T.Setup(&commsCfg) if T.Name != "Telegram" || T.Enabled || T.Token != "testest" || T.Verbose { t.Error("telegram Setup() error, unexpected setup values", @@ -31,6 +34,8 @@ func TestSetup(t *testing.T) { } func TestConnect(t *testing.T) { + t.Parallel() + var T Telegram err := T.Connect() if err == nil { t.Error("telegram Connect() error") @@ -38,6 +43,8 @@ func TestConnect(t *testing.T) { } func TestPushEvent(t *testing.T) { + t.Parallel() + var T Telegram err := T.PushEvent(base.Event{}) if err != nil { t.Error("telegram PushEvent() error", err) @@ -52,6 +59,7 @@ func TestPushEvent(t *testing.T) { func TestHandleMessages(t *testing.T) { t.Parallel() + var T Telegram chatID := int64(1337) err := T.HandleMessages(cmdHelp, chatID) if err.Error() != testErrNotFound { @@ -82,6 +90,7 @@ func TestHandleMessages(t *testing.T) { func TestGetUpdates(t *testing.T) { t.Parallel() + var T Telegram _, err := T.GetUpdates() if err != nil { t.Error("telegram GetUpdates() error", err) @@ -90,6 +99,7 @@ func TestGetUpdates(t *testing.T) { func TestTestConnection(t *testing.T) { t.Parallel() + var T Telegram err := T.TestConnection() if err.Error() != testErrNotFound { t.Errorf("telegram TestConnection() error, expected 'Not found' got '%s'", @@ -99,6 +109,7 @@ func TestTestConnection(t *testing.T) { func TestSendMessage(t *testing.T) { t.Parallel() + var T Telegram err := T.SendMessage("Test message", int64(1337)) if err.Error() != testErrNotFound { t.Errorf("telegram SendMessage() error, expected 'Not found' got '%s'", @@ -108,6 +119,7 @@ func TestSendMessage(t *testing.T) { func TestSendHTTPRequest(t *testing.T) { t.Parallel() + var T Telegram err := T.SendHTTPRequest("0.0.0.0", nil, nil) if err == nil { t.Error("telegram SendHTTPRequest() error") diff --git a/config/config.go b/config/config.go index b81c330c..6ed252be 100644 --- a/config/config.go +++ b/config/config.go @@ -1062,7 +1062,7 @@ func (c *Config) CheckBankAccountConfig() { } } } - banking.Accounts = c.BankAccounts + banking.SetAccounts(c.BankAccounts...) } // CheckCurrencyConfigValues checks to see if the currency config values are correct or not diff --git a/config/config_encryption_test.go b/config/config_encryption_test.go index 605aad68..bd5f18ec 100644 --- a/config/config_encryption_test.go +++ b/config/config_encryption_test.go @@ -38,6 +38,7 @@ func TestPromptForConfigKey(t *testing.T) { } func TestEncryptConfigFile(t *testing.T) { + t.Parallel() _, err := EncryptConfigFile([]byte("test"), nil) if err == nil { t.Fatal("Expected error") @@ -67,6 +68,7 @@ func TestEncryptConfigFile(t *testing.T) { } func TestDecryptConfigFile(t *testing.T) { + t.Parallel() result, err := EncryptConfigFile([]byte("test"), []byte("key")) if err != nil { t.Fatal(err) @@ -135,8 +137,9 @@ func TestMakeNewSessionDK(t *testing.T) { } func TestEncryptTwiceReusesSaltButNewCipher(t *testing.T) { - c := &Config{} - c.EncryptConfig = 1 + c := &Config{ + EncryptConfig: 1, + } tempDir, err := ioutil.TempDir("", "") if err != nil { t.Fatalf("Problem creating temp dir at %s: %s\n", tempDir, err) @@ -148,8 +151,14 @@ func TestEncryptTwiceReusesSaltButNewCipher(t *testing.T) { if err != nil { t.Fatalf("Problem creating temp file at %s: %s\n", tempDir, err) } - passFile.WriteString("pass\npass\n") - passFile.Close() + _, err = passFile.WriteString("pass\npass\n") + if err != nil { + t.Error(err) + } + err = passFile.Close() + if err != nil { + t.Error(err) + } // Temporarily replace Stdin with a custom input oldIn := os.Stdin @@ -179,7 +188,7 @@ func TestEncryptTwiceReusesSaltButNewCipher(t *testing.T) { if err != nil { t.Fatalf("Problem reading file %s: %s\n", enc2, err) } - // legth of prefix + salt + // length of prefix + salt l := len(EncryptConfirmString+SaltPrefix) + SaltRandomLength // Even though prefix, including salt with the random bytes is the same if !bytes.Equal(data1[:l], data2[:l]) { @@ -285,6 +294,7 @@ func TestReadConfigWithPrompt(t *testing.T) { } func TestReadEncryptedConfigFromReader(t *testing.T) { + t.Parallel() keyProvider := func() ([]byte, error) { return []byte("pass"), nil } // Encrypted conf for: `{"name":"test"}` with key `pass` confBytes := []byte{84, 72, 79, 82, 83, 45, 72, 65, 77, 77, 69, 82, 126, 71, 67, 84, 126, 83, 79, 126, 83, 65, 76, 84, 89, 126, 246, 110, 128, 3, 30, 168, 172, 160, 198, 176, 136, 62, 152, 155, 253, 176, 16, 48, 52, 246, 44, 29, 151, 47, 217, 226, 178, 12, 218, 113, 248, 172, 195, 232, 136, 104, 9, 199, 20, 4, 71, 4, 253, 249} diff --git a/config/config_test.go b/config/config_test.go index c399c576..15233761 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1,12 +1,14 @@ package config import ( + "errors" "io/ioutil" "os" "path/filepath" "runtime" "strings" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/convert" @@ -22,12 +24,10 @@ import ( ) const ( - // Default number of enabled exchanges. Modify this whenever an exchange is - // added or removed - defaultEnabledExchanges = 28 - testFakeExchangeName = "Stampbit" - testPair = "BTC-USD" - testString = "test" + testFakeExchangeName = "Stampbit" + testPair = "BTC-USD" + testString = "test" + bfx = "Bitfinex" ) func TestGetNonExistentDefaultFilePathDoesNotCreateDefaultDir(t *testing.T) { @@ -42,21 +42,28 @@ func TestGetNonExistentDefaultFilePathDoesNotCreateDefaultDir(t *testing.T) { } func TestGetCurrencyConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetCurrencyConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Currency: CurrencyConfig{ + ForeignExchangeUpdateDuration: time.Second, + }, + } + cCFG := cfg.GetCurrencyConfig() + if cCFG.ForeignExchangeUpdateDuration != cfg.Currency.ForeignExchangeUpdateDuration { + t.Error("did not retrieve correct currency config") } - _ = cfg.GetCurrencyConfig() } func TestGetClientBankAccounts(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Fatal("GetExchangeBankAccounts LoadConfig error", err) - } - _, err = cfg.GetClientBankAccounts("Kraken", "USD") + t.Parallel() + cfg := &Config{BankAccounts: []banking.Account{ + { + SupportedCurrencies: "USD", + SupportedExchanges: "Kraken", + }, + }} + + _, err := cfg.GetClientBankAccounts("Kraken", "USD") if err != nil { t.Error("GetExchangeBankAccounts error", err) } @@ -67,12 +74,21 @@ func TestGetClientBankAccounts(t *testing.T) { } func TestGetExchangeBankAccounts(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetExchangeBankAccounts LoadConfig error", err) + t.Parallel() + + cfg := &Config{ + Exchanges: []ExchangeConfig{{ + Name: bfx, + Enabled: true, + BankAccounts: []banking.Account{ + { + SupportedCurrencies: "USD", + SupportedExchanges: bfx, + }, + }, + }}, } - _, err = cfg.GetExchangeBankAccounts("Bitfinex", "", "USD") + _, err := cfg.GetExchangeBankAccounts(bfx, "", "USD") if err != nil { t.Error("GetExchangeBankAccounts error", err) } @@ -83,32 +99,61 @@ func TestGetExchangeBankAccounts(t *testing.T) { } func TestCheckBankAccountConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetExchangeBankAccounts LoadConfig error", err) + t.Parallel() + cfg := &Config{ + BankAccounts: []banking.Account{ + { + Enabled: true, + }, + }, } - cfg.BankAccounts[0].Enabled = true cfg.CheckBankAccountConfig() + if cfg.BankAccounts[0].Enabled { + t.Error("validation should have changed it to false") + } + cfg.BankAccounts[0] = banking.Account{ + Enabled: true, + ID: "1337", + BankName: "1337", + BankAddress: "1337", + BankPostalCode: "1337", + BankPostalCity: "1337", + BankCountry: "1337", + AccountName: "1337", + AccountNumber: "1337", + SWIFTCode: "1337", + IBAN: "1337", + BSBNumber: "1337", + BankCode: 1337, + SupportedCurrencies: "1337", + SupportedExchanges: "1337", + } + cfg.CheckBankAccountConfig() + if !cfg.BankAccounts[0].Enabled { + t.Error("validation should have not have changed result") + } } func TestUpdateExchangeBankAccounts(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("UpdateExchangeBankAccounts LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Name: bfx, + Enabled: true, + }, + }, } - b := []banking.Account{{Enabled: false}} - err = cfg.UpdateExchangeBankAccounts("Bitfinex", b) + err := cfg.UpdateExchangeBankAccounts(bfx, b) if err != nil { t.Error("UpdateExchangeBankAccounts error", err) } var count int - for _, exch := range cfg.Exchanges { - if exch.Name == "Bitfinex" { - if !exch.BankAccounts[0].Enabled { + for i := range cfg.Exchanges { + if cfg.Exchanges[i].Name == bfx { + if !cfg.Exchanges[i].BankAccounts[0].Enabled { count++ } } @@ -124,13 +169,17 @@ func TestUpdateExchangeBankAccounts(t *testing.T) { } func TestUpdateClientBankAccounts(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("UpdateClientBankAccounts LoadConfig error", err) + t.Parallel() + cfg := &Config{ + BankAccounts: []banking.Account{ + { + BankName: testString, + AccountNumber: "1337", + }, + }, } - b := banking.Account{Enabled: false, BankName: testString, AccountNumber: "0234"} - err = cfg.UpdateClientBankAccounts(&b) + b := banking.Account{Enabled: false, BankName: testString, AccountNumber: "1337"} + err := cfg.UpdateClientBankAccounts(&b) if err != nil { t.Error("UpdateClientBankAccounts error", err) } @@ -154,18 +203,12 @@ func TestUpdateClientBankAccounts(t *testing.T) { } func TestCheckClientBankAccounts(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("CheckClientBankAccounts LoadConfig error", err) - } - - cfg.BankAccounts = nil + t.Parallel() + cfg := &Config{} cfg.CheckClientBankAccounts() if len(cfg.BankAccounts) == 0 { - t.Error("CheckClientBankAccounts error:", err) + t.Error("expected a placeholder account") } - cfg.BankAccounts = nil cfg.BankAccounts = []banking.Account{ { @@ -288,19 +331,24 @@ func TestPurgeExchangeCredentials(t *testing.T) { } func TestGetCommunicationsConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetCommunicationsConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Communications: base.CommunicationsConfig{ + SlackConfig: base.SlackConfig{Name: "hellomoto"}, + }, + } + cCFG := cfg.GetCommunicationsConfig() + if cCFG.SlackConfig.Name != cfg.Communications.SlackConfig.Name { + t.Error("failed to retrieve config") } - _ = cfg.GetCommunicationsConfig() } func TestUpdateCommunicationsConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("UpdateCommunicationsConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Communications: base.CommunicationsConfig{ + SlackConfig: base.SlackConfig{Name: "hellomoto"}, + }, } cfg.UpdateCommunicationsConfig(&base.CommunicationsConfig{SlackConfig: base.SlackConfig{Name: testString}}) if cfg.Communications.SlackConfig.Name != testString { @@ -309,38 +357,40 @@ func TestUpdateCommunicationsConfig(t *testing.T) { } func TestGetCryptocurrencyProviderConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetCryptocurrencyProviderConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Currency: CurrencyConfig{ + CryptocurrencyProvider: CryptocurrencyProvider{ + Name: "hellomoto", + }, + }, + } + cCFG := cfg.GetCryptocurrencyProviderConfig() + if cCFG.Name != cfg.Currency.CryptocurrencyProvider.Name { + t.Error("failed to retrieve config") } - _ = cfg.GetCryptocurrencyProviderConfig() } func TestUpdateCryptocurrencyProviderConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("UpdateCryptocurrencyProviderConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Currency: CurrencyConfig{ + CryptocurrencyProvider: CryptocurrencyProvider{ + Name: "hellomoto", + }, + }, } - - orig := cfg.GetCryptocurrencyProviderConfig() cfg.UpdateCryptocurrencyProviderConfig(CryptocurrencyProvider{Name: "SERIOUS TESTING PROCEDURE!"}) if cfg.Currency.CryptocurrencyProvider.Name != "SERIOUS TESTING PROCEDURE!" { t.Error("UpdateCurrencyProviderConfig LoadConfig error") } - - cfg.UpdateCryptocurrencyProviderConfig(orig) } func TestCheckCommunicationsConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("CheckCommunicationsConfig LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Communications: base.CommunicationsConfig{}, } - - cfg.Communications = base.CommunicationsConfig{} cfg.CheckCommunicationsConfig() if cfg.Communications.SlackConfig.Name != "Slack" || cfg.Communications.SMSGlobalConfig.Name != "SMSGlobal" || @@ -354,7 +404,7 @@ func TestCheckCommunicationsConfig(t *testing.T) { cfg.Communications.SMSGlobalConfig.Name = "" cfg.CheckCommunicationsConfig() if cfg.Communications.SMSGlobalConfig.Password != testString { - t.Error("CheckCommunicationsConfig error:", err) + t.Error("incorrect password") } cfg.SMS.Contacts = append(cfg.SMS.Contacts, base.SMSContact{ @@ -365,7 +415,7 @@ func TestCheckCommunicationsConfig(t *testing.T) { cfg.Communications.SMSGlobalConfig.Name = "" cfg.CheckCommunicationsConfig() if cfg.Communications.SMSGlobalConfig.Contacts[0].Name != "Bobby" { - t.Error("CheckCommunicationsConfig error:", err) + t.Error("incorrect name") } cfg.Communications.SMSGlobalConfig.From = "" @@ -497,7 +547,6 @@ func TestSupportsExchangeAssetType(t *testing.T) { func TestSetPairs(t *testing.T) { t.Parallel() - var c Config pairs := currency.Pairs{ currency.NewPair(currency.BTC, currency.USD), @@ -544,7 +593,6 @@ func TestSetPairs(t *testing.T) { func TestGetCurrencyPairConfig(t *testing.T) { t.Parallel() - var c Config _, err := c.GetCurrencyPairConfig("asdfg", asset.Spot) if err == nil { @@ -602,7 +650,6 @@ func TestCheckPairConfigFormats(t *testing.T) { if err := c.CheckPairConfigFormats("non-existent"); err == nil { t.Error("non-existent exchange should throw an error") } - // Test nil pair store c.Exchanges = append(c.Exchanges, ExchangeConfig{ @@ -851,14 +898,26 @@ func TestCheckPairConsistency(t *testing.T) { } func TestSupportsPair(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "TestSupportsPair. LoadConfig Error: %s", err.Error(), - ) + t.Parallel() + fmt := ¤cy.PairFormat{} + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Name: bfx, + Enabled: true, + CurrencyPairs: ¤cy.PairsManager{ + Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: []currency.Pair{currency.NewPair(currency.BTC, currency.USD)}, + ConfigFormat: fmt, + RequestFormat: fmt, + }, + }, + }, + }, + }, } - assetType := asset.Spot if cfg.SupportsPair("asdf", currency.NewPair(currency.BTC, currency.USD), assetType) { @@ -867,10 +926,9 @@ func TestSupportsPair(t *testing.T) { ) } - if !cfg.SupportsPair("Bitfinex", - currency.NewPair(currency.BTC, currency.USD), assetType) { + if !cfg.SupportsPair(bfx, currency.NewPair(currency.BTC, currency.USD), assetType) { t.Errorf( - "TestSupportsPair. Incorrect values. Err: %s", err, + "expected true", ) } } @@ -1065,22 +1123,16 @@ func TestGetEnabledPairs(t *testing.T) { } func TestGetEnabledExchanges(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "TestGetEnabledExchanges. LoadConfig Error: %s", err.Error(), - ) - } + t.Parallel() + cfg := &Config{Exchanges: []ExchangeConfig{ + { + Name: bfx, + Enabled: true, + }, + }} exchanges := cfg.GetEnabledExchanges() - if len(exchanges) != defaultEnabledExchanges { - t.Error( - "TestGetEnabledExchanges. Enabled exchanges value mismatch", - ) - } - - if !common.StringDataCompare(exchanges, "Bitfinex") { + if !common.StringDataCompare(exchanges, bfx) { t.Error( "TestGetEnabledExchanges. Expected exchange Bitfinex not found", ) @@ -1088,14 +1140,13 @@ func TestGetEnabledExchanges(t *testing.T) { } func TestGetDisabledExchanges(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "TestGetDisabledExchanges. LoadConfig Error: %s", err.Error(), - ) - } - + t.Parallel() + cfg := &Config{Exchanges: []ExchangeConfig{ + { + Name: bfx, + Enabled: true, + }, + }} exchanges := cfg.GetDisabledExchanges() if len(exchanges) != 0 { t.Error( @@ -1103,7 +1154,7 @@ func TestGetDisabledExchanges(t *testing.T) { ) } - exchCfg, err := cfg.GetExchangeConfig("Bitfinex") + exchCfg, err := cfg.GetExchangeConfig(bfx) if err != nil { t.Errorf( "TestGetDisabledExchanges. GetExchangeConfig Error: %s", err.Error(), @@ -1126,26 +1177,27 @@ func TestGetDisabledExchanges(t *testing.T) { } func TestCountEnabledExchanges(t *testing.T) { - GetConfigEnabledExchanges := GetConfig() - err := GetConfigEnabledExchanges.LoadConfig(TestFile, true) - if err != nil { - t.Error( - "GetConfigEnabledExchanges load config error: " + err.Error(), - ) - } - enabledExch := GetConfigEnabledExchanges.CountEnabledExchanges() - if enabledExch != defaultEnabledExchanges { - t.Errorf("Expected %v, Received %v", defaultEnabledExchanges, enabledExch) + t.Parallel() + cfg := &Config{Exchanges: []ExchangeConfig{ + { + Enabled: true, + }, + }} + enabledExch := cfg.CountEnabledExchanges() + if enabledExch != 1 { + t.Errorf("Expected %v, Received %v", 1, enabledExch) } } func TestGetCurrencyPairDisplayConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "GetCurrencyPairDisplayConfig. LoadConfig Error: %s", err.Error(), - ) + t.Parallel() + cfg := &Config{ + Currency: CurrencyConfig{ + CurrencyPairFormat: &CurrencyPairFormatConfig{ + Delimiter: "-", + Uppercase: true, + }, + }, } settings := cfg.GetCurrencyPairDisplayConfig() if settings.Delimiter != "-" || !settings.Uppercase { @@ -1156,42 +1208,50 @@ func TestGetCurrencyPairDisplayConfig(t *testing.T) { } func TestGetAllExchangeConfigs(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetAllExchangeConfigs. LoadConfig error", err) + t.Parallel() + cfg := &Config{ + Exchanges: []ExchangeConfig{ + {}, + }, } - if len(cfg.GetAllExchangeConfigs()) < 26 { + if len(cfg.GetAllExchangeConfigs()) != 1 { t.Error("GetAllExchangeConfigs error") } } func TestGetExchangeConfig(t *testing.T) { - GetExchangeConfig := GetConfig() - err := GetExchangeConfig.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "GetExchangeConfig.LoadConfig Error: %s", err.Error(), - ) + t.Parallel() + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Name: bfx, + }, + }, } - _, err = GetExchangeConfig.GetExchangeConfig("Bitfinex") + _, err := cfg.GetExchangeConfig(bfx) if err != nil { t.Errorf("GetExchangeConfig.GetExchangeConfig Error: %s", err.Error()) } - _, err = GetExchangeConfig.GetExchangeConfig("Testy") - if err == nil { - t.Error("GetExchangeConfig.GetExchangeConfig Expected error") + _, err = cfg.GetExchangeConfig("Testy") + if !errors.Is(err, ErrExchangeNotFound) { + t.Errorf("received '%v' expected '%v'", err, ErrExchangeNotFound) } } func TestGetForexProviderConfig(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetForexProviderConfig. LoadConfig error", err) + t.Parallel() + fxr := "Fixer" + cfg := &Config{ + Currency: CurrencyConfig{ + ForexProviders: []currency.FXSettings{ + { + Name: fxr, + }, + }, + }, } - _, err = cfg.GetForexProvider("Fixer") + _, err := cfg.GetForexProvider(fxr) if err != nil { t.Error("GetForexProviderConfig error", err) } @@ -1203,25 +1263,37 @@ func TestGetForexProviderConfig(t *testing.T) { } func TestGetForexProviders(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error(err) + t.Parallel() + fxr := "Fixer" + cfg := &Config{ + Currency: CurrencyConfig{ + ForexProviders: []currency.FXSettings{ + { + Name: fxr, + }, + }, + }, } - - if r := cfg.GetForexProviders(); len(r) != 6 { + if r := cfg.GetForexProviders(); len(r) != 1 { t.Error("unexpected length of forex providers") } } func TestGetPrimaryForexProvider(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Error("GetPrimaryForexProvider. LoadConfig error", err) + t.Parallel() + fxr := "Fixer" + cfg := &Config{ + Currency: CurrencyConfig{ + ForexProviders: []currency.FXSettings{ + { + Name: fxr, + PrimaryProvider: true, + }, + }, + }, } primary := cfg.GetPrimaryForexProvider() - if primary == "" { + if primary != fxr { t.Error("GetPrimaryForexProvider error") } @@ -1235,25 +1307,29 @@ func TestGetPrimaryForexProvider(t *testing.T) { } func TestUpdateExchangeConfig(t *testing.T) { - c := GetConfig() - err := c.LoadConfig(TestFile, true) - if err != nil { - t.Error(err) + t.Parallel() + ok := "OKEX" + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Name: ok, + API: APIConfig{Credentials: APICredentialsConfig{}}, + }, + }, } - e := &ExchangeConfig{} - err = c.UpdateExchangeConfig(e) + err := cfg.UpdateExchangeConfig(e) if err == nil { t.Error("Expected error from non-existent exchange") } - e, err = c.GetExchangeConfig("OKEX") + e, err = cfg.GetExchangeConfig(ok) if err != nil { t.Error(err) } e.API.Credentials.Key = "test1234" - err = c.UpdateExchangeConfig(e) + err = cfg.UpdateExchangeConfig(e) if err != nil { t.Error(err) } @@ -1481,7 +1557,10 @@ func TestCheckExchangeConfigValues(t *testing.T) { cfg.Exchanges[0].API.Credentials.Secret = "Secret" cfg.Exchanges[0].API.AuthenticatedSupport = true cfg.Exchanges[0].API.AuthenticatedWebsocketSupport = true - cfg.CheckExchangeConfigValues() + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } if cfg.Exchanges[0].API.AuthenticatedSupport || cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected authenticated endpoints to be false from invalid API keys") @@ -1493,7 +1572,10 @@ func TestCheckExchangeConfigValues(t *testing.T) { cfg.Exchanges[0].API.AuthenticatedWebsocketSupport = true cfg.Exchanges[0].API.Credentials.ClientID = DefaultAPIClientID cfg.Exchanges[0].API.Credentials.Secret = "TESTYTEST" - cfg.CheckExchangeConfigValues() + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } if cfg.Exchanges[0].API.AuthenticatedSupport || cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected AuthenticatedAPISupport to be false from invalid API keys") @@ -1505,7 +1587,10 @@ func TestCheckExchangeConfigValues(t *testing.T) { cfg.Exchanges[0].API.Credentials.Key = "meow" cfg.Exchanges[0].API.Credentials.Secret = "test123" cfg.Exchanges[0].API.Credentials.ClientID = "clientIDerino" - cfg.CheckExchangeConfigValues() + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } if !cfg.Exchanges[0].API.AuthenticatedSupport || !cfg.Exchanges[0].API.AuthenticatedWebsocketSupport { t.Error("Expected AuthenticatedAPISupport and AuthenticatedWebsocketAPISupport to be false from invalid API keys") @@ -1517,7 +1602,10 @@ func TestCheckExchangeConfigValues(t *testing.T) { // Test empty exchange name for an enabled exchange cfg.Exchanges[0].Enabled = true cfg.Exchanges[0].Name = "" - cfg.CheckExchangeConfigValues() + err = cfg.CheckExchangeConfigValues() + if err != nil { + t.Error(err) + } if cfg.Exchanges[0].Enabled { t.Errorf( "Exchange with no name should be empty", @@ -1610,14 +1698,35 @@ func TestCheckExchangeConfigValues(t *testing.T) { } func TestRetrieveConfigCurrencyPairs(t *testing.T) { - cfg := GetConfig() - err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "TestRetrieveConfigCurrencyPairs.LoadConfig: %s", err.Error(), - ) + t.Parallel() + cp1 := currency.NewPair(currency.DOGE, currency.XRP) + cp2 := currency.NewPair(currency.DOGE, currency.USD) + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Enabled: true, + BaseCurrencies: currency.Currencies{ + currency.USD, + }, + CurrencyPairs: ¤cy.PairsManager{ + RequestFormat: nil, + ConfigFormat: nil, + UseGlobalFormat: false, + LastUpdated: 0, + Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: currency.Pairs{cp1, cp2}, + Enabled: currency.Pairs{cp1}, + ConfigFormat: ¤cy.PairFormat{}, + RequestFormat: ¤cy.PairFormat{}, + }, + }, + }, + }, + }, } - err = cfg.RetrieveConfigCurrencyPairs(true, asset.Spot) + err := cfg.RetrieveConfigCurrencyPairs(true, asset.Spot) if err != nil { t.Errorf( "TestRetrieveConfigCurrencyPairs.RetrieveConfigCurrencyPairs: %s", @@ -1635,19 +1744,20 @@ func TestRetrieveConfigCurrencyPairs(t *testing.T) { } func TestReadConfigFromFile(t *testing.T) { - readConfig := GetConfig() - err := readConfig.ReadConfigFromFile(TestFile, true) + cfg := &Config{} + err := cfg.ReadConfigFromFile(TestFile, true) if err != nil { t.Errorf("TestReadConfig %s", err.Error()) } - err = readConfig.ReadConfigFromFile("bla", true) + err = cfg.ReadConfigFromFile("bla", true) if err == nil { t.Error("TestReadConfig error cannot be nil") } } func TestReadConfigFromReader(t *testing.T) { + t.Parallel() confString := `{"name":"test"}` conf, encrypted, err := ReadConfig(strings.NewReader(confString), Unencrypted) if err != nil { @@ -1667,21 +1777,21 @@ func TestReadConfigFromReader(t *testing.T) { } func TestLoadConfig(t *testing.T) { - loadConfig := GetConfig() - err := loadConfig.LoadConfig(TestFile, true) + cfg := &Config{} + err := cfg.LoadConfig(TestFile, true) if err != nil { t.Error("TestLoadConfig " + err.Error()) } - err = loadConfig.LoadConfig("testy", true) + err = cfg.LoadConfig("testy", true) if err == nil { t.Error("TestLoadConfig Expected error") } } func TestSaveConfigToFile(t *testing.T) { - saveConfig := GetConfig() - err := saveConfig.LoadConfig(TestFile, true) + cfg := &Config{} + err := cfg.LoadConfig(TestFile, true) if err != nil { t.Errorf("TestSaveConfig.LoadConfig: %s", err.Error()) } @@ -1691,7 +1801,7 @@ func TestSaveConfigToFile(t *testing.T) { } f.Close() defer os.Remove(f.Name()) - err2 := saveConfig.SaveConfigToFile(f.Name()) + err2 := cfg.SaveConfigToFile(f.Name()) if err2 != nil { t.Errorf("TestSaveConfig.SaveConfig, %s", err2.Error()) } @@ -1722,6 +1832,7 @@ func TestDefaultFilePath(t *testing.T) { // means moving a users config file around), a way of getting around this is // to pass the datadir as a param line but adds a burden to everyone who // uses it + t.Parallel() result := DefaultFilePath() if !strings.Contains(result, File) && !strings.Contains(result, EncryptedFile) { @@ -1730,6 +1841,7 @@ func TestDefaultFilePath(t *testing.T) { } func TestGetFilePath(t *testing.T) { + t.Parallel() expected := "blah.json" result, wasDefault, _ := GetFilePath("blah.json") if result != "blah.json" { @@ -1792,13 +1904,36 @@ func TestCheckRemoteControlConfig(t *testing.T) { } func TestCheckConfig(t *testing.T) { - var c Config - err := c.LoadConfig(TestFile, true) - if err != nil { - t.Errorf("%s", err) + t.Parallel() + cp1 := currency.NewPair(currency.DOGE, currency.XRP) + cp2 := currency.NewPair(currency.DOGE, currency.USD) + cfg := &Config{ + Exchanges: []ExchangeConfig{ + { + Name: testFakeExchangeName, + Enabled: true, + BaseCurrencies: currency.Currencies{ + currency.USD, + }, + CurrencyPairs: ¤cy.PairsManager{ + RequestFormat: nil, + ConfigFormat: nil, + UseGlobalFormat: false, + LastUpdated: 0, + Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: currency.Pairs{cp1, cp2}, + Enabled: currency.Pairs{cp1}, + ConfigFormat: ¤cy.PairFormat{}, + RequestFormat: ¤cy.PairFormat{}, + }, + }, + }, + }, + }, } - - err = c.CheckConfig() + err := cfg.CheckConfig() if err != nil { t.Fatal(err) } @@ -1952,92 +2087,94 @@ func TestCheckDatabaseConfig(t *testing.T) { } func TestCheckNTPConfig(t *testing.T) { - c := GetConfig() + t.Parallel() + cfg := &Config{ + NTPClient: NTPClientConfig{}, + } - c.NTPClient.Level = 0 - c.NTPClient.Pool = nil - c.NTPClient.AllowedNegativeDifference = nil - c.NTPClient.AllowedDifference = nil + cfg.CheckNTPConfig() - c.CheckNTPConfig() - - if c.NTPClient.Pool[0] != "pool.ntp.org:123" { + if cfg.NTPClient.Pool[0] != "pool.ntp.org:123" { t.Error("ntpclient with no valid pool should default to pool.ntp.org") } - if c.NTPClient.AllowedDifference == nil { + if cfg.NTPClient.AllowedDifference == nil { t.Error("ntpclient with nil alloweddifference should default to sane value") } - if c.NTPClient.AllowedNegativeDifference == nil { + if cfg.NTPClient.AllowedNegativeDifference == nil { t.Error("ntpclient with nil allowednegativedifference should default to sane value") } } func TestCheckCurrencyConfigValues(t *testing.T) { - c := GetConfig() - c.Currency.ForexProviders = nil - c.Currency.CryptocurrencyProvider = CryptocurrencyProvider{} - err := c.CheckCurrencyConfigValues() + t.Parallel() + cfg := &Config{ + Currency: CurrencyConfig{}, + } + cfg.Currency.ForexProviders = nil + cfg.Currency.CryptocurrencyProvider = CryptocurrencyProvider{} + err := cfg.CheckCurrencyConfigValues() if err != nil { t.Error(err) } - if c.Currency.ForexProviders == nil { + if cfg.Currency.ForexProviders == nil { t.Error("Failed to populate c.Currency.ForexProviders") } - if c.Currency.CryptocurrencyProvider.APIkey != DefaultUnsetAPIKey { + if cfg.Currency.CryptocurrencyProvider.APIkey != DefaultUnsetAPIKey { t.Error("Failed to set the api key to the default key") } - if c.Currency.CryptocurrencyProvider.Name != "CoinMarketCap" { + if cfg.Currency.CryptocurrencyProvider.Name != "CoinMarketCap" { t.Error("Failed to set the c.Currency.CryptocurrencyProvider.Name") } - c.Currency.ForexProviders[0].Enabled = true - c.Currency.ForexProviders[0].Name = "CurrencyConverter" - c.Currency.ForexProviders[0].PrimaryProvider = true - c.Currency.Cryptocurrencies = nil - c.Cryptocurrencies = nil - c.Currency.CurrencyPairFormat = nil - c.CurrencyPairFormat = &CurrencyPairFormatConfig{ + cfg.Currency.ForexProviders[0].Enabled = true + cfg.Currency.ForexProviders[0].Name = "CurrencyConverter" + cfg.Currency.ForexProviders[0].PrimaryProvider = true + cfg.Currency.Cryptocurrencies = nil + cfg.Cryptocurrencies = nil + cfg.Currency.CurrencyPairFormat = nil + cfg.CurrencyPairFormat = &CurrencyPairFormatConfig{ Uppercase: true, } - c.Currency.FiatDisplayCurrency = currency.Code{} - c.FiatDisplayCurrency = ¤cy.BTC - c.Currency.CryptocurrencyProvider.Enabled = true - err = c.CheckCurrencyConfigValues() + cfg.Currency.FiatDisplayCurrency = currency.Code{} + cfg.FiatDisplayCurrency = ¤cy.BTC + cfg.Currency.CryptocurrencyProvider.Enabled = true + err = cfg.CheckCurrencyConfigValues() if err != nil { t.Error(err) } - if c.Currency.ForexProviders[0].Enabled { + if cfg.Currency.ForexProviders[0].Enabled { t.Error("Failed to disable invalid forex provider") } - if !c.Currency.CurrencyPairFormat.Uppercase { + if !cfg.Currency.CurrencyPairFormat.Uppercase { t.Error("Failed to apply c.CurrencyPairFormat format to c.Currency.CurrencyPairFormat") } - c.Currency.CryptocurrencyProvider.Enabled = false - c.Currency.CryptocurrencyProvider.APIkey = "" - c.Currency.CryptocurrencyProvider.AccountPlan = "" - c.FiatDisplayCurrency = ¤cy.BTC - c.Currency.ForexProviders[0].Enabled = true - c.Currency.ForexProviders[0].Name = "Name" - c.Currency.ForexProviders[0].PrimaryProvider = true - c.Currency.Cryptocurrencies = currency.Currencies{} - c.Cryptocurrencies = ¤cy.Currencies{} - err = c.CheckCurrencyConfigValues() + cfg.Currency.CryptocurrencyProvider.Enabled = false + cfg.Currency.CryptocurrencyProvider.APIkey = "" + cfg.Currency.CryptocurrencyProvider.AccountPlan = "" + cfg.FiatDisplayCurrency = ¤cy.BTC + cfg.Currency.ForexProviders[0].Enabled = true + cfg.Currency.ForexProviders[0].Name = "Name" + cfg.Currency.ForexProviders[0].PrimaryProvider = true + cfg.Currency.Cryptocurrencies = currency.Currencies{} + cfg.Cryptocurrencies = ¤cy.Currencies{} + err = cfg.CheckCurrencyConfigValues() if err != nil { t.Error(err) } - if c.FiatDisplayCurrency != nil { + if cfg.FiatDisplayCurrency != nil { t.Error("Failed to clear c.FiatDisplayCurrency") } - if c.Currency.CryptocurrencyProvider.APIkey != DefaultUnsetAPIKey || - c.Currency.CryptocurrencyProvider.AccountPlan != DefaultUnsetAccountPlan { + if cfg.Currency.CryptocurrencyProvider.APIkey != DefaultUnsetAPIKey || + cfg.Currency.CryptocurrencyProvider.AccountPlan != DefaultUnsetAccountPlan { t.Error("Failed to set CryptocurrencyProvider.APIkey and AccountPlan") } } func TestPreengineConfigUpgrade(t *testing.T) { + t.Parallel() var c Config if err := c.LoadConfig("../testdata/preengine_config.json", false); err != nil { t.Fatal(err) diff --git a/database/database.go b/database/database.go index 6ba98c11..d5770fe1 100644 --- a/database/database.go +++ b/database/database.go @@ -13,7 +13,7 @@ func (i *Instance) SetConfig(cfg *Config) error { return ErrNilInstance } if cfg == nil { - return errNilConfig + return ErrNilConfig } i.m.Lock() i.config = cfg diff --git a/database/database_test.go b/database/database_test.go index 6f66825b..400ccd20 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -20,8 +20,8 @@ func TestSetConfig(t *testing.T) { } err = inst.SetConfig(nil) - if !errors.Is(err, errNilConfig) { - t.Errorf("received %v, expected %v", err, errNilConfig) + if !errors.Is(err, ErrNilConfig) { + t.Errorf("received %v, expected %v", err, ErrNilConfig) } inst = nil diff --git a/database/database_types.go b/database/database_types.go index f47d129d..79d3d614 100644 --- a/database/database_types.go +++ b/database/database_types.go @@ -46,9 +46,10 @@ var ( DefaultSQLiteDatabase = "gocryptotrader.db" // ErrNilInstance for when a database is nil ErrNilInstance = errors.New("database instance is nil") - errNilConfig = errors.New("received nil config") - errNilSQL = errors.New("database SQL connection is nil") - errFailedPing = errors.New("unable to verify database is connected, failed ping") + // ErrNilConfig for when a config is nil + ErrNilConfig = errors.New("received nil config") + errNilSQL = errors.New("database SQL connection is nil") + errFailedPing = errors.New("unable to verify database is connected, failed ping") ) const ( diff --git a/database/drivers/postgres/postgres.go b/database/drivers/postgres/postgres.go index 30521856..5d616a38 100644 --- a/database/drivers/postgres/postgres.go +++ b/database/drivers/postgres/postgres.go @@ -11,6 +11,12 @@ import ( // Connect opens a connection to Postgres database and returns a pointer to database.DB func Connect(cfg *database.Config) (*database.Instance, error) { + if cfg == nil { + return nil, database.ErrNilConfig + } + if !cfg.Enabled { + return nil, database.ErrDatabaseSupportDisabled + } if cfg.SSLMode == "" { cfg.SSLMode = "disable" } diff --git a/database/repository/audit/audit_test.go b/database/repository/audit/audit_test.go index 8dfc8e2f..d2aa85a0 100644 --- a/database/repository/audit/audit_test.go +++ b/database/repository/audit/audit_test.go @@ -83,16 +83,13 @@ func TestAudit(t *testing.T) { if !testhelpers.CheckValidConfig(&test.config.ConnectionDetails) { t.Skip("database not configured skipping test") } - dbConn, err := testhelpers.ConnectToDatabase(test.config) if err != nil { t.Fatal(err) } - if test.runner != nil { test.runner(t) } - if test.closer != nil { err = test.closer(dbConn) if err != nil { diff --git a/database/repository/datahistoryjob/datahistoryjob_test.go b/database/repository/datahistoryjob/datahistoryjob_test.go index 57a27168..a3603d82 100644 --- a/database/repository/datahistoryjob/datahistoryjob_test.go +++ b/database/repository/datahistoryjob/datahistoryjob_test.go @@ -124,8 +124,8 @@ func TestDataHistoryJob(t *testing.T) { Asset: asset.Spot.String(), Base: currency.BTC.String(), Quote: currency.USD.String(), - StartDate: time.Now().Add(time.Duration(i) * time.Second), - EndDate: time.Now().Add(time.Minute * time.Duration(i)), + StartDate: time.Now().Add(time.Duration(i+1) * time.Second).UTC(), + EndDate: time.Now().Add(time.Minute * time.Duration(i+1)).UTC(), Interval: int64(i), }) } @@ -144,8 +144,8 @@ func TestDataHistoryJob(t *testing.T) { Asset: asset.Spot.String(), Base: currency.BTC.String(), Quote: currency.USD.String(), - StartDate: time.Now().Add(time.Duration(i) * time.Second), - EndDate: time.Now().Add(time.Minute * time.Duration(i)), + StartDate: time.Now().Add(time.Duration(i+1) * time.Second).UTC(), + EndDate: time.Now().Add(time.Minute * time.Duration(i+1)).UTC(), Interval: int64(i), } if i == 19 { @@ -179,7 +179,7 @@ func TestDataHistoryJob(t *testing.T) { t.Errorf("expected 19, received %v", len(results)) } - jerb, err := db.getJobAndAllResultsPostgres(jerberoos[0].Nickname) + jerb, err := db.GetJobAndAllResults(jerberoos[0].Nickname) if err != nil { t.Fatal(err) } diff --git a/database/repository/trade/trade.go b/database/repository/trade/trade.go index c79de5ca..e7ed382f 100644 --- a/database/repository/trade/trade.go +++ b/database/repository/trade/trade.go @@ -107,7 +107,7 @@ func verifyTradeInIntervalsSqlite(ctx context.Context, tx *sql.Tx, exchangeName, quote, irh.Ranges[i].Intervals[j].Start.Time.UTC().Format(time.RFC3339), irh.Ranges[i].Intervals[j].End.Time.UTC().Format(time.RFC3339))).One(ctx, tx) - if err != nil { + if err != nil && err != sql.ErrNoRows { return err } if result != nil { @@ -126,14 +126,14 @@ func verifyTradeInIntervalsPostgres(ctx context.Context, tx *sql.Tx, exchangeNam } for i := range irh.Ranges { for j := range irh.Ranges[i].Intervals { - result, err := postgres.Trades(qm.Where("exchange_name_id = ? AND asset = ? AND base = ? AND quote = ? timestamp between ? AND ?", + result, err := postgres.Trades(qm.Where("exchange_name_id = ? AND asset = ? AND base = ? AND quote = ? AND timestamp between ? AND ?", exch.ID, assetType, base, quote, - irh.Ranges[i].Intervals[j].Start.Time.UTC().Format(time.RFC3339), - irh.Ranges[i].Intervals[j].End.Time.UTC().Format(time.RFC3339))).One(ctx, tx) - if err != nil { + irh.Ranges[i].Intervals[j].Start.Time.UTC(), + irh.Ranges[i].Intervals[j].End.Time.UTC())).One(ctx, tx) + if err != nil && err != sql.ErrNoRows { return err } if result != nil { diff --git a/database/repository/trade/trade_test.go b/database/repository/trade/trade_test.go index 28b2e24c..e280f6a0 100644 --- a/database/repository/trade/trade_test.go +++ b/database/repository/trade/trade_test.go @@ -103,7 +103,7 @@ func tradeSQLTester(t *testing.T) { uu, _ := uuid.NewV4() trades = append(trades, Data{ ID: uu.String(), - Timestamp: firstTime.Add(time.Minute * time.Duration(i)), + Timestamp: firstTime.Add(time.Minute * time.Duration(i+1)), Exchange: testExchanges[0].Name, Base: currency.BTC.String(), Quote: currency.USD.String(), @@ -123,7 +123,7 @@ func tradeSQLTester(t *testing.T) { uu, _ := uuid.NewV4() trades2 = append(trades2, Data{ ID: uu.String(), - Timestamp: firstTime.Add(time.Minute * time.Duration(i)), + Timestamp: firstTime.Add(time.Minute * time.Duration(i+1)), Exchange: testExchanges[0].Name, Base: currency.BTC.String(), Quote: currency.USD.String(), @@ -171,7 +171,6 @@ func tradeSQLTester(t *testing.T) { if err != nil { t.Error(err) } - err = VerifyTradeInIntervals(testExchanges[0].Name, asset.Spot.String(), currency.BTC.String(), @@ -181,15 +180,10 @@ func tradeSQLTester(t *testing.T) { t.Error(err) } - if !ranges.HasDataAtDate(firstTime) { - t.Error("expected data") - } - err = DeleteTrades(trades...) if err != nil { t.Error(err) } - err = DeleteTrades(trades2...) if err != nil { t.Error(err) diff --git a/engine/apiserver_test.go b/engine/apiserver_test.go index 6a6c2082..0ceffbd7 100644 --- a/engine/apiserver_test.go +++ b/engine/apiserver_test.go @@ -8,9 +8,7 @@ import ( "net/http/httptest" "os" "reflect" - "sync" "testing" - "time" "github.com/thrasher-corp/gocryptotrader/config" ) @@ -61,15 +59,10 @@ func TestStartRESTServer(t *testing.T) { t.Errorf("error '%v', expected '%v'", err, errServerDisabled) } m.remoteConfig.DeprecatedRPC.Enabled = true - var wg sync.WaitGroup - wg.Add(1) - // this is difficult to test as a webserver actually starts, so quit if an immediate error is not received err = m.StartRESTServer() if err != nil { t.Fatal(err) } - time.Sleep(time.Second) - wg.Done() } func TestStartWebsocketServer(t *testing.T) { diff --git a/engine/communication_manager_test.go b/engine/communication_manager_test.go index 4d1a3d38..dab3ccdf 100644 --- a/engine/communication_manager_test.go +++ b/engine/communication_manager_test.go @@ -3,7 +3,6 @@ package engine import ( "errors" "testing" - "time" "github.com/thrasher-corp/gocryptotrader/communications" "github.com/thrasher-corp/gocryptotrader/communications/base" @@ -151,7 +150,6 @@ func TestPushEvent(t *testing.T) { t.Errorf("error '%v', expected '%v'", err, nil) } m.PushEvent(base.Event{}) - time.Sleep(time.Second) m.PushEvent(base.Event{}) m = nil m.PushEvent(base.Event{}) diff --git a/engine/database_connection.go b/engine/database_connection.go index 56b596e9..e5e9e42e 100644 --- a/engine/database_connection.go +++ b/engine/database_connection.go @@ -1,7 +1,6 @@ package engine import ( - "errors" "fmt" "sync" "sync/atomic" @@ -16,19 +15,11 @@ import ( // DatabaseConnectionManagerName is an exported subsystem name const DatabaseConnectionManagerName = "database" -var errDatabaseDisabled = errors.New("database support disabled") - // DatabaseConnectionManager holds the database connection and its status type DatabaseConnectionManager struct { started int32 shutdown chan struct{} - enabled bool - verbose bool - host string - username string - password string - database string - driver string + cfg database.Config wg sync.WaitGroup dbConn *database.Instance } @@ -57,13 +48,7 @@ func SetupDatabaseConnectionManager(cfg *database.Config) (*DatabaseConnectionMa } m := &DatabaseConnectionManager{ shutdown: make(chan struct{}), - enabled: cfg.Enabled, - verbose: cfg.Verbose, - host: cfg.Host, - username: cfg.Username, - password: cfg.Password, - database: cfg.Database, - driver: cfg.Driver, + cfg: *cfg, dbConn: database.DB, } err := m.dbConn.SetConfig(cfg) @@ -98,23 +83,23 @@ func (m *DatabaseConnectionManager) Start(wg *sync.WaitGroup) (err error) { log.Debugln(log.DatabaseMgr, "Database manager starting...") - if m.enabled { + if m.cfg.Enabled { m.shutdown = make(chan struct{}) - switch m.driver { + switch m.cfg.Driver { case database.DBPostgreSQL: log.Debugf(log.DatabaseMgr, "Attempting to establish database connection to host %s/%s utilising %s driver\n", - m.host, - m.database, - m.driver) - m.dbConn, err = dbpsql.Connect(m.dbConn.GetConfig()) + m.cfg.Host, + m.cfg.Database, + m.cfg.Driver) + m.dbConn, err = dbpsql.Connect(&m.cfg) case database.DBSQLite, database.DBSQLite3: log.Debugf(log.DatabaseMgr, "Attempting to establish database connection to %s utilising %s driver\n", - m.database, - m.driver) - m.dbConn, err = dbsqlite3.Connect(m.database) + m.cfg.Database, + m.cfg.Driver) + m.dbConn, err = dbsqlite3.Connect(m.cfg.Database) default: return database.ErrNoDatabaseProvided } @@ -128,7 +113,7 @@ func (m *DatabaseConnectionManager) Start(wg *sync.WaitGroup) (err error) { return nil } - return errDatabaseDisabled + return database.ErrDatabaseSupportDisabled } // Stop stops the database manager and closes the connection @@ -185,7 +170,7 @@ func (m *DatabaseConnectionManager) checkConnection() error { if atomic.LoadInt32(&m.started) == 0 { return fmt.Errorf("%s %w", DatabaseConnectionManagerName, ErrSubSystemNotStarted) } - if !m.enabled { + if !m.cfg.Enabled { return database.ErrDatabaseSupportDisabled } if m.dbConn == nil { diff --git a/engine/database_connection_test.go b/engine/database_connection_test.go index 05894f91..168a39c5 100644 --- a/engine/database_connection_test.go +++ b/engine/database_connection_test.go @@ -60,8 +60,8 @@ func TestStartSQLite(t *testing.T) { } var wg sync.WaitGroup err = m.Start(&wg) - if !errors.Is(err, errDatabaseDisabled) { - t.Errorf("error '%v', expected '%v'", err, errDatabaseDisabled) + if !errors.Is(err, database.ErrDatabaseSupportDisabled) { + t.Errorf("error '%v', expected '%v'", err, database.ErrDatabaseSupportDisabled) } m, err = SetupDatabaseConnectionManager(&database.Config{Enabled: true}) if !errors.Is(err, nil) { @@ -71,10 +71,10 @@ func TestStartSQLite(t *testing.T) { if !errors.Is(err, database.ErrNoDatabaseProvided) { t.Errorf("error '%v', expected '%v'", err, database.ErrNoDatabaseProvided) } - m.driver = database.DBSQLite + m.cfg = database.Config{Driver: database.DBSQLite} err = m.Start(&wg) - if !errors.Is(err, database.ErrFailedToConnect) { - t.Errorf("error '%v', expected '%v'", err, database.ErrFailedToConnect) + if !errors.Is(err, database.ErrDatabaseSupportDisabled) { + t.Errorf("error '%v', expected '%v'", err, database.ErrDatabaseSupportDisabled) } _, err = SetupDatabaseConnectionManager(&database.Config{ Enabled: true, @@ -91,23 +91,21 @@ func TestStartSQLite(t *testing.T) { // This test does not care for a successful connection func TestStartPostgres(t *testing.T) { - tmpDir := CreateDatabase(t) - defer Cleanup(tmpDir) m, err := SetupDatabaseConnectionManager(&database.Config{}) if !errors.Is(err, nil) { t.Errorf("error '%v', expected '%v'", err, nil) } var wg sync.WaitGroup err = m.Start(&wg) - if !errors.Is(err, errDatabaseDisabled) { - t.Errorf("error '%v', expected '%v'", err, errDatabaseDisabled) + if !errors.Is(err, database.ErrDatabaseSupportDisabled) { + t.Errorf("error '%v', expected '%v'", err, database.ErrDatabaseSupportDisabled) } - m.enabled = true + m.cfg.Enabled = true err = m.Start(&wg) if !errors.Is(err, database.ErrNoDatabaseProvided) { t.Errorf("error '%v', expected '%v'", err, database.ErrNoDatabaseProvided) } - m.driver = database.DBPostgreSQL + m.cfg.Driver = database.DBPostgreSQL err = m.Start(&wg) if !errors.Is(err, database.ErrFailedToConnect) { t.Errorf("error '%v', expected '%v'", err, database.ErrFailedToConnect) diff --git a/engine/datahistory_manager.go b/engine/datahistory_manager.go index 10694f25..18506e2a 100644 --- a/engine/datahistory_manager.go +++ b/engine/datahistory_manager.go @@ -181,7 +181,7 @@ func (m *DataHistoryManager) compareJobsToData(jobs ...*DataHistoryJob) error { jobs[i].rangeHolder.SetHasDataFromCandles(candles.Candles) case dataHistoryTradeDataType: err := m.tradeLoader(jobs[i].Exchange, jobs[i].Asset.String(), jobs[i].Pair.Base.String(), jobs[i].Pair.Quote.String(), jobs[i].rangeHolder) - if err != nil && !errors.Is(err, sql.ErrNoRows) { + if err != nil && err != sql.ErrNoRows { return fmt.Errorf("%s could not load trade data: %w", jobs[i].Nickname, err) } default: @@ -682,7 +682,7 @@ func (m *DataHistoryManager) GetByNickname(nickname string, fullDetails bool) (* // now try the database j, err := m.jobDB.GetByNickName(nickname) if err != nil { - if errors.Is(err, sql.ErrNoRows) { + if err == sql.ErrNoRows { // no need to display normal sql err to user return nil, errJobNotFound } diff --git a/engine/datahistory_manager_test.go b/engine/datahistory_manager_test.go index a0137102..21681012 100644 --- a/engine/datahistory_manager_test.go +++ b/engine/datahistory_manager_test.go @@ -812,7 +812,7 @@ func createDHM(t *testing.T) *DataHistoryManager { em := SetupExchangeManager() exch, err := em.NewExchangeByName(testExchange) if !errors.Is(err, nil) { - t.Errorf("error '%v', expected '%v'", err, nil) + t.Fatalf("error '%v', expected '%v'", err, nil) } cp := currency.NewPair(currency.BTC, currency.USD) exch.SetDefaults() @@ -826,7 +826,7 @@ func createDHM(t *testing.T) *DataHistoryManager { exch2, err := em.NewExchangeByName("Binance") if !errors.Is(err, nil) { - t.Errorf("error '%v', expected '%v'", err, nil) + t.Fatalf("error '%v', expected '%v'", err, nil) } cp2 := currency.NewPair(currency.BTC, currency.USDT) exch2.SetDefaults() diff --git a/engine/engine_test.go b/engine/engine_test.go index befe2d80..d2988370 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "os" "testing" + "time" "github.com/thrasher-corp/gocryptotrader/config" ) @@ -165,8 +166,15 @@ func TestStartStopTwoDoesNotCausePanic(t *testing.T) { } func TestCheckExchangeExists(t *testing.T) { - e := CreateTestBot(t) - + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if !errors.Is(err, nil) { + t.Fatalf("received '%v' expected '%v'", err, nil) + } + exch.SetDefaults() + em.Add(exch) + e := &Engine{ExchangeManager: em} if e.GetExchangeByName(testExchange) == nil { t.Errorf("TestGetExchangeExists: Unable to find exchange") } @@ -177,12 +185,16 @@ func TestCheckExchangeExists(t *testing.T) { } func TestGetExchangeByName(t *testing.T) { - e := CreateTestBot(t) - - exch := e.GetExchangeByName(testExchange) - if exch == nil { - t.Errorf("TestGetExchangeByName: Failed to get exchange") + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if !errors.Is(err, nil) { + t.Fatalf("received '%v' expected '%v'", err, nil) } + exch.SetDefaults() + exch.SetEnabled(true) + em.Add(exch) + e := &Engine{ExchangeManager: em} if !exch.IsEnabled() { t.Errorf("TestGetExchangeByName: Unexpected result") @@ -205,9 +217,19 @@ func TestGetExchangeByName(t *testing.T) { } func TestUnloadExchange(t *testing.T) { - e := CreateTestBot(t) - - err := e.UnloadExchange("asdf") + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if !errors.Is(err, nil) { + t.Fatalf("received '%v' expected '%v'", err, nil) + } + exch.SetDefaults() + exch.SetEnabled(true) + em.Add(exch) + e := &Engine{ExchangeManager: em, + Config: &config.Config{Exchanges: []config.ExchangeConfig{{Name: testExchange}}}, + } + err = e.UnloadExchange("asdf") if !errors.Is(err, config.ErrExchangeNotFound) { t.Errorf("error '%v', expected '%v'", err, config.ErrExchangeNotFound) } @@ -225,30 +247,29 @@ func TestUnloadExchange(t *testing.T) { } func TestDryRunParamInteraction(t *testing.T) { - bot := CreateTestBot(t) - - // Simulate overiding default settings and ensure that enabling exchange - // verbose mode will be set on Bitfinex - var err error - if err = bot.UnloadExchange(testExchange); err != nil { + t.Parallel() + bot := &Engine{ + ExchangeManager: SetupExchangeManager(), + Settings: Settings{}, + Config: &config.Config{ + Exchanges: []config.ExchangeConfig{ + { + Name: testExchange, + WebsocketTrafficTimeout: time.Second, + }, + }, + }, + } + if err := bot.LoadExchange(testExchange, false, nil); err != nil { t.Error(err) } - - bot.Settings.CheckParamInteraction = false - bot.Settings.EnableExchangeVerbose = false - if err = bot.LoadExchange(testExchange, false, nil); err != nil { - t.Error(err) - } - exchCfg, err := bot.Config.GetExchangeConfig(testExchange) if err != nil { t.Error(err) } - if exchCfg.Verbose { t.Error("verbose should have been disabled") } - if err = bot.UnloadExchange(testExchange); err != nil { t.Error(err) } @@ -267,7 +288,6 @@ func TestDryRunParamInteraction(t *testing.T) { if err != nil { t.Error(err) } - if !bot.Settings.EnableDryRun || !exchCfg.Verbose { t.Error("dryrun should be true and verbose should be true") diff --git a/engine/event_manager_test.go b/engine/event_manager_test.go index 011297f2..bbe9a584 100644 --- a/engine/event_manager_test.go +++ b/engine/event_manager_test.go @@ -125,7 +125,7 @@ func TestEventManagerAdd(t *testing.T) { } exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Error(err) + t.Fatal(err) } exch.SetDefaults() em.Add(exch) @@ -181,7 +181,7 @@ func TestEventManagerRemove(t *testing.T) { } exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Error(err) + t.Fatal(err) } exch.SetDefaults() em.Add(exch) @@ -222,7 +222,7 @@ func TestGetEventCounter(t *testing.T) { } exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Error(err) + t.Fatal(err) } exch.SetDefaults() em.Add(exch) @@ -268,7 +268,7 @@ func TestCheckEventCondition(t *testing.T) { } exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Error(err) + t.Fatal(err) } exch.SetDefaults() em.Add(exch) diff --git a/engine/exchange_manager_test.go b/engine/exchange_manager_test.go index 86ac26be..6257813c 100644 --- a/engine/exchange_manager_test.go +++ b/engine/exchange_manager_test.go @@ -69,7 +69,7 @@ func TestNewExchangeByName(t *testing.T) { for i := range exchanges { exch, err := m.NewExchangeByName(exchanges[i]) if err != nil && exchanges[i] != "fake" { - t.Error(err) + t.Fatal(err) } if err == nil { exch.SetDefaults() diff --git a/engine/helpers_test.go b/engine/helpers_test.go index 799e7703..1c736eb8 100644 --- a/engine/helpers_test.go +++ b/engine/helpers_test.go @@ -16,6 +16,7 @@ import ( "time" "github.com/thrasher-corp/gocryptotrader/common" + "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/common/file" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" @@ -29,34 +30,73 @@ import ( var testExchange = "Bitstamp" func CreateTestBot(t *testing.T) *Engine { - bot, err := NewFromSettings(&Settings{ConfigFile: config.TestFile, EnableDryRun: true}, nil) - if err != nil { - t.Fatal(err) - } + cFormat := ¤cy.PairFormat{Uppercase: true} + cp1 := currency.NewPair(currency.BTC, currency.USD) + cp2 := currency.NewPair(currency.BTC, currency.USDT) - err = bot.Config.RetrieveConfigCurrencyPairs(true, asset.Spot) - if err != nil { - t.Fatalf("Failed to retrieve config currency pairs. %s", err) + pairs1 := map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: currency.Pairs{cp1}, + Enabled: currency.Pairs{cp1}, + }, } - bot.ExchangeManager = SetupExchangeManager() - if bot.GetExchangeByName(testExchange) == nil { - err := bot.LoadExchange(testExchange, false, nil) - if err != nil { - t.Fatalf("SetupTest: Failed to load exchange: %s", err) - } + pairs2 := map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Available: currency.Pairs{cp2}, + Enabled: currency.Pairs{cp2}, + }, + } + bot := &Engine{ + ExchangeManager: SetupExchangeManager(), + Config: &config.Config{Exchanges: []config.ExchangeConfig{ + { + Name: testExchange, + Enabled: true, + WebsocketTrafficTimeout: time.Second, + API: config.APIConfig{ + Credentials: config.APICredentialsConfig{}, + }, + CurrencyPairs: ¤cy.PairsManager{ + RequestFormat: cFormat, + ConfigFormat: cFormat, + UseGlobalFormat: true, + Pairs: pairs1, + }, + }, + { + Name: "binance", + Enabled: true, + WebsocketTrafficTimeout: time.Second, + API: config.APIConfig{ + Credentials: config.APICredentialsConfig{}, + }, + CurrencyPairs: ¤cy.PairsManager{ + RequestFormat: cFormat, + ConfigFormat: cFormat, + UseGlobalFormat: true, + Pairs: pairs2, + }, + }, + }}} + err := bot.LoadExchange(testExchange, false, nil) + if err != nil { + t.Fatalf("SetupTest: Failed to load exchange: %s", err) } return bot } func TestGetExchangeOTPs(t *testing.T) { + t.Parallel() bot := CreateTestBot(t) _, err := bot.GetExchangeOTPs() if err == nil { t.Fatal("Expected err with no exchange OTP secrets set") } - bfxCfg, err := bot.Config.GetExchangeConfig("Bitfinex") + bnCfg, err := bot.Config.GetExchangeConfig("binance") if err != nil { t.Fatal(err) } @@ -65,7 +105,7 @@ func TestGetExchangeOTPs(t *testing.T) { t.Fatal(err) } - bfxCfg.API.Credentials.OTPSecret = "JBSWY3DPEHPK3PXP" + bnCfg.API.Credentials.OTPSecret = "JBSWY3DPEHPK3PXP" bCfg.API.Credentials.OTPSecret = "JBSWY3DPEHPK3PXP" result, err := bot.GetExchangeOTPs() if err != nil { @@ -75,7 +115,7 @@ func TestGetExchangeOTPs(t *testing.T) { t.Fatal("Expected 2 OTP results") } - bfxCfg.API.Credentials.OTPSecret = "°" + bnCfg.API.Credentials.OTPSecret = "°" result, err = bot.GetExchangeOTPs() if err != nil { t.Fatal(err) @@ -85,11 +125,12 @@ func TestGetExchangeOTPs(t *testing.T) { } // Flush settings - bfxCfg.API.Credentials.OTPSecret = "" + bnCfg.API.Credentials.OTPSecret = "" bCfg.API.Credentials.OTPSecret = "" } func TestGetExchangeoOTPByName(t *testing.T) { + t.Parallel() bot := CreateTestBot(t) _, err := bot.GetExchangeOTPByName(testExchange) if err == nil { @@ -115,6 +156,7 @@ func TestGetExchangeoOTPByName(t *testing.T) { } func TestGetAuthAPISupportedExchanges(t *testing.T) { + t.Parallel() e := CreateTestBot(t) if result := e.GetAuthAPISupportedExchanges(); len(result) != 0 { t.Fatal("Unexpected result", result) @@ -131,6 +173,7 @@ func TestGetAuthAPISupportedExchanges(t *testing.T) { } func TestIsOnline(t *testing.T) { + t.Parallel() e := CreateTestBot(t) var err error e.connectionManager, err = setupConnectionManager(&e.Config.ConnectionMonitor) @@ -163,46 +206,60 @@ func TestIsOnline(t *testing.T) { } func TestGetSpecificAvailablePairs(t *testing.T) { + t.Parallel() e := CreateTestBot(t) + c := currency.Code{ + Item: ¤cy.Item{ + Role: currency.Cryptocurrency, + Symbol: "usdt", + }, + } + e.Config = &config.Config{ + Exchanges: []config.ExchangeConfig{ + { + Enabled: true, + Name: testExchange, + CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Enabled: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)}, + Available: currency.Pairs{currency.NewPair(currency.BTC, currency.USD), currency.NewPair(currency.BTC, c)}, + ConfigFormat: ¤cy.PairFormat{ + Uppercase: true, + }, + }, + }}, + }, + }, + } assetType := asset.Spot - result := e.GetSpecificAvailablePairs(true, true, true, false, assetType) - btsusd, err := currency.NewPairFromStrings("BTC", "USD") - if err != nil { - t.Fatal(err) + result := e.GetSpecificAvailablePairs(true, true, true, true, assetType) + btcUSD := currency.NewPair(currency.BTC, currency.USD) + if !result.Contains(btcUSD, true) { + t.Error("Unexpected result") } - if !result.Contains(btsusd, true) { - t.Fatal("Unexpected result") - } - - btcusdt, err := currency.NewPairFromStrings("BTC", "USDT") - if err != nil { - t.Fatal(err) - } - - if !result.Contains(btcusdt, false) { - t.Fatal("Unexpected result") + btcUSDT := currency.NewPair(currency.BTC, c) + if !result.Contains(btcUSDT, false) { + t.Error("Unexpected result") } result = e.GetSpecificAvailablePairs(true, true, false, false, assetType) - if result.Contains(btcusdt, false) { - t.Fatal("Unexpected result") - } - - ltcbtc, err := currency.NewPairFromStrings("LTC", "BTC") - if err != nil { - t.Fatal(err) + if result.Contains(btcUSDT, false) { + t.Error("Unexpected result") } + ltcBTC := currency.NewPair(currency.LTC, currency.BTC) result = e.GetSpecificAvailablePairs(true, false, false, true, assetType) - if !result.Contains(ltcbtc, false) { - t.Fatal("Unexpected result") + if result.Contains(ltcBTC, false) { + t.Error("Unexpected result") } } func TestIsRelatablePairs(t *testing.T) { + t.Parallel() CreateTestBot(t) xbtusd, err := currency.NewPairFromStrings("XBT", "USD") if err != nil { @@ -392,6 +449,7 @@ func TestIsRelatablePairs(t *testing.T) { } func TestGetRelatableCryptocurrencies(t *testing.T) { + t.Parallel() CreateTestBot(t) btcltc, err := currency.NewPairFromStrings("BTC", "LTC") if err != nil { @@ -415,63 +473,57 @@ func TestGetRelatableCryptocurrencies(t *testing.T) { p := GetRelatableCryptocurrencies(btcltc) if p.Contains(btcltc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if p.Contains(btcbtc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if p.Contains(ltcltc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if !p.Contains(btceth, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } p = GetRelatableCryptocurrencies(btcltc) if p.Contains(btcltc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if p.Contains(btcbtc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if p.Contains(ltcltc, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } if !p.Contains(btceth, true) { - t.Fatal("Unexpected result") + t.Error("Unexpected result") } } func TestGetRelatableFiatCurrencies(t *testing.T) { - CreateTestBot(t) - - btsusd, err := currency.NewPairFromStrings("BTC", "USD") + t.Parallel() + btcUSD, err := currency.NewPairFromStrings("BTC", "USD") if err != nil { t.Fatal(err) } - btceur, err := currency.NewPairFromStrings("BTC", "EUR") + btcEUR, err := currency.NewPairFromStrings("BTC", "EUR") if err != nil { t.Fatal(err) } - p := GetRelatableFiatCurrencies(btsusd) - if !p.Contains(btceur, true) { - t.Fatal("Unexpected result") + p := GetRelatableFiatCurrencies(btcUSD) + if !p.Contains(btcEUR, true) { + t.Error("Unexpected result") } - btczar, err := currency.NewPairFromStrings("BTC", "ZAR") - if err != nil { - t.Fatal(err) - } - - p = GetRelatableFiatCurrencies(btsusd) - if !p.Contains(btczar, true) { - t.Fatal("Unexpected result") + if p.Contains(currency.NewPair(currency.DOGE, currency.XRP), true) { + t.Error("Unexpected result") } } func TestMapCurrenciesByExchange(t *testing.T) { + t.Parallel() e := CreateTestBot(t) var pairs = []currency.Pair{ @@ -491,9 +543,7 @@ func TestMapCurrenciesByExchange(t *testing.T) { } func TestGetExchangeNamesByCurrency(t *testing.T) { - e := CreateTestBot(t) - assetType := asset.Spot - + t.Parallel() btsusd, err := currency.NewPairFromStrings("BTC", "USD") if err != nil { t.Fatal(err) @@ -509,6 +559,24 @@ func TestGetExchangeNamesByCurrency(t *testing.T) { t.Fatal(err) } + e := CreateTestBot(t) + bf := "Bitflyer" + e.Config.Exchanges = append(e.Config.Exchanges, config.ExchangeConfig{ + Enabled: true, + Name: bf, + CurrencyPairs: ¤cy.PairsManager{Pairs: map[asset.Item]*currency.PairStore{ + asset.Spot: { + AssetEnabled: convert.BoolPtr(true), + Enabled: currency.Pairs{btcjpy}, + Available: currency.Pairs{btcjpy}, + ConfigFormat: ¤cy.PairFormat{ + Uppercase: true, + }, + }, + }}, + }) + assetType := asset.Spot + result := e.GetExchangeNamesByCurrency(btsusd, true, assetType) @@ -519,7 +587,7 @@ func TestGetExchangeNamesByCurrency(t *testing.T) { result = e.GetExchangeNamesByCurrency(btcjpy, true, assetType) - if !common.StringDataCompare(result, "Bitflyer") { + if !common.StringDataCompare(result, bf) { t.Fatal("Unexpected result") } @@ -532,6 +600,7 @@ func TestGetExchangeNamesByCurrency(t *testing.T) { } func TestGetSpecificOrderbook(t *testing.T) { + t.Parallel() e := CreateTestBot(t) var bids []orderbook.Item @@ -580,6 +649,7 @@ func TestGetSpecificOrderbook(t *testing.T) { } func TestGetSpecificTicker(t *testing.T) { + t.Parallel() e := CreateTestBot(t) p, err := currency.NewPairFromStrings("BTC", "USD") if err != nil { @@ -621,6 +691,7 @@ func TestGetSpecificTicker(t *testing.T) { } func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) { + t.Parallel() CreateTestBot(t) var exchangeInfo []account.Holdings @@ -681,6 +752,7 @@ func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) { } func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) { + t.Parallel() CreateTestBot(t) p, err := currency.NewPairFromStrings("BTC", "USD") @@ -717,6 +789,7 @@ func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) { } func TestGetExchangeLowestPriceByCurrencyPair(t *testing.T) { + t.Parallel() CreateTestBot(t) p, err := currency.NewPairFromStrings("BTC", "USD") @@ -753,6 +826,7 @@ func TestGetExchangeLowestPriceByCurrencyPair(t *testing.T) { } func TestGetCryptocurrenciesByExchange(t *testing.T) { + t.Parallel() e := CreateTestBot(t) _, err := e.GetCryptocurrenciesByExchange("Bitfinex", false, false, asset.Spot) @@ -762,6 +836,7 @@ func TestGetCryptocurrenciesByExchange(t *testing.T) { } func TestGetExchangeNames(t *testing.T) { + t.Parallel() bot := CreateTestBot(t) if e := bot.GetExchangeNames(true); len(e) == 0 { t.Error("exchange names should be populated") @@ -779,7 +854,7 @@ func TestGetExchangeNames(t *testing.T) { for i := range bot.Config.Exchanges { exch, err := bot.ExchangeManager.NewExchangeByName(bot.Config.Exchanges[i].Name) if err != nil && !errors.Is(err, ErrExchangeAlreadyLoaded) { - t.Error(err) + t.Fatal(err) } if exch != nil { exch.SetDefaults() diff --git a/engine/order_manager_test.go b/engine/order_manager_test.go index 2eaf7145..7a6d227d 100644 --- a/engine/order_manager_test.go +++ b/engine/order_manager_test.go @@ -138,7 +138,7 @@ func OrdersSetup(t *testing.T) *OrderManager { em := SetupExchangeManager() exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Error(err) + t.Fatal(err) } exch.SetDefaults() diff --git a/engine/portfolio_manager_test.go b/engine/portfolio_manager_test.go index 40ff4776..05724eb8 100644 --- a/engine/portfolio_manager_test.go +++ b/engine/portfolio_manager_test.go @@ -104,7 +104,7 @@ func TestProcessPortfolio(t *testing.T) { em := SetupExchangeManager() exch, err := em.NewExchangeByName("Bitstamp") if !errors.Is(err, nil) { - t.Errorf("error '%v', expected '%v'", err, nil) + t.Fatalf("error '%v', expected '%v'", err, nil) } exch.SetDefaults() em.Add(exch) diff --git a/engine/rpcserver_test.go b/engine/rpcserver_test.go index d02e10a8..ff6b3aba 100644 --- a/engine/rpcserver_test.go +++ b/engine/rpcserver_test.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" + "io/ioutil" "log" "os" "path/filepath" "reflect" - "runtime" "strings" "sync" "testing" @@ -41,7 +41,6 @@ const ( unexpectedLackOfError = "unexpected lack of error" migrationsFolder = "migrations" databaseFolder = "database" - databaseName = "rpctestdb.db" ) // fExchange is a fake exchange with function overrides @@ -50,6 +49,44 @@ type fExchange struct { exchange.IBotExchange } +func (f fExchange) GetHistoricCandles(p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) { + return kline.Item{ + Exchange: "fake", + Pair: p, + Asset: a, + Interval: interval, + Candles: []kline.Candle{ + { + Time: timeStart, + Open: 1337, + High: 1337, + Low: 1337, + Close: 1337, + Volume: 1337, + }, + }, + }, nil +} + +func (f fExchange) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) { + return kline.Item{ + Exchange: "fake", + Pair: p, + Asset: a, + Interval: interval, + Candles: []kline.Candle{ + { + Time: timeStart, + Open: 1337, + High: 1337, + Low: 1337, + Close: 1337, + Volume: 1337, + }, + }, + }, nil +} + // FetchAccountInfo overrides testExchange's fetch account info function // to do the bare minimum required with no API calls or credentials required func (f fExchange) FetchAccountInfo(a asset.Item) (account.Holdings, error) { @@ -84,6 +121,7 @@ func (f fExchange) UpdateAccountInfo(a asset.Item) (account.Holdings, error) { } // Sets up everything required to run any function inside rpcserver +// Only use if you require a database, this makes tests slow func RPCTestSetup(t *testing.T) *Engine { t.Helper() var err error @@ -92,24 +130,60 @@ func RPCTestSetup(t *testing.T) *Engine { Driver: database.DBSQLite3, ConnectionDetails: drivers.ConnectionDetails{ Host: "localhost", - Database: databaseName, + Database: "test123.db", }, } engerino := new(Engine) + dbm, err := SetupDatabaseConnectionManager(&dbConf) + if err != nil { + t.Fatal(err) + } + tempDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + dbm.dbConn.DataPath = tempDir + engerino.DatabaseManager = dbm + var wg sync.WaitGroup + err = dbm.Start(&wg) + if err != nil { + t.Fatal(err) + } engerino.Config = &config.Config{} - err = engerino.Config.LoadConfig(config.TestFile, true) + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) if err != nil { - t.Fatalf("SetupTest: Failed to load config: %s", err) + t.Fatal(err) } - engerino.ExchangeManager = SetupExchangeManager() - err = engerino.LoadExchange(testExchange, false, nil) + exch.SetDefaults() + b := exch.GetBase() + cp := currency.NewPair(currency.BTC, currency.USD) + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + em.Add(exch) + + exch, err = em.NewExchangeByName("Binance") if err != nil { - log.Fatal(err) - } - err = engerino.LoadExchange("Binance", false, nil) - if err != nil { - log.Fatal(err) + t.Fatal(err) } + exch.SetDefaults() + b = exch.GetBase() + cp = currency.NewPair(currency.BTC, currency.USDT) + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + em.Add(exch) + engerino.ExchangeManager = em + engerino.Config.Database = dbConf engerino.DatabaseManager, err = SetupDatabaseConnectionManager(&engerino.Config.Database) if err != nil { @@ -147,7 +221,7 @@ func CleanRPCTest(t *testing.T, engerino *Engine) { t.Error(err) return } - err = os.Remove(filepath.Join(common.GetDefaultDataDir(runtime.GOOS), databaseFolder, databaseName)) + err = os.Remove(filepath.Join(engerino.DatabaseManager.dbConn.DataPath, engerino.DatabaseManager.cfg.Database)) if err != nil { t.Error(err) } @@ -243,7 +317,7 @@ func TestConvertTradesToCandles(t *testing.T) { }, AssetType: asset.Spot.String(), Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), }) if !errors.Is(err, errExchangeNotLoaded) { @@ -259,8 +333,8 @@ func TestConvertTradesToCandles(t *testing.T) { Quote: currency.USD.String(), }, AssetType: asset.Spot.String(), - Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), }) if !errors.Is(err, errNoTrades) { @@ -269,7 +343,7 @@ func TestConvertTradesToCandles(t *testing.T) { // add a trade err = sqltrade.Insert(sqltrade.Data{ - Timestamp: time.Date(2020, 1, 1, 1, 2, 2, 1, time.UTC), + Timestamp: time.Date(2020, 0, 0, 0, 30, 0, 0, time.UTC), Exchange: testExchange, Base: currency.BTC.String(), Quote: currency.USD.String(), @@ -292,8 +366,8 @@ func TestConvertTradesToCandles(t *testing.T) { Quote: currency.USD.String(), }, AssetType: asset.Spot.String(), - Start: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 3, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), }) if err != nil { @@ -312,8 +386,8 @@ func TestConvertTradesToCandles(t *testing.T) { Quote: currency.USD.String(), }, AssetType: asset.Spot.String(), - Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), Sync: true, }) @@ -330,8 +404,8 @@ func TestConvertTradesToCandles(t *testing.T) { Quote: currency.USD.String(), }, AssetType: asset.Spot.String(), - Start: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 2, 2, 2, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), Sync: true, Force: true, @@ -349,8 +423,8 @@ func TestConvertTradesToCandles(t *testing.T) { Quote: currency.USD.String(), }, AssetType: asset.Spot.String(), - Start: time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 2, 2, 2, 2, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), UseDb: true, }) @@ -368,8 +442,8 @@ func TestGetHistoricCandles(t *testing.T) { defer CleanRPCTest(t, engerino) s := RPCServer{Engine: engerino} // error checks - defaultStart := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC) - defaultEnd := time.Date(2020, 1, 2, 2, 2, 2, 2, time.UTC) + defaultStart := time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC) + defaultEnd := time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC) cp := currency.NewPair(currency.BTC, currency.USD) _, err := s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ Exchange: "", @@ -382,7 +456,7 @@ func TestGetHistoricCandles(t *testing.T) { AssetType: asset.Spot.String(), }) if !errors.Is(err, errExchangeNotLoaded) { - t.Errorf("expected %v, received %v", errExchangeNotLoaded, err) + t.Errorf("received '%v', expected '%v'", err, errExchangeNotLoaded) } _, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ @@ -393,7 +467,7 @@ func TestGetHistoricCandles(t *testing.T) { AssetType: asset.Spot.String(), }) if !errors.Is(err, errCurrencyPairUnset) { - t.Errorf("expected %v, received %v", errCurrencyPairUnset, err) + t.Errorf("received '%v', expected '%v'", err, errCurrencyPairUnset) } _, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{ Exchange: testExchange, @@ -475,7 +549,7 @@ func TestGetHistoricCandles(t *testing.T) { Price: 1337, Amount: 1337, Side: order.Buy, - Timestamp: time.Date(2020, 1, 2, 3, 1, 1, 7, time.UTC), + Timestamp: time.Date(2020, 0, 0, 2, 0, 0, 0, time.UTC), }) if err != nil { t.Error(err) @@ -490,7 +564,7 @@ func TestGetHistoricCandles(t *testing.T) { }, AssetType: asset.Spot.String(), Start: defaultStart.Format(common.SimpleTimeFormat), - End: time.Date(2020, 1, 2, 4, 2, 2, 2, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 3, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), TimeInterval: int64(kline.OneHour.Duration()), UseDb: true, FillMissingWithTrades: true, @@ -621,8 +695,8 @@ func TestFindMissingSavedCandleIntervals(t *testing.T) { } cp := currency.NewPair(currency.BTC, currency.USD) // no data found response - defaultStart := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC) - defaultEnd := time.Date(2020, 1, 2, 2, 2, 2, 2, time.UTC) + defaultStart := time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC) + defaultEnd := time.Date(2020, 0, 0, 4, 0, 0, 0, time.UTC) var resp *gctrpc.FindMissingIntervalsResponse _, err = s.FindMissingSavedCandleIntervals(context.Background(), &gctrpc.FindMissingCandlePeriodsRequest{ ExchangeName: testExchange, @@ -648,7 +722,7 @@ func TestFindMissingSavedCandleIntervals(t *testing.T) { Interval: kline.OneHour, Candles: []kline.Candle{ { - Time: time.Date(2020, 1, 1, 2, 1, 1, 1, time.UTC), + Time: time.Date(2020, 0, 0, 0, 30, 0, 0, time.UTC), Open: 1337, High: 1337, Low: 1337, @@ -685,7 +759,7 @@ func TestFindMissingSavedCandleIntervals(t *testing.T) { Interval: kline.OneHour, Candles: []kline.Candle{ { - Time: time.Date(2020, 1, 1, 3, 1, 1, 1, time.UTC), + Time: time.Date(2020, 0, 0, 2, 45, 0, 0, time.UTC), Open: 1337, High: 1337, Low: 1337, @@ -719,28 +793,33 @@ func TestFindMissingSavedCandleIntervals(t *testing.T) { } func TestSetExchangeTradeProcessing(t *testing.T) { - engerino := RPCTestSetup(t) - defer CleanRPCTest(t, engerino) - s := RPCServer{Engine: engerino} - _, err := s.SetExchangeTradeProcessing(context.Background(), &gctrpc.SetExchangeTradeProcessingRequest{Exchange: testExchange, Status: true}) + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + b.Config = &config.ExchangeConfig{ + Features: &config.FeaturesConfig{Enabled: config.FeaturesEnabledConfig{SaveTradeData: false}}, + } + em.Add(exch) + s := RPCServer{Engine: &Engine{ExchangeManager: em}} + _, err = s.SetExchangeTradeProcessing(context.Background(), &gctrpc.SetExchangeTradeProcessingRequest{Exchange: testExchange, Status: true}) if err != nil { t.Error(err) return } - exch := s.GetExchangeByName(testExchange) - base := exch.GetBase() - if !base.IsSaveTradeDataEnabled() { + if !b.IsSaveTradeDataEnabled() { t.Error("expected true") } - _, err = s.SetExchangeTradeProcessing(context.Background(), &gctrpc.SetExchangeTradeProcessingRequest{Exchange: testExchange, Status: false}) if err != nil { t.Error(err) return } - exch = s.GetExchangeByName(testExchange) - base = exch.GetBase() - if base.IsSaveTradeDataEnabled() { + if b.IsSaveTradeDataEnabled() { t.Error("expected false") } } @@ -762,7 +841,7 @@ func TestGetRecentTrades(t *testing.T) { }, AssetType: asset.Spot.String(), Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), }) if !errors.Is(err, errExchangeNotLoaded) { t.Error(err) @@ -798,7 +877,7 @@ func TestGetHistoricTrades(t *testing.T) { }, AssetType: asset.Spot.String(), Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), }, nil) if !errors.Is(err, errExchangeNotLoaded) { t.Error(err) @@ -812,7 +891,7 @@ func TestGetHistoricTrades(t *testing.T) { }, AssetType: asset.Spot.String(), Start: time.Date(2020, 0, 0, 0, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), - End: time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC).Format(common.SimpleTimeFormat), + End: time.Date(2020, 0, 0, 1, 0, 0, 0, time.UTC).Format(common.SimpleTimeFormat), }, nil) if err != common.ErrFunctionNotSupported { t.Error(err) @@ -820,41 +899,58 @@ func TestGetHistoricTrades(t *testing.T) { } func TestGetAccountInfo(t *testing.T) { - bot := CreateTestBot(t) - exch := bot.ExchangeManager.GetExchangeByName(testExchange) + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } b := exch.GetBase() b.Name = "fake" + b.Enabled = true + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + AssetEnabled: convert.BoolPtr(true), + } fakeExchange := fExchange{ IBotExchange: exch, } - bot.ExchangeManager.Add(fakeExchange) - s := RPCServer{Engine: bot} - - _, err := s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()}) + em.Add(fakeExchange) + s := RPCServer{Engine: &Engine{ExchangeManager: em}} + _, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()}) if !errors.Is(err, nil) { - t.Errorf("expected %v, received %v", errAssetTypeDisabled, nil) + t.Errorf("received '%v', expected '%v'", err, nil) } } func TestUpdateAccountInfo(t *testing.T) { - bot := CreateTestBot(t) - exch := bot.ExchangeManager.GetExchangeByName(testExchange) + t.Parallel() + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(testExchange) + if err != nil { + t.Fatal(err) + } b := exch.GetBase() b.Name = "fake" + b.Enabled = true + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + AssetEnabled: convert.BoolPtr(true), + } fakeExchange := fExchange{ IBotExchange: exch, } - bot.ExchangeManager.Add(fakeExchange) - s := RPCServer{Engine: bot} + em.Add(fakeExchange) + s := RPCServer{Engine: &Engine{ExchangeManager: em}} - _, err := s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()}) + _, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()}) if !errors.Is(err, nil) { - t.Errorf("expected %v, received %v", nil, err) + t.Errorf("received '%v', expected '%v'", err, nil) } _, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Futures.String()}) if !errors.Is(err, errAssetTypeDisabled) { - t.Errorf("expected %v, received %v", errAssetTypeDisabled, err) + t.Errorf("received '%v', expected '%v'", err, errAssetTypeDisabled) } _, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{ @@ -862,15 +958,40 @@ func TestUpdateAccountInfo(t *testing.T) { AssetType: asset.Spot.String(), }) if !errors.Is(err, nil) { - t.Errorf("expected %v, received %v", nil, err) + t.Errorf("received '%v', expected '%v'", err, nil) } } func TestGetOrders(t *testing.T) { - exchName := "binance" - engerino := RPCTestSetup(t) - defer CleanRPCTest(t, engerino) - s := RPCServer{Engine: engerino} + t.Parallel() + exchName := "Binance" + engerino := &Engine{} + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(exchName) + if err != nil { + t.Fatal(err) + } + exch.SetDefaults() + b := exch.GetBase() + cp := currency.NewPair(currency.BTC, currency.USDT) + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + em.Add(exch) + var wg sync.WaitGroup + om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false) + if !errors.Is(err, nil) { + t.Errorf("received '%v', expected '%v'", err, nil) + } + err = om.Start() + if !errors.Is(err, nil) { + t.Errorf("received '%v', expected '%v'", err, nil) + } + s := RPCServer{Engine: &Engine{ExchangeManager: em, OrderManager: om}} p := &gctrpc.CurrencyPair{ Delimiter: "-", @@ -878,9 +999,9 @@ func TestGetOrders(t *testing.T) { Quote: currency.USDT.String(), } - _, err := s.GetOrders(context.Background(), nil) + _, err = s.GetOrders(context.Background(), nil) if !errors.Is(err, errInvalidArguments) { - t.Errorf("expected %v, received %v", errInvalidArguments, err) + t.Errorf("received '%v', expected '%v'", err, errInvalidArguments) } _, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{ @@ -888,7 +1009,7 @@ func TestGetOrders(t *testing.T) { Pair: p, }) if !errors.Is(err, errExchangeNotLoaded) { - t.Errorf("expected %v, received %v", errExchangeNotLoaded, err) + t.Errorf("received '%v', expected '%v'", errExchangeNotLoaded, err) } _, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{ @@ -896,7 +1017,7 @@ func TestGetOrders(t *testing.T) { AssetType: asset.Spot.String(), }) if !errors.Is(err, errCurrencyPairUnset) { - t.Errorf("expected %v, received %v", errCurrencyPairUnset, err) + t.Errorf("received '%v', expected '%v'", err, errCurrencyPairUnset) } _, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{ @@ -904,7 +1025,7 @@ func TestGetOrders(t *testing.T) { Pair: p, }) if !errors.Is(err, asset.ErrNotSupported) { - t.Errorf("expected %v, received %v", asset.ErrNotSupported, err) + t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported) } _, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{ @@ -929,11 +1050,6 @@ func TestGetOrders(t *testing.T) { t.Errorf("received '%v', expected '%v'", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) } - exch := engerino.GetExchangeByName(exchName) - if exch == nil { - t.Fatal("expected an exchange") - } - b := exch.GetBase() b.API.Credentials.Key = "test" b.API.Credentials.Secret = "test" b.API.AuthenticatedSupport = true @@ -949,17 +1065,35 @@ func TestGetOrders(t *testing.T) { } func TestGetOrder(t *testing.T) { + t.Parallel() exchName := "Binance" - engerino := RPCTestSetup(t) - defer CleanRPCTest(t, engerino) - s := RPCServer{Engine: engerino} - var wg sync.WaitGroup - var err error - engerino.OrderManager, err = SetupOrderManager(engerino.ExchangeManager, engerino.CommunicationsManager, &wg, false) - if !errors.Is(err, nil) { - t.Errorf("expected %v, received %v", errInvalidArguments, nil) + engerino := &Engine{} + em := SetupExchangeManager() + exch, err := em.NewExchangeByName(exchName) + if err != nil { + t.Fatal(err) } - + exch.SetDefaults() + b := exch.GetBase() + cp := currency.NewPair(currency.BTC, currency.USDT) + b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore) + b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{ + Available: currency.Pairs{cp}, + Enabled: currency.Pairs{cp}, + AssetEnabled: convert.BoolPtr(true), + ConfigFormat: ¤cy.PairFormat{Uppercase: true}, + RequestFormat: ¤cy.PairFormat{Uppercase: true}} + em.Add(exch) + var wg sync.WaitGroup + om, err := SetupOrderManager(em, engerino.CommunicationsManager, &wg, false) + if !errors.Is(err, nil) { + t.Errorf("received '%v', expected '%v'", err, nil) + } + err = om.Start() + if !errors.Is(err, nil) { + t.Errorf("received '%v', expected '%v'", err, nil) + } + s := RPCServer{Engine: &Engine{ExchangeManager: em, OrderManager: om}} p := &gctrpc.CurrencyPair{ Delimiter: "-", Base: "BTC", @@ -968,7 +1102,7 @@ func TestGetOrder(t *testing.T) { _, err = s.GetOrder(context.Background(), nil) if !errors.Is(err, errInvalidArguments) { - t.Errorf("expected %v, received %v", errInvalidArguments, err) + t.Errorf("received '%v', expected '%v'", err, errInvalidArguments) } _, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{ @@ -978,7 +1112,7 @@ func TestGetOrder(t *testing.T) { Asset: "spot", }) if !errors.Is(err, errExchangeNotLoaded) { - t.Errorf("expected %v, received %v", errExchangeNotLoaded, err) + t.Errorf("received '%v', expected '%v'", err, errExchangeNotLoaded) } _, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{ @@ -988,7 +1122,7 @@ func TestGetOrder(t *testing.T) { Asset: "", }) if !errors.Is(err, errCurrencyPairUnset) { - t.Errorf("expected %v, received %v", errCurrencyPairUnset, err) + t.Errorf("received '%v', expected '%v'", err, errCurrencyPairUnset) } _, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{ @@ -998,17 +1132,7 @@ func TestGetOrder(t *testing.T) { Asset: "", }) if !errors.Is(err, asset.ErrNotSupported) { - t.Errorf("expected %v, received %v", asset.ErrNotSupported, err) - } - - s.OrderManager, err = SetupOrderManager(engerino.ExchangeManager, engerino.CommunicationsManager, &engerino.ServicesWG, engerino.Settings.Verbose) - if err != nil { - t.Fatal(err) - } - - err = s.OrderManager.Start() - if err != nil { - t.Fatal(err) + t.Errorf("received '%v', expected '%v'", err, asset.ErrNotSupported) } _, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{ @@ -1018,7 +1142,7 @@ func TestGetOrder(t *testing.T) { Asset: asset.Spot.String(), }) if !errors.Is(err, ErrOrderIDCannotBeEmpty) { - t.Errorf("expected %v, received %v", ErrOrderIDCannotBeEmpty, err) + t.Errorf("received '%v', expected '%v'", err, ErrOrderIDCannotBeEmpty) } _, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{ Exchange: exchName, @@ -1032,8 +1156,8 @@ func TestGetOrder(t *testing.T) { } func TestCheckVars(t *testing.T) { + t.Parallel() var e exchange.IBotExchange - err := checkParams("Binance", e, asset.Spot, currency.NewPair(currency.BTC, currency.USDT)) if !errors.Is(err, errExchangeNotLoaded) { t.Errorf("expected %v, got %v", errExchangeNotLoaded, err) @@ -1130,6 +1254,7 @@ func TestCheckVars(t *testing.T) { } func TestParseEvents(t *testing.T) { + t.Parallel() var exchangeName = "Binance" var testData []*withdraw.Response for x := 0; x < 5; x++ { @@ -1294,7 +1419,7 @@ func TestGetDataHistoryJobDetails(t *testing.T) { t.Fatal("expected job") } if !strings.EqualFold(resp.Nickname, "TestGetDataHistoryJobDetails") { - t.Errorf("received %v, expected %v", "TestGetDataHistoryJobDetails", resp.Nickname) + t.Errorf("received %v, expected %v", resp.Nickname, "TestGetDataHistoryJobDetails") } } diff --git a/engine/sync_manager_test.go b/engine/sync_manager_test.go index c23b98f5..4c546418 100644 --- a/engine/sync_manager_test.go +++ b/engine/sync_manager_test.go @@ -13,6 +13,7 @@ import ( ) func TestSetupSyncManager(t *testing.T) { + t.Parallel() _, err := setupSyncManager(&Config{}, nil, nil, nil) if !errors.Is(err, errNoSyncItemsEnabled) { t.Errorf("error '%v', expected '%v'", err, errNoSyncItemsEnabled) @@ -38,6 +39,7 @@ func TestSetupSyncManager(t *testing.T) { } func TestSyncManagerStart(t *testing.T) { + t.Parallel() m, err := setupSyncManager(&Config{SyncTrades: true}, &ExchangeManager{}, nil, &config.RemoteControlConfig{}) if !errors.Is(err, nil) { t.Errorf("error '%v', expected '%v'", err, nil) @@ -69,6 +71,7 @@ func TestSyncManagerStart(t *testing.T) { } func TestSyncManagerStop(t *testing.T) { + t.Parallel() var m *syncManager err := m.Stop() if !errors.Is(err, ErrNilSubsystem) { @@ -103,6 +106,7 @@ func TestSyncManagerStop(t *testing.T) { } func TestPrintCurrencyFormat(t *testing.T) { + t.Parallel() c := printCurrencyFormat(1337, currency.BTC) if c == "" { t.Error("expected formatted currency") @@ -110,6 +114,7 @@ func TestPrintCurrencyFormat(t *testing.T) { } func TestPrintConvertCurrencyFormat(t *testing.T) { + t.Parallel() c := printConvertCurrencyFormat(currency.BTC, 1337, currency.USD) if c == "" { t.Error("expected formatted currency") @@ -117,6 +122,7 @@ func TestPrintConvertCurrencyFormat(t *testing.T) { } func TestPrintTickerSummary(t *testing.T) { + t.Parallel() var m *syncManager m.PrintTickerSummary(&ticker.Price{}, "REST", nil) @@ -155,6 +161,7 @@ func TestPrintTickerSummary(t *testing.T) { } func TestPrintOrderbookSummary(t *testing.T) { + t.Parallel() var m *syncManager m.PrintOrderbookSummary(nil, "REST", nil) @@ -196,5 +203,7 @@ func TestPrintOrderbookSummary(t *testing.T) { } func TestRelayWebsocketEvent(t *testing.T) { + t.Parallel() + relayWebsocketEvent(nil, "", "", "") } diff --git a/engine/websocketroutine_manager_test.go b/engine/websocketroutine_manager_test.go index 1f2411cf..0ca86bbc 100644 --- a/engine/websocketroutine_manager_test.go +++ b/engine/websocketroutine_manager_test.go @@ -127,7 +127,7 @@ func TestWebsocketRoutineManagerHandleData(t *testing.T) { em := SetupExchangeManager() exch, err := em.NewExchangeByName(exchName) if !errors.Is(err, nil) { - t.Errorf("error '%v', expected '%v'", err, nil) + t.Fatalf("error '%v', expected '%v'", err, nil) } exch.SetDefaults() em.Add(exch) diff --git a/engine/withdraw_manager_test.go b/engine/withdraw_manager_test.go index f057077e..440c1551 100644 --- a/engine/withdraw_manager_test.go +++ b/engine/withdraw_manager_test.go @@ -40,29 +40,25 @@ func TestSubmitWithdrawal(t *testing.T) { if err != nil { t.Fatal(err) } - - banking.Accounts = append(banking.Accounts, - banking.Account{ - Enabled: true, - ID: "test-bank-01", - BankName: "Test Bank", - BankAddress: "42 Bank Street", - BankPostalCode: "13337", - BankPostalCity: "Satoshiville", - BankCountry: "Japan", - AccountName: "Satoshi Nakamoto", - AccountNumber: "0234", - BSBNumber: "123456", - SWIFTCode: "91272837", - IBAN: "98218738671897", - SupportedCurrencies: "AUD,USD", - SupportedExchanges: "Binance", - }, - ) - bank, err := banking.GetBankAccountByID("test-bank-01") - if err != nil { - t.Error(err) + bank := banking.Account{ + Enabled: true, + ID: "test-bank-01", + BankName: "Test Bank", + BankAddress: "42 Bank Street", + BankPostalCode: "13337", + BankPostalCity: "Satoshiville", + BankCountry: "Japan", + AccountName: "Satoshi Nakamoto", + AccountNumber: "0234", + BSBNumber: "123456", + SWIFTCode: "91272837", + IBAN: "98218738671897", + SupportedCurrencies: "AUD,USD", + SupportedExchanges: "Binance", } + + banking.AppendAccounts(bank) + req := &withdraw.Request{ Exchange: exchangeName, Currency: currency.AUD, @@ -70,7 +66,7 @@ func TestSubmitWithdrawal(t *testing.T) { Amount: 1.0, Type: withdraw.Fiat, Fiat: withdraw.FiatRequest{ - Bank: *bank, + Bank: bank, }, } _, err = m.SubmitWithdrawal(req) diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 7dab4241..3957883f 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -1167,7 +1167,6 @@ func TestWsNewOffer(t *testing.T) { if err != nil { t.Error(err) } - time.Sleep(time.Second) } // TestWsCancelOffer dials websocket, sends cancel offer request. @@ -1182,7 +1181,6 @@ func TestWsCancelOffer(t *testing.T) { if err != nil { t.Error(err) } - time.Sleep(time.Second) } func TestConvertSymbolToDepositMethod(t *testing.T) { @@ -1313,7 +1311,8 @@ func TestGetHistoricCandles(t *testing.T) { t.Fatal(err) } startTime := time.Now().Add(-time.Hour * 24) - _, err = b.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin) + endTime := time.Now().Add(-time.Hour * 20) + _, err = b.GetHistoricCandles(currencyPair, asset.Spot, startTime, endTime, kline.OneHour) if err != nil { t.Fatal(err) } @@ -1330,12 +1329,13 @@ func TestGetHistoricCandlesExtended(t *testing.T) { t.Fatal(err) } startTime := time.Now().Add(-time.Hour * 24) - _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour) + endTime := time.Now().Add(-time.Hour * 20) + _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, endTime, kline.OneHour) if err != nil { t.Fatal(err) } - _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin*1337) + _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, endTime, kline.OneMin*1337) if err == nil { t.Fatal(err) } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index ca661d94..8dbf9ab0 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -524,7 +524,7 @@ func (b *Bitfinex) GetWithdrawalsHistory(c currency.Code) (resp []exchange.Withd // GetRecentTrades returns the most recent trades for a currency and asset func (b *Bitfinex) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) + return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Minute*15), time.Now()) } // GetHistoricTrades returns historic trade data within the timeframe provided diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go index d8282345..9aedb6db 100644 --- a/exchanges/bitmex/bitmex_test.go +++ b/exchanges/bitmex/bitmex_test.go @@ -51,7 +51,6 @@ func TestMain(m *testing.M) { if err != nil { log.Fatal("Bitmex setup error", err) } - b.UpdateTradablePairs(true) os.Exit(m.Run()) } @@ -64,17 +63,12 @@ func TestStart(t *testing.T) { func TestGetFullFundingHistory(t *testing.T) { t.Parallel() - _, err := b.GetFullFundingHistory("", "", "", "", "", true, time.Time{}, time.Time{}) + _, err := b.GetFullFundingHistory("", "", "", "", "", true, time.Now().Add(-time.Minute), time.Now()) if err != nil { t.Error(err) } - _, err = b.GetFullFundingHistory("", "", "", "", "", true, time.Now().Add(-time.Hour*8), time.Now()) - if err != nil { - t.Error(err) - } - - _, err = b.GetFullFundingHistory("LTCUSD", "1", "", "", "", true, time.Now().Add(time.Hour*-24), time.Now()) + _, err = b.GetFullFundingHistory("LTCUSD", "1", "", "", "", true, time.Now().Add(-time.Minute), time.Now()) if err != nil { t.Error(err) } @@ -82,6 +76,9 @@ func TestGetFullFundingHistory(t *testing.T) { func TestGetUrgentAnnouncement(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.GetUrgentAnnouncement() if err == nil { t.Error("GetUrgentAnnouncement() Expected error") @@ -90,6 +87,9 @@ func TestGetUrgentAnnouncement(t *testing.T) { func TestGetAPIKeys(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.GetAPIKeys() if err == nil { t.Error("GetAPIKeys() Expected error") @@ -98,6 +98,7 @@ func TestGetAPIKeys(t *testing.T) { func TestRemoveAPIKey(t *testing.T) { t.Parallel() + _, err := b.RemoveAPIKey(APIKeyParams{APIKeyID: "1337"}) if err == nil { t.Error("RemoveAPIKey() Expected error") @@ -106,6 +107,9 @@ func TestRemoveAPIKey(t *testing.T) { func TestDisableAPIKey(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.DisableAPIKey(APIKeyParams{APIKeyID: "1337"}) if err == nil { t.Error("DisableAPIKey() Expected error") @@ -114,6 +118,9 @@ func TestDisableAPIKey(t *testing.T) { func TestEnableAPIKey(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.EnableAPIKey(APIKeyParams{APIKeyID: "1337"}) if err == nil { t.Error("EnableAPIKey() Expected error") @@ -122,7 +129,7 @@ func TestEnableAPIKey(t *testing.T) { func TestGetTrollboxMessages(t *testing.T) { t.Parallel() - _, err := b.GetTrollboxMessages(ChatGetParams{Count: 5}) + _, err := b.GetTrollboxMessages(ChatGetParams{Count: 1}) if err != nil { t.Error("GetTrollboxMessages() error", err) } @@ -130,6 +137,9 @@ func TestGetTrollboxMessages(t *testing.T) { func TestSendTrollboxMessage(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.SendTrollboxMessage(ChatSendParams{ ChannelID: 1337, Message: "Hello,World!"}) @@ -156,6 +166,9 @@ func TestGetTrollboxConnectedUsers(t *testing.T) { func TestGetAccountExecutions(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.GetAccountExecutions(&GenericRequestParams{}) if err == nil { t.Error("GetAccountExecutions() Expected error") @@ -164,6 +177,9 @@ func TestGetAccountExecutions(t *testing.T) { func TestGetAccountExecutionTradeHistory(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.GetAccountExecutionTradeHistory(&GenericRequestParams{}) if err == nil { t.Error("GetAccountExecutionTradeHistory() Expected error") @@ -180,7 +196,9 @@ func TestGetFundingHistory(t *testing.T) { func TestGetInstruments(t *testing.T) { t.Parallel() - _, err := b.GetInstruments(&GenericRequestParams{}) + _, err := b.GetInstruments(&GenericRequestParams{ + Symbol: "XRPUSD", + }) if err != nil { t.Error("GetInstruments() error", err) } @@ -260,6 +278,9 @@ func TestGetLiquidationOrders(t *testing.T) { func TestGetCurrentNotifications(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.GetCurrentNotifications() if err == nil { t.Error("GetCurrentNotifications() Expected error") @@ -268,6 +289,9 @@ func TestGetCurrentNotifications(t *testing.T) { func TestAmendOrder(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.AmendOrder(&OrderAmendParams{}) if err == nil { t.Error("AmendOrder() Expected error") @@ -276,6 +300,9 @@ func TestAmendOrder(t *testing.T) { func TestCreateOrder(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.CreateOrder(&OrderNewParams{Symbol: "XBTM15", Price: 219.0, ClientOrderID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA", @@ -287,6 +314,9 @@ func TestCreateOrder(t *testing.T) { func TestCancelOrders(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.CancelOrders(&OrderCancelParams{}) if err == nil { t.Error("CancelOrders() Expected error") @@ -295,6 +325,9 @@ func TestCancelOrders(t *testing.T) { func TestCancelAllOrders(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.CancelAllExistingOrders(OrderCancelAllParams{}) if err == nil { t.Error("CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error)", err) @@ -303,6 +336,9 @@ func TestCancelAllOrders(t *testing.T) { func TestAmendBulkOrders(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.AmendBulkOrders(OrderAmendBulkParams{}) if err == nil { t.Error("AmendBulkOrders() Expected error") @@ -311,6 +347,9 @@ func TestAmendBulkOrders(t *testing.T) { func TestCreateBulkOrders(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.CreateBulkOrders(OrderNewBulkParams{}) if err == nil { t.Error("CreateBulkOrders() Expected error") @@ -319,6 +358,9 @@ func TestCreateBulkOrders(t *testing.T) { func TestCancelAllOrdersAfterTime(t *testing.T) { t.Parallel() + if areTestAPIKeysSet() && !canManipulateRealOrders { + t.Skip("API keys set, canManipulateRealOrders false, skipping test") + } _, err := b.CancelAllOrdersAfterTime(OrderCancelAllAfterParams{}) if err == nil { t.Error("CancelAllOrdersAfterTime() Expected error") @@ -426,7 +468,7 @@ func TestGetTrade(t *testing.T) { _, err := b.GetTrade(&GenericRequestParams{ Symbol: "XBT", Reverse: false, - StartTime: time.Now().Add(-time.Hour).Format(time.RFC3339), + StartTime: time.Now().Add(-time.Minute).Format(time.RFC3339), }) if err != nil { t.Error("GetTrade() error", err) @@ -437,7 +479,7 @@ func TestGetPreviousTrades(t *testing.T) { t.Parallel() _, err := b.GetPreviousTrades(&TradeGetBucketedParams{ Symbol: "XBTBTC", - Start: int32(time.Now().Add(-time.Hour * 24).Unix()), + Start: int32(time.Now().Add(-time.Hour).Unix()), Columns: "open,high,low,close,volume", }) if err == nil { @@ -1043,7 +1085,7 @@ func TestGetHistoricTrades(t *testing.T) { t.Fatal(err) } currencyPair := b.CurrencyPairs.Pairs[asset.Futures].Available[0] - _, err = b.GetHistoricTrades(currencyPair, asset.Futures, time.Now().Add(-time.Minute*15), time.Now()) + _, err = b.GetHistoricTrades(currencyPair, asset.Futures, time.Now().Add(-time.Minute), time.Now()) if err != nil { t.Error(err) } diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index be970486..91faf2f7 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -453,7 +453,7 @@ func (b *Bitmex) GetWithdrawalsHistory(c currency.Code) (resp []exchange.Withdra // GetRecentTrades returns the most recent trades for a currency and asset func (b *Bitmex) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) + return b.GetHistoricTrades(p, assetType, time.Now().Add(-time.Minute*15), time.Now()) } // GetHistoricTrades returns historic trade data within the timeframe provided diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index 5e35844b..f5cddaff 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -737,7 +737,7 @@ func TestBTCMarkets_GetHistoricCandles(t *testing.T) { } func TestBTCMarkets_GetHistoricCandlesExtended(t *testing.T) { - start := time.Now().AddDate(0, 0, -1001) + start := time.Now().AddDate(0, 0, -2) end := time.Now() p, err := currency.NewPairFromString(BTCAUD) if err != nil { diff --git a/exchanges/coinbene/coinbene_test.go b/exchanges/coinbene/coinbene_test.go index 12004027..97892406 100644 --- a/exchanges/coinbene/coinbene_test.go +++ b/exchanges/coinbene/coinbene_test.go @@ -653,7 +653,7 @@ func TestGetHistoricCandlesExtended(t *testing.T) { if err != nil { t.Fatal(err) } - startTime := time.Now().Add(-time.Hour * 24) + startTime := time.Now().Add(-time.Hour * 2) _, err = c.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour) if err != nil { t.Fatal(err) diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 6b03e203..b0ac321c 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -348,13 +348,23 @@ func TestSetAPICredentialDefaults(t *testing.T) { } func TestSetAutoPairDefaults(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig(config.TestFile, true) - if err != nil { - t.Fatalf("TestSetAutoPairDefaults failed to load config file. Error: %s", err) - } + t.Parallel() + bs := "Bitstamp" + cfg := &config.Config{Exchanges: []config.ExchangeConfig{ + { + Name: bs, + CurrencyPairs: ¤cy.PairsManager{}, + Features: &config.FeaturesConfig{ + Supports: config.FeaturesSupportedConfig{ + RESTCapabilities: protocol.Features{ + AutoPairUpdates: true, + }, + }, + }, + }, + }} - exch, err := cfg.GetExchangeConfig("Bitstamp") + exch, err := cfg.GetExchangeConfig(bs) if err != nil { t.Fatalf("TestSetAutoPairDefaults load config failed. Error %s", err) } @@ -369,7 +379,7 @@ func TestSetAutoPairDefaults(t *testing.T) { exch.Features.Supports.RESTCapabilities.AutoPairUpdates = false - exch, err = cfg.GetExchangeConfig("Bitstamp") + exch, err = cfg.GetExchangeConfig(bs) if err != nil { t.Fatalf("TestSetAutoPairDefaults load config failed. Error %s", err) } @@ -1467,10 +1477,14 @@ func TestSetPairs(t *testing.T) { } func TestUpdatePairs(t *testing.T) { - cfg := config.GetConfig() - err := cfg.LoadConfig(config.TestFile, true) - if err != nil { - t.Fatal("TestUpdatePairs failed to load config") + t.Parallel() + cfg := &config.Config{ + Exchanges: []config.ExchangeConfig{ + { + Name: defaultTestExchange, + CurrencyPairs: ¤cy.PairsManager{}, + }, + }, } exchCfg, err := cfg.GetExchangeConfig(defaultTestExchange) diff --git a/exchanges/ftx/ftx_test.go b/exchanges/ftx/ftx_test.go index 18697940..948172c2 100644 --- a/exchanges/ftx/ftx_test.go +++ b/exchanges/ftx/ftx_test.go @@ -1119,7 +1119,7 @@ func TestGetHistoricCandles(t *testing.T) { t.Fatal(err) } start := time.Date(2019, 11, 12, 0, 0, 0, 0, time.UTC) - end := start.AddDate(0, 0, 5) + end := start.AddDate(0, 0, 2) _, err = f.GetHistoricCandles(currencyPair, asset.Spot, start, end, kline.OneDay) if err != nil { t.Fatal(err) @@ -1133,8 +1133,8 @@ func TestGetHistoricCandlesExtended(t *testing.T) { t.Fatal(err) } start := time.Date(2019, 11, 12, 0, 0, 0, 0, time.UTC) - end := start.AddDate(0, 0, 5) - _, err = f.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneMin) + end := start.AddDate(0, 0, 2) + _, err = f.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneDay) if err != nil { t.Fatal(err) } diff --git a/exchanges/ftx/ftx_wrapper.go b/exchanges/ftx/ftx_wrapper.go index d51052cb..1addac7e 100644 --- a/exchanges/ftx/ftx_wrapper.go +++ b/exchanges/ftx/ftx_wrapper.go @@ -471,7 +471,7 @@ func (f *FTX) GetWithdrawalsHistory(c currency.Code) (resp []exchange.Withdrawal // GetRecentTrades returns the most recent trades for a currency and asset func (f *FTX) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return f.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) + return f.GetHistoricTrades(p, assetType, time.Now().Add(-time.Minute*15), time.Now()) } // GetHistoricTrades returns historic trade data within the timeframe provided diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index ab7e38a8..2d9216e4 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -750,7 +750,7 @@ func TestGetHistoricCandlesExtended(t *testing.T) { if err != nil { t.Fatal(err) } - startTime := time.Now().Add(-time.Hour * 6) + startTime := time.Now().Add(-time.Minute * 2) _, err = g.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin) if err != nil { t.Fatal(err) diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go index 4b16a858..50705c29 100644 --- a/exchanges/gemini/gemini_test.go +++ b/exchanges/gemini/gemini_test.go @@ -1190,7 +1190,7 @@ func TestGetHistoricTrades(t *testing.T) { tEnd := time.Date(2020, 6, 7, 0, 0, 0, 0, time.UTC) if !mockTests { tStart = time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 0, 0, 0, time.UTC) - tEnd = time.Date(time.Now().Year(), time.Now().Month(), 1, 1, 0, 0, 0, time.UTC) + tEnd = time.Date(time.Now().Year(), time.Now().Month(), 1, 0, 15, 0, 0, time.UTC) } _, err = g.GetHistoricTrades(currencyPair, asset.Spot, tStart, tEnd) if err != nil { diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 9cdccf78..4e3fa335 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -465,7 +465,7 @@ func (h *HitBTC) GetWithdrawalsHistory(c currency.Code) (resp []exchange.Withdra // GetRecentTrades returns the most recent trades for a currency and asset func (h *HitBTC) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return h.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) + return h.GetHistoricTrades(p, assetType, time.Now().Add(-time.Minute*15), time.Now()) } // GetHistoricTrades returns historic trade data within the timeframe provided diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index 13fa286d..f69fa962 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -135,7 +135,7 @@ func TestFGetKlineData(t *testing.T) { if err != nil { t.Error(err) } - _, err = h.FGetKlineData(cp, "5min", 5, time.Time{}, time.Time{}) + _, err = h.FGetKlineData(cp, "5min", 5, time.Now().Add(-time.Minute*5), time.Now()) if err != nil { t.Error(err) } @@ -654,7 +654,8 @@ func TestFetchTradablePairs(t *testing.T) { } } -func TestUpdateTicker(t *testing.T) { +func TestUpdateTickerSpot(t *testing.T) { + t.Parallel() sp, err := currency.NewPairFromString("BTC_USDT") if err != nil { t.Error(err) @@ -663,6 +664,10 @@ func TestUpdateTicker(t *testing.T) { if err != nil { t.Error(err) } +} + +func TestUpdateTickerCMF(t *testing.T) { + t.Parallel() cp1, err := currency.NewPairFromString("BTC-USD") if err != nil { t.Error(err) @@ -671,6 +676,10 @@ func TestUpdateTicker(t *testing.T) { if err != nil { t.Error(err) } +} + +func TestUpdateTickerFutures(t *testing.T) { + t.Parallel() tradablePairs, err := h.FetchTradablePairs(asset.Futures) if err != nil { t.Error(err) @@ -688,7 +697,7 @@ func TestUpdateTicker(t *testing.T) { } } -func TestUpdateOrderbook(t *testing.T) { +func TestUpdateOrderbookSpot(t *testing.T) { t.Parallel() sp, err := currency.NewPairFromString("BTC_USDT") if err != nil { @@ -698,7 +707,11 @@ func TestUpdateOrderbook(t *testing.T) { if err != nil { t.Error(err) } - cp1, err := currency.NewPairFromString("BTC_USD") +} + +func TestUpdateOrderbookCMF(t *testing.T) { + t.Parallel() + cp1, err := currency.NewPairFromString("BTC-USD") if err != nil { t.Error(err) } @@ -706,6 +719,10 @@ func TestUpdateOrderbook(t *testing.T) { if err != nil { t.Error(err) } +} + +func TestUpdateOrderbookFuture(t *testing.T) { + t.Parallel() tradablePairs, err := h.FetchTradablePairs(asset.Futures) if err != nil { t.Error(err) @@ -1550,7 +1567,7 @@ func TestGetHistoricCandlesExtended(t *testing.T) { if err != nil { t.Fatal(err) } - startTime := time.Now().Add(-time.Hour * 1) + startTime := time.Now().Add(-time.Minute * 2) _, err = h.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin) if err != nil { t.Fatal(err) diff --git a/exchanges/kline/kline_test.go b/exchanges/kline/kline_test.go index 75d6f3f8..dfb5cc7e 100644 --- a/exchanges/kline/kline_test.go +++ b/exchanges/kline/kline_test.go @@ -32,6 +32,7 @@ var ( ) func TestValidateData(t *testing.T) { + t.Parallel() err := validateData(nil) if err == nil { t.Error("error cannot be nil") @@ -90,6 +91,7 @@ func TestValidateData(t *testing.T) { } func TestCreateKline(t *testing.T) { + t.Parallel() c, err := CreateKline(nil, OneMin, currency.NewPair(currency.BTC, currency.USD), @@ -135,24 +137,28 @@ func TestCreateKline(t *testing.T) { } func TestKlineWord(t *testing.T) { + t.Parallel() if OneDay.Word() != "oneday" { t.Fatalf("unexpected result: %v", OneDay.Word()) } } func TestKlineDuration(t *testing.T) { + t.Parallel() if OneDay.Duration() != time.Hour*24 { t.Fatalf("unexpected result: %v", OneDay.Duration()) } } func TestKlineShort(t *testing.T) { + t.Parallel() if OneDay.Short() != "24h" { t.Fatalf("unexpected result: %v", OneDay.Short()) } } func TestDurationToWord(t *testing.T) { + t.Parallel() testCases := []struct { name string interval Interval @@ -254,6 +260,7 @@ func TestDurationToWord(t *testing.T) { } func TestKlineErrors(t *testing.T) { + t.Parallel() v := ErrorKline{ Interval: OneYear, Pair: currency.NewPair(currency.BTC, currency.AUD), @@ -278,6 +285,7 @@ func TestKlineErrors(t *testing.T) { } func TestTotalCandlesPerInterval(t *testing.T) { + t.Parallel() start := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) end := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) @@ -399,7 +407,8 @@ func TestTotalCandlesPerInterval(t *testing.T) { } func TestCalculateCandleDateRanges(t *testing.T) { - pt := time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC) + t.Parallel() + pt := time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) ft := time.Date(2222, 1, 1, 0, 0, 0, 0, time.UTC) et := time.Date(2020, 1, 1, 1, 0, 0, 0, time.UTC) nt := time.Time{} @@ -424,31 +433,31 @@ func TestCalculateCandleDateRanges(t *testing.T) { t.Errorf("received %v expected %v", err, common.ErrStartEqualsEnd) } - v, err := CalculateCandleDateRanges(pt, et, OneMin, 300) + v, err := CalculateCandleDateRanges(pt, et, OneWeek, 300) if err != nil { t.Error(err) } - if v.Ranges[0].Start.Ticks != time.Unix(915148800, 0).Unix() { - t.Errorf("expected %v received %v", 915148800, v.Ranges[0].Start.Ticks) + if !v.Ranges[0].Start.Time.Equal(time.Unix(1546214400, 0)) { + t.Errorf("expected %v received %v", 1546214400, v.Ranges[0].Start.Ticks) } - v, err = CalculateCandleDateRanges(pt, et, OneDay, 100) + v, err = CalculateCandleDateRanges(pt, et, OneWeek, 100) if err != nil { t.Error(err) } - if len(v.Ranges) != 77 { - t.Fatalf("expected %v received %v", 77, len(v.Ranges)) + if len(v.Ranges) != 1 { + t.Fatalf("expected %v received %v", 1, len(v.Ranges)) } - if len(v.Ranges[0].Intervals) != 100 { - t.Errorf("expected %v received %v", 100, len(v.Ranges[0].Intervals)) + if len(v.Ranges[0].Intervals) != 52 { + t.Errorf("expected %v received %v", 52, len(v.Ranges[0].Intervals)) } - v, err = CalculateCandleDateRanges(et, ft, OneDay, 5) + v, err = CalculateCandleDateRanges(et, ft, OneWeek, 5) if err != nil { t.Error(err) } - if len(v.Ranges) != 14756 { - t.Errorf("expected %v received %v", 14756, len(v.Ranges)) + if len(v.Ranges) != 2108 { + t.Errorf("expected %v received %v", 2108, len(v.Ranges)) } if len(v.Ranges[0].Intervals) != 5 { t.Errorf("expected %v received %v", 5, len(v.Ranges[0].Intervals)) @@ -458,12 +467,13 @@ func TestCalculateCandleDateRanges(t *testing.T) { } lenRanges := len(v.Ranges) - 1 lenIntervals := len(v.Ranges[lenRanges].Intervals) - 1 - if !v.Ranges[lenRanges].Intervals[lenIntervals].End.Equal(ft.Round(OneDay.Duration())) { + if !v.Ranges[lenRanges].Intervals[lenIntervals].End.Equal(ft.Round(OneWeek.Duration())) { t.Errorf("expected %v received %v", ft.Round(OneDay.Duration()), v.Ranges[lenRanges].Intervals[lenIntervals].End) } } func TestItem_SortCandlesByTimestamp(t *testing.T) { + t.Parallel() var tempKline = Item{ Exchange: "testExchange", Pair: currency.NewPair(currency.BTC, currency.USDT), @@ -742,6 +752,7 @@ func TestLoadCSV(t *testing.T) { } func TestVerifyResultsHaveData(t *testing.T) { + t.Parallel() tt2 := time.Now().Round(OneDay.Duration()) tt1 := time.Now().Add(-time.Hour * 24).Round(OneDay.Duration()) dateRanges, err := CalculateCandleDateRanges(tt1, tt2, OneDay, 0) @@ -770,6 +781,7 @@ func TestVerifyResultsHaveData(t *testing.T) { } func TestDataSummary(t *testing.T) { + t.Parallel() tt1 := time.Now().Add(-time.Hour * 24).Round(OneDay.Duration()) tt2 := time.Now().Round(OneDay.Duration()) tt3 := time.Now().Add(time.Hour * 24).Round(OneDay.Duration()) @@ -797,6 +809,7 @@ func TestDataSummary(t *testing.T) { } func TestHasDataAtDate(t *testing.T) { + t.Parallel() tt2 := time.Now().Round(OneDay.Duration()) tt1 := time.Now().Add(-time.Hour * 24 * 30).Round(OneDay.Duration()) dateRanges, err := CalculateCandleDateRanges(tt1, tt2, OneDay, 0) @@ -826,6 +839,7 @@ func TestHasDataAtDate(t *testing.T) { } func TestIntervalsPerYear(t *testing.T) { + t.Parallel() i := OneYear if i.IntervalsPerYear() != 1.0 { t.Error("expected 1") diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index b4cd09f5..4f078693 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -128,10 +128,10 @@ func TestUpdateAccountInfo(t *testing.T) { } func TestWrapperGetOrderInfo(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.GetOrderInfo("123", currency.Pair{}, asset.Futures) if err != nil { t.Error(err) @@ -139,10 +139,10 @@ func TestWrapperGetOrderInfo(t *testing.T) { } func TestFuturesBatchOrder(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() var data []PlaceBatchOrderData var tempData PlaceBatchOrderData tempData.PlaceOrderType = "cancel" @@ -156,10 +156,10 @@ func TestFuturesBatchOrder(t *testing.T) { } func TestFuturesEditOrder(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() _, err := k.FuturesEditOrder("test123", "", 5.2, 1, 0) if err != nil { t.Error(err) @@ -167,10 +167,10 @@ func TestFuturesEditOrder(t *testing.T) { } func TestFuturesSendOrder(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() cp, err := currency.NewPairFromString("PI_XBTUSD") if err != nil { t.Error(err) @@ -182,10 +182,10 @@ func TestFuturesSendOrder(t *testing.T) { } func TestFuturesCancelOrder(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() _, err := k.FuturesCancelOrder("test123", "") if err != nil { t.Error(err) @@ -193,10 +193,10 @@ func TestFuturesCancelOrder(t *testing.T) { } func TestFuturesGetFills(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesGetFills(time.Now().Add(-time.Hour * 24)) if err != nil { t.Error(err) @@ -204,10 +204,10 @@ func TestFuturesGetFills(t *testing.T) { } func TestFuturesTransfer(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesTransfer("cash", "futures", "btc", 2) if err != nil { t.Error(err) @@ -215,10 +215,10 @@ func TestFuturesTransfer(t *testing.T) { } func TestFuturesGetOpenPositions(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesGetOpenPositions() if err != nil { t.Error(err) @@ -226,10 +226,10 @@ func TestFuturesGetOpenPositions(t *testing.T) { } func TestFuturesNotifications(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesNotifications() if err != nil { t.Error(err) @@ -237,10 +237,10 @@ func TestFuturesNotifications(t *testing.T) { } func TestFuturesCancelAllOrders(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() cp, err := currency.NewPairFromString("PI_XBTUSD") if err != nil { t.Error(err) @@ -252,10 +252,10 @@ func TestFuturesCancelAllOrders(t *testing.T) { } func TestGetFuturesAccountData(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.GetFuturesAccountData() if err != nil { t.Error(err) @@ -263,10 +263,10 @@ func TestGetFuturesAccountData(t *testing.T) { } func TestFuturesCancelAllOrdersAfter(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() _, err := k.FuturesCancelAllOrdersAfter(50) if err != nil { t.Error(err) @@ -274,10 +274,10 @@ func TestFuturesCancelAllOrdersAfter(t *testing.T) { } func TestFuturesOpenOrders(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesOpenOrders() if err != nil { t.Error(err) @@ -285,10 +285,10 @@ func TestFuturesOpenOrders(t *testing.T) { } func TestFuturesRecentOrders(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() cp, err := currency.NewPairFromString("PI_XBTUSD") if err != nil { t.Error(err) @@ -300,10 +300,10 @@ func TestFuturesRecentOrders(t *testing.T) { } func TestFuturesWithdrawToSpotWallet(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test: api keys not set or canManipulateRealOrders") } - t.Parallel() _, err := k.FuturesWithdrawToSpotWallet("xbt", 5) if err != nil { t.Error(err) @@ -311,10 +311,10 @@ func TestFuturesWithdrawToSpotWallet(t *testing.T) { } func TestFuturesGetTransfers(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("skipping test: api keys not set") } - t.Parallel() _, err := k.FuturesGetTransfers(time.Now().Add(-time.Hour * 24)) if err != nil { t.Error(err) @@ -508,14 +508,6 @@ func TestGetTrades(t *testing.T) { if err != nil { t.Error("GetTrades() error", err) } - cp2, err := currency.NewPairFromString("MADEUP") - if err != nil { - t.Error(err) - } - _, err = k.GetTrades(cp2) - if err == nil { - t.Error("expected error") - } } // TestGetSpread API endpoint test @@ -680,6 +672,7 @@ func setFeeBuilder() *exchange.FeeBuilder { // TestGetFeeByTypeOfflineTradeFee logic test func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { + t.Parallel() var feeBuilder = setFeeBuilder() k.GetFeeByType(feeBuilder) if !areTestAPIKeysSet() { @@ -694,6 +687,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { } func TestGetFee(t *testing.T) { + t.Parallel() var feeBuilder = setFeeBuilder() if areTestAPIKeysSet() { @@ -766,6 +760,7 @@ func TestGetFee(t *testing.T) { // TestFormatWithdrawPermissions logic test func TestFormatWithdrawPermissions(t *testing.T) { + t.Parallel() expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawCryptoWith2FAText + " & " + exchange.AutoWithdrawFiatWithSetupText + " & " + exchange.WithdrawFiatWith2FAText withdrawPermissions := k.FormatWithdrawPermissions() if withdrawPermissions != expectedResult { @@ -797,6 +792,7 @@ func TestGetActiveOrders(t *testing.T) { // TestGetOrderHistory wrapper test func TestGetOrderHistory(t *testing.T) { + t.Parallel() var getOrdersRequest = order.GetOrdersRequest{ Type: order.AnyType, AssetType: asset.Spot, @@ -812,6 +808,7 @@ func TestGetOrderHistory(t *testing.T) { // TestGetOrderHistory wrapper test func TestGetOrderInfo(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -837,6 +834,7 @@ func areTestAPIKeysSet() bool { // TestSubmitOrder wrapper test func TestSubmitOrder(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -863,6 +861,7 @@ func TestSubmitOrder(t *testing.T) { // TestCancelExchangeOrder wrapper test func TestCancelExchangeOrder(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -883,6 +882,7 @@ func TestCancelExchangeOrder(t *testing.T) { // TestCancelExchangeOrder wrapper test func TestCancelBatchExchangeOrder(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -911,6 +911,7 @@ func TestCancelBatchExchangeOrder(t *testing.T) { // TestCancelAllExchangeOrders wrapper test func TestCancelAllExchangeOrders(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -930,6 +931,7 @@ func TestCancelAllExchangeOrders(t *testing.T) { // TestGetAccountInfo wrapper test func TestGetAccountInfo(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() { _, err := k.UpdateAccountInfo(asset.Spot) if err != nil { @@ -945,6 +947,7 @@ func TestGetAccountInfo(t *testing.T) { } func TestUpdateFuturesAccountInfo(t *testing.T) { + t.Parallel() if !areTestAPIKeysSet() { t.Skip("API keys not set. Skipping the test") } @@ -957,6 +960,7 @@ func TestUpdateFuturesAccountInfo(t *testing.T) { // TestModifyOrder wrapper test func TestModifyOrder(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -968,6 +972,7 @@ func TestModifyOrder(t *testing.T) { // TestWithdraw wrapper test func TestWithdraw(t *testing.T) { + t.Parallel() withdrawCryptoRequest := withdraw.Request{ Exchange: k.Name, Crypto: withdraw.CryptoRequest{ @@ -994,6 +999,7 @@ func TestWithdraw(t *testing.T) { // TestWithdrawFiat wrapper test func TestWithdrawFiat(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -1016,6 +1022,7 @@ func TestWithdrawFiat(t *testing.T) { // TestWithdrawInternationalBank wrapper test func TestWithdrawInternationalBank(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -1038,6 +1045,7 @@ func TestWithdrawInternationalBank(t *testing.T) { // TestGetDepositAddress wrapper test func TestGetDepositAddress(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() { _, err := k.GetDepositAddress(currency.BTC, "") if err != nil { @@ -1053,6 +1061,7 @@ func TestGetDepositAddress(t *testing.T) { // TestWithdrawStatus wrapper test func TestWithdrawStatus(t *testing.T) { + t.Parallel() if areTestAPIKeysSet() { _, err := k.WithdrawStatus(currency.BTC, "") if err != nil { @@ -1068,6 +1077,7 @@ func TestWithdrawStatus(t *testing.T) { // TestWithdrawCancel wrapper test func TestWithdrawCancel(t *testing.T) { + t.Parallel() _, err := k.WithdrawCancel(currency.BTC, "") if areTestAPIKeysSet() && err == nil { t.Error("WithdrawCancel() error cannot be nil") @@ -1166,6 +1176,7 @@ func TestWsCancelAllOrders(t *testing.T) { } func TestWsPong(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "event": "pong", "reqid": 42 @@ -1177,6 +1188,7 @@ func TestWsPong(t *testing.T) { } func TestWsSystemStatus(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "connectionID": 8628615390848610000, "event": "systemStatus", @@ -1190,6 +1202,7 @@ func TestWsSystemStatus(t *testing.T) { } func TestWsSubscriptionStatus(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 10001, "channelName": "ticker", @@ -1251,6 +1264,7 @@ func TestWsSubscriptionStatus(t *testing.T) { } func TestWsTicker(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 1337, "channelName": "ticker", @@ -1317,6 +1331,7 @@ func TestWsTicker(t *testing.T) { } func TestWsOHLC(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 13337, "channelName": "ohlc", @@ -1354,6 +1369,7 @@ func TestWsOHLC(t *testing.T) { } func TestWsTrade(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 133337, "channelName": "trade", @@ -1398,6 +1414,7 @@ func TestWsTrade(t *testing.T) { } func TestWsSpread(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 1333337, "channelName": "spread", @@ -1431,6 +1448,7 @@ func TestWsSpread(t *testing.T) { } func TestWsOrdrbook(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "channelID": 13333337, "channelName": "book", @@ -1606,6 +1624,7 @@ func TestWsOrdrbook(t *testing.T) { } func TestWsOwnTrades(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`[ [ { @@ -1678,6 +1697,7 @@ func TestWsOwnTrades(t *testing.T) { } func TestWsOpenOrders(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`[ [ { @@ -1825,6 +1845,7 @@ func TestWsOpenOrders(t *testing.T) { } func TestWsAddOrderJSON(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "descr": "buy 0.01770000 XBTUSD @ limit 4000", "event": "addOrderStatus", @@ -1838,6 +1859,7 @@ func TestWsAddOrderJSON(t *testing.T) { } func TestWsCancelOrderJSON(t *testing.T) { + t.Parallel() pressXToJSON := []byte(`{ "event": "cancelOrderStatus", "status": "ok" @@ -1849,6 +1871,7 @@ func TestWsCancelOrderJSON(t *testing.T) { } func TestParseTime(t *testing.T) { + t.Parallel() // Test REST example r := convert.TimeFromUnixTimestampDecimal(1373750306.9819).UTC() if r.Year() != 2013 || @@ -1867,11 +1890,12 @@ func TestParseTime(t *testing.T) { } func TestGetHistoricCandles(t *testing.T) { + t.Parallel() currencyPair, err := currency.NewPairFromString("XBT-USD") if err != nil { t.Fatal(err) } - _, err = k.GetHistoricCandles(currencyPair, asset.Spot, time.Now().AddDate(0, 0, -1), time.Now(), kline.OneMin) + _, err = k.GetHistoricCandles(currencyPair, asset.Spot, time.Now(), time.Now().Add(-time.Minute*3), kline.OneMin) if err != nil { t.Fatal(err) } @@ -1883,11 +1907,12 @@ func TestGetHistoricCandles(t *testing.T) { } func TestGetHistoricCandlesExtended(t *testing.T) { + t.Parallel() currencyPair, err := currency.NewPairFromString("XBT-USD") if err != nil { t.Fatal(err) } - _, err = k.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Now().AddDate(0, -6, 0), time.Now(), kline.OneDay) + _, err = k.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Now().Add(-time.Hour*48), time.Now(), kline.OneDay) if err != nil { t.Fatal(err) } @@ -1899,6 +1924,7 @@ func TestGetHistoricCandlesExtended(t *testing.T) { } func Test_FormatExchangeKlineInterval(t *testing.T) { + t.Parallel() testCases := []struct { name string interval kline.Interval @@ -1931,7 +1957,7 @@ func Test_FormatExchangeKlineInterval(t *testing.T) { func TestGetRecentTrades(t *testing.T) { t.Parallel() - currencyPair, err := currency.NewPairFromString("XBTUSD") + currencyPair, err := currency.NewPairFromString("BCHEUR") if err != nil { t.Fatal(err) } @@ -1983,6 +2009,7 @@ var testOb = orderbook.Base{ const krakenAPIDocChecksum = 974947235 func TestChecksumCalculation(t *testing.T) { + t.Parallel() expected := "5005" if v := trim("0.05005"); v != expected { t.Fatalf("expected %s but received %s", expected, v) diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index 7a6c4c27..522730c0 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -58,9 +58,12 @@ const ( // orderbookMutex Ensures if two entries arrive at once, only one can be // processed at a time -var subscriptionChannelPair []WebsocketChannelData -var authToken string -var pingRequest = WebsocketBaseEventRequest{Event: stream.Ping} +var ( + subscriptionChannelPair []WebsocketChannelData + authToken string + pingRequest = WebsocketBaseEventRequest{Event: stream.Ping} + m sync.Mutex +) // Channels require a topic and a currency // Format [[ticker,but-t4u],[orderbook,nce-btt]] @@ -625,6 +628,8 @@ func (k *Kraken) addNewSubscriptionChannelData(response *wsSubscription) { return } } + m.Lock() + defer m.Unlock() subscriptionChannelPair = append(subscriptionChannelPair, WebsocketChannelData{ Subscription: response.Subscription.Name, Pair: fPair, @@ -634,6 +639,8 @@ func (k *Kraken) addNewSubscriptionChannelData(response *wsSubscription) { // getSubscriptionChannelData retrieves WebsocketChannelData based on response ID func getSubscriptionChannelData(id int64) (WebsocketChannelData, error) { + m.Lock() + defer m.Unlock() for i := range subscriptionChannelPair { if subscriptionChannelPair[i].ChannelID == nil { continue diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go index d5009b99..5d4da1db 100644 --- a/exchanges/lakebtc/lakebtc_test.go +++ b/exchanges/lakebtc/lakebtc_test.go @@ -492,7 +492,7 @@ func TestGetHistoricTrades(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Hour*24), time.Now()) + _, err = l.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Minute*15), time.Now()) if err != nil && err != common.ErrFunctionNotSupported { t.Error(err) } diff --git a/exchanges/lbank/lbank_test.go b/exchanges/lbank/lbank_test.go index bcdfb39e..a17dd938 100644 --- a/exchanges/lbank/lbank_test.go +++ b/exchanges/lbank/lbank_test.go @@ -427,7 +427,7 @@ func TestGetHistoricCandles(t *testing.T) { func TestGetHistoricCandlesExtended(t *testing.T) { t.Parallel() - startTime := time.Now().Add(-time.Hour) + startTime := time.Now().Add(-time.Minute * 2) end := time.Now() pair, err := currency.NewPairFromString("eth_btc") if err != nil { diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go index 5672730c..a7da426f 100644 --- a/exchanges/lbank/lbank_wrapper.go +++ b/exchanges/lbank/lbank_wrapper.go @@ -356,7 +356,7 @@ func (l *Lbank) GetWithdrawalsHistory(c currency.Code) (resp []exchange.Withdraw // GetRecentTrades returns the most recent trades for a currency and asset func (l *Lbank) GetRecentTrades(p currency.Pair, assetType asset.Item) ([]trade.Data, error) { - return l.GetHistoricTrades(p, assetType, time.Now().Add(-time.Hour), time.Now()) + return l.GetHistoricTrades(p, assetType, time.Now().Add(-time.Minute*15), time.Now()) } // GetHistoricTrades returns historic trade data within the timeframe provided diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go index 41169115..f043659c 100644 --- a/exchanges/okcoin/okcoin_test.go +++ b/exchanges/okcoin/okcoin_test.go @@ -823,7 +823,6 @@ func TestOrderBookUpdateChecksumCalculator(t *testing.T) { if err != nil { t.Fatal(err) } - time.Sleep(time.Second) err = o.WsProcessOrderBook([]byte(update)) if err != nil { t.Error(err) @@ -841,7 +840,6 @@ func TestOrderBookUpdateChecksumCalculatorWith8DecimalPlaces(t *testing.T) { if err != nil { t.Fatal(err) } - time.Sleep(time.Second) err = o.WsProcessOrderBook([]byte(update)) if err != nil { t.Error(err) diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index dc7c5c05..1d8b7aef 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -1647,7 +1647,6 @@ func TestOrderBookUpdateChecksumCalculator(t *testing.T) { if err != nil { t.Fatal(err) } - time.Sleep(time.Second) err = o.WsHandleData([]byte(update)) if err != nil { t.Error(err) @@ -1662,7 +1661,6 @@ func TestOrderBookUpdateChecksumCalculatorWith8DecimalPlaces(t *testing.T) { if err != nil { t.Fatal(err) } - time.Sleep(time.Second) err = o.WsHandleData([]byte(update)) if err != nil { t.Error(err) diff --git a/exchanges/stream/buffer/buffer_test.go b/exchanges/stream/buffer/buffer_test.go index e5a96d72..6511c97e 100644 --- a/exchanges/stream/buffer/buffer_test.go +++ b/exchanges/stream/buffer/buffer_test.go @@ -423,6 +423,7 @@ func TestOrderbookLastUpdateID(t *testing.T) { // TestRunUpdateWithoutSnapshot logic test func TestRunUpdateWithoutSnapshot(t *testing.T) { + t.Parallel() var holder Orderbook var snapShot1 orderbook.Base asks := []orderbook.Item{ @@ -451,6 +452,7 @@ func TestRunUpdateWithoutSnapshot(t *testing.T) { // TestRunUpdateWithoutAnyUpdates logic test func TestRunUpdateWithoutAnyUpdates(t *testing.T) { + t.Parallel() var obl Orderbook var snapShot1 orderbook.Base snapShot1.Asks = []orderbook.Item{} @@ -472,6 +474,7 @@ func TestRunUpdateWithoutAnyUpdates(t *testing.T) { // TestRunSnapshotWithNoData logic test func TestRunSnapshotWithNoData(t *testing.T) { + t.Parallel() var obl Orderbook obl.ob = make(map[currency.Code]map[currency.Code]map[asset.Item]*orderbookHolder) obl.dataHandler = make(chan interface{}, 1) @@ -488,6 +491,7 @@ func TestRunSnapshotWithNoData(t *testing.T) { // TestLoadSnapshot logic test func TestLoadSnapshot(t *testing.T) { + t.Parallel() var obl Orderbook obl.dataHandler = make(chan interface{}, 100) obl.ob = make(map[currency.Code]map[currency.Code]map[asset.Item]*orderbookHolder) @@ -509,8 +513,8 @@ func TestLoadSnapshot(t *testing.T) { } } -// TestFlushbuffer logic test -func TestFlushbuffer(t *testing.T) { +// TestFlushBuffer logic test +func TestFlushBuffer(t *testing.T) { obl, _, _, err := createSnapshot() if err != nil { t.Fatal(err) @@ -526,6 +530,7 @@ func TestFlushbuffer(t *testing.T) { // TestInsertingSnapShots logic test func TestInsertingSnapShots(t *testing.T) { + t.Parallel() var holder Orderbook holder.dataHandler = make(chan interface{}, 100) holder.ob = make(map[currency.Code]map[currency.Code]map[asset.Item]*orderbookHolder) @@ -705,6 +710,7 @@ func TestGetOrderbook(t *testing.T) { } func TestSetup(t *testing.T) { + t.Parallel() w := Orderbook{} err := w.Setup(0, false, false, false, false, true, "", nil) if !errors.Is(err, errUnsetExchangeName) { @@ -736,6 +742,7 @@ func TestSetup(t *testing.T) { } func TestValidate(t *testing.T) { + t.Parallel() w := Orderbook{} err := w.validate(nil) if !errors.Is(err, errUpdateIsNil) { @@ -749,6 +756,7 @@ func TestValidate(t *testing.T) { } func TestEnsureMultipleUpdatesViaPrice(t *testing.T) { + t.Parallel() holder, _, _, err := createSnapshot() if err != nil { t.Error(err) @@ -782,6 +790,7 @@ func deploySliceOrdered(size int) orderbook.Items { } func TestUpdateByIDAndAction(t *testing.T) { + t.Parallel() holder := orderbookHolder{} asks := deploySliceOrdered(100) @@ -990,6 +999,7 @@ func TestUpdateByIDAndAction(t *testing.T) { } func TestFlushOrderbook(t *testing.T) { + t.Parallel() w := &Orderbook{} err := w.Setup(5, false, false, false, false, false, "test", make(chan interface{}, 2)) if err != nil { diff --git a/exchanges/stream/stream_match_test.go b/exchanges/stream/stream_match_test.go index 743a2d94..0a72390e 100644 --- a/exchanges/stream/stream_match_test.go +++ b/exchanges/stream/stream_match_test.go @@ -6,6 +6,7 @@ import ( ) func TestMatch(t *testing.T) { + t.Parallel() bm := &Match{} if bm.Incoming("wow") { t.Fatal("Should not have matched") diff --git a/exchanges/stream/websocket_test.go b/exchanges/stream/websocket_test.go index 5651f1f1..e6fcf775 100644 --- a/exchanges/stream/websocket_test.go +++ b/exchanges/stream/websocket_test.go @@ -87,6 +87,7 @@ func (d *dodgyConnection) Connect() error { } func TestSetup(t *testing.T) { + t.Parallel() var w *Websocket err := w.Setup(nil) if err == nil { @@ -164,7 +165,7 @@ func TestTrafficMonitorTimeout(t *testing.T) { if err != nil { t.Fatal(err) } - ws.trafficTimeout = time.Millisecond + ws.trafficTimeout = time.Second * 2 ws.ShutdownC = make(chan struct{}) ws.trafficMonitor() if !ws.IsTrafficMonitorRunning() { @@ -187,6 +188,7 @@ func TestTrafficMonitorTimeout(t *testing.T) { } func TestIsDisconnectionError(t *testing.T) { + t.Parallel() isADisconnectionError := isDisconnectionError(errors.New("errorText")) if isADisconnectionError { t.Error("Its not") @@ -215,6 +217,7 @@ func TestIsDisconnectionError(t *testing.T) { } func TestConnectionMessageErrors(t *testing.T) { + t.Parallel() var wsWrong = &Websocket{} err := wsWrong.Connect() if err == nil { @@ -283,6 +286,7 @@ outer: } func TestWebsocket(t *testing.T) { + t.Parallel() wsInit := Websocket{} err := wsInit.Setup(&WebsocketSetup{ ExchangeName: "test", @@ -440,6 +444,7 @@ func TestWebsocket(t *testing.T) { // TestSubscribe logic test func TestSubscribeUnsubscribe(t *testing.T) { + t.Parallel() ws := *New() err := ws.Setup(defaultSetup) if err != nil { @@ -498,6 +503,7 @@ func TestSubscribeUnsubscribe(t *testing.T) { } func TestResubscribe(t *testing.T) { + t.Parallel() ws := *New() err := ws.Setup(defaultSetup) if err != nil { @@ -534,6 +540,7 @@ func TestResubscribe(t *testing.T) { // TestConnectionMonitorNoConnection logic test func TestConnectionMonitorNoConnection(t *testing.T) { + t.Parallel() ws := *New() ws.DataHandler = make(chan interface{}, 1) ws.ShutdownC = make(chan struct{}, 1) @@ -567,6 +574,7 @@ func TestConnectionMonitorNoConnection(t *testing.T) { // TestSliceCopyDoesntImpactBoth logic test func TestGetSubscriptions(t *testing.T) { + t.Parallel() w := Websocket{ subscriptions: []ChannelSubscription{ { @@ -581,6 +589,7 @@ func TestGetSubscriptions(t *testing.T) { // TestSetCanUseAuthenticatedEndpoints logic test func TestSetCanUseAuthenticatedEndpoints(t *testing.T) { + t.Parallel() ws := *New() result := ws.CanUseAuthenticatedEndpoints() if result { @@ -595,6 +604,7 @@ func TestSetCanUseAuthenticatedEndpoints(t *testing.T) { // TestDial logic test func TestDial(t *testing.T) { + t.Parallel() var testCases = []testStruct{ {Error: nil, WC: WebsocketConnection{ @@ -642,6 +652,7 @@ func TestDial(t *testing.T) { // TestSendMessage logic test func TestSendMessage(t *testing.T) { + t.Parallel() var testCases = []testStruct{ {Error: nil, WC: WebsocketConnection{ ExchangeName: "test1", @@ -696,6 +707,7 @@ func TestSendMessage(t *testing.T) { // TestSendMessageWithResponse logic test func TestSendMessageWithResponse(t *testing.T) { + t.Parallel() wc := &WebsocketConnection{ Verbose: true, URL: "wss://ws.kraken.com", @@ -757,6 +769,7 @@ func readMessages(wc *WebsocketConnection, t *testing.T) { // TestSetupPingHandler logic test func TestSetupPingHandler(t *testing.T) { + t.Parallel() wc := &WebsocketConnection{ URL: websocketTestURL, ResponseMaxLimit: time.Second * 5, @@ -800,6 +813,7 @@ func TestSetupPingHandler(t *testing.T) { // TestParseBinaryResponse logic test func TestParseBinaryResponse(t *testing.T) { + t.Parallel() wc := &WebsocketConnection{ URL: websocketTestURL, ResponseMaxLimit: time.Second * 5, @@ -849,6 +863,7 @@ func TestParseBinaryResponse(t *testing.T) { // TestCanUseAuthenticatedWebsocketForWrapper logic test func TestCanUseAuthenticatedWebsocketForWrapper(t *testing.T) { + t.Parallel() ws := &Websocket{} resp := ws.CanUseAuthenticatedWebsocketForWrapper() if resp { @@ -867,6 +882,7 @@ func TestCanUseAuthenticatedWebsocketForWrapper(t *testing.T) { } func TestGenerateMessageID(t *testing.T) { + t.Parallel() wc := WebsocketConnection{} var id int64 for i := 0; i < 10; i++ { @@ -927,6 +943,7 @@ func TestCheckWebsocketURL(t *testing.T) { } func TestGetChannelDifference(t *testing.T) { + t.Parallel() web := Websocket{} newChans := []ChannelSubscription{ @@ -1022,6 +1039,7 @@ func (g *GenSubs) UNSUBME(unsubs []ChannelSubscription) error { func connect() error { return nil } func TestFlushChannels(t *testing.T) { + t.Parallel() // Enabled pairs/setup system newgen := GenSubs{EnabledPairs: []currency.Pair{ currency.NewPair(currency.BTC, currency.AUD), @@ -1143,6 +1161,7 @@ func TestFlushChannels(t *testing.T) { } func TestDisable(t *testing.T) { + t.Parallel() web := Websocket{ enabled: true, connected: true, @@ -1159,6 +1178,7 @@ func TestDisable(t *testing.T) { } func TestEnable(t *testing.T) { + t.Parallel() web := Websocket{ connector: connect, Wg: new(sync.WaitGroup), @@ -1178,6 +1198,7 @@ func TestEnable(t *testing.T) { } func TestSetupNewConnection(t *testing.T) { + t.Parallel() var nonsenseWebsock *Websocket err := nonsenseWebsock.SetupNewConnection(ConnectionSetup{URL: "urlstring"}) if err == nil { @@ -1232,6 +1253,7 @@ func TestSetupNewConnection(t *testing.T) { } func TestWebsocketConnectionShutdown(t *testing.T) { + t.Parallel() wc := WebsocketConnection{} err := wc.Shutdown() if err != nil { diff --git a/exchanges/trade/trade_test.go b/exchanges/trade/trade_test.go index 3ea32e80..82de3968 100644 --- a/exchanges/trade/trade_test.go +++ b/exchanges/trade/trade_test.go @@ -203,17 +203,16 @@ func TestShutdown(t *testing.T) { t.Parallel() var p Processor p.mutex.Lock() - p.bufferProcessorInterval = time.Second + p.bufferProcessorInterval = time.Millisecond p.mutex.Unlock() var wg sync.WaitGroup wg.Add(1) go p.Run(&wg) wg.Wait() - time.Sleep(time.Millisecond) if atomic.LoadInt32(&p.started) != 1 { t.Error("expected it to start running") } - time.Sleep(time.Second * 2) + time.Sleep(time.Millisecond * 20) if atomic.LoadInt32(&p.started) != 0 { t.Error("expected it to stop running") } diff --git a/gctscript/vm/vm_test.go b/gctscript/vm/vm_test.go index c4309550..50768cae 100644 --- a/gctscript/vm/vm_test.go +++ b/gctscript/vm/vm_test.go @@ -93,7 +93,6 @@ func TestVMLoad1s(t *testing.T) { } testVM.CompileAndRun() - time.Sleep(5000) err = testVM.Shutdown() if err != nil { if !errors.Is(err, ErrNoVMLoaded) { diff --git a/portfolio/banking/banking.go b/portfolio/banking/banking.go index fabc0ffe..1b517129 100644 --- a/portfolio/banking/banking.go +++ b/portfolio/banking/banking.go @@ -8,14 +8,35 @@ import ( "github.com/thrasher-corp/gocryptotrader/currency" ) +// SetAccounts safely overwrites bank account slice +func SetAccounts(accs ...Account) { + m.Lock() + defer m.Unlock() + accounts = accs +} + +// AppendAccounts safely adds to bank account slice +func AppendAccounts(accs ...Account) { + m.Lock() + defer m.Unlock() +accountRange: + for j := range accs { + for i := range accounts { + if accounts[i].AccountNumber == accs[j].AccountNumber { + continue accountRange + } + } + accounts = append(accounts, accs[j]) + } +} + // GetBankAccountByID Returns a bank account based on its ID func GetBankAccountByID(id string) (*Account, error) { m.Lock() defer m.Unlock() - - for x := range Accounts { - if strings.EqualFold(Accounts[x].ID, id) { - return &Accounts[x], nil + for x := range accounts { + if strings.EqualFold(accounts[x].ID, id) { + return &accounts[x], nil } } return nil, fmt.Errorf(ErrBankAccountNotFound, id) @@ -83,7 +104,7 @@ func (b *Account) ValidateForWithdrawal(exchange string, cur currency.Code) (err if cur.Upper() == currency.AUD { if b.BSBNumber == "" { - err = append(err, ErrBSBRequiredforAUD) + err = append(err, ErrBSBRequiredForAUD) } } else { if b.IBAN == "" && b.SWIFTCode == "" { diff --git a/portfolio/banking/banking_test.go b/portfolio/banking/banking_test.go index a45a20d5..bf120944 100644 --- a/portfolio/banking/banking_test.go +++ b/portfolio/banking/banking_test.go @@ -8,53 +8,51 @@ import ( ) var ( - testBankAccounts = []Account{ - { - Enabled: true, - ID: "valid-test-bank-01", - BankName: "Test Bank", - BankAddress: "42 Bank Street", - BankPostalCode: "13337", - BankPostalCity: "Satoshiville", - BankCountry: "Japan", - AccountName: "Satoshi Nakamoto", - AccountNumber: "0234", - SWIFTCode: "91272837", - BSBNumber: "123456", - IBAN: "98218738671897", - SupportedCurrencies: "AUD,USD", - SupportedExchanges: "test-exchange", - }, - { - Enabled: false, - ID: "invalid-test-bank-01", - BankName: "", - BankAddress: "", - BankPostalCode: "", - BankPostalCity: "", - BankCountry: "", - AccountName: "", - AccountNumber: "", - SWIFTCode: "", - BSBNumber: "", - IBAN: "", - SupportedCurrencies: "", - SupportedExchanges: "", - }, + validAccount = Account{ + Enabled: true, + ID: "valid-test-bank-01", + BankName: "Test Bank", + BankAddress: "42 Bank Street", + BankPostalCode: "13337", + BankPostalCity: "Satoshiville", + BankCountry: "Japan", + AccountName: "Satoshi Nakamoto", + AccountNumber: "0234", + SWIFTCode: "91272837", + BSBNumber: "123456", + IBAN: "98218738671897", + SupportedCurrencies: "AUD,USD", + SupportedExchanges: "test-exchange", + } + invalidAccount = Account{ + Enabled: false, + ID: "invalid-test-bank-01", + BankName: "", + BankAddress: "", + BankPostalCode: "", + BankPostalCity: "", + BankCountry: "", + AccountName: "", + AccountNumber: "", + SWIFTCode: "", + BSBNumber: "", + IBAN: "", + SupportedCurrencies: "", + SupportedExchanges: "", } ) func TestMain(m *testing.M) { - Accounts = append(Accounts, testBankAccounts...) os.Exit(m.Run()) } func TestGetBankAccountByID(t *testing.T) { + t.Parallel() + SetAccounts(validAccount, invalidAccount) _, err := GetBankAccountByID("valid-test-bank-01") if err != nil { t.Error(err) } - _, err = GetBankAccountByID("invalid-test-") if err == nil { t.Error("error expected for invalid account received nil") @@ -62,29 +60,25 @@ func TestGetBankAccountByID(t *testing.T) { } func TestAccount_Validate(t *testing.T) { - valid, err := GetBankAccountByID("valid-test-bank-01") - if err != nil { - t.Fatal(err) + t.Parallel() + testBankAccounts := []Account{ + validAccount, invalidAccount, } - if err = valid.Validate(); err != nil { - t.Error(err) - } - invalid := testBankAccounts[1] - if err = invalid.Validate(); err == nil { + if err := invalid.Validate(); err == nil { t.Error(err) } invalid = testBankAccounts[0] invalid.SupportedCurrencies = "AUD" invalid.BSBNumber = "" - if err = invalid.Validate(); err == nil { + if err := invalid.Validate(); err == nil { t.Error("Expected error when Currency is AUD but no BSB set") } invalid = testBankAccounts[0] invalid.SupportedExchanges = "" - if err = invalid.Validate(); err != nil { + if err := invalid.Validate(); err != nil { t.Error("Expected error when Currency is AUD but no BSB set") } if invalid.SupportedExchanges != "ALL" { @@ -95,53 +89,73 @@ func TestAccount_Validate(t *testing.T) { invalid.SWIFTCode = "" invalid.IBAN = "" invalid.SupportedCurrencies = "USD" - if err = invalid.Validate(); err == nil { + if err := invalid.Validate(); err == nil { t.Error("Expected error when no Swift/IBAN set") } } func TestAccount_ValidateForWithdrawal(t *testing.T) { - v, err := GetBankAccountByID("valid-test-bank-01") - if err != nil { - t.Fatal(err) - } - errWith := v.ValidateForWithdrawal("test-exchange", currency.AUD) + t.Parallel() + acc := validAccount + errWith := acc.ValidateForWithdrawal("test-exchange", currency.AUD) if errWith != nil { t.Fatal(errWith) } - v.BSBNumber = "" - errWith = v.ValidateForWithdrawal("test-exchange", currency.AUD) + acc.BSBNumber = "" + errWith = acc.ValidateForWithdrawal("test-exchange", currency.AUD) if errWith != nil { - if errWith[0] != ErrBSBRequiredforAUD { + if errWith[0] != ErrBSBRequiredForAUD { t.Fatal(errWith) } } - v.SWIFTCode = "" - v.IBAN = "" - errWith = v.ValidateForWithdrawal("test-exchange", currency.USD) + acc.SWIFTCode = "" + acc.IBAN = "" + errWith = acc.ValidateForWithdrawal("test-exchange", currency.USD) if errWith != nil { if errWith[0] != ErrIBANSwiftNotSet { t.Fatal(errWith) } } - errWith = v.ValidateForWithdrawal("test-exchange-nope", currency.AUD) + errWith = acc.ValidateForWithdrawal("test-exchange-nope", currency.AUD) if errWith != nil { if errWith[0] != "Exchange test-exchange-nope not supported by bank account" { t.Fatal(errWith) } } - v.AccountNumber = "" - errWith = v.ValidateForWithdrawal("test-exchange", currency.AUD) + acc.AccountNumber = "" + errWith = acc.ValidateForWithdrawal("test-exchange", currency.AUD) if errWith != nil { if errWith[0] != ErrAccountCannotBeEmpty { t.Fatal(errWith) } } - v.Enabled = false - errWith = v.ValidateForWithdrawal("test-exchange", currency.AUD) + acc.Enabled = false + errWith = acc.ValidateForWithdrawal("test-exchange", currency.AUD) if errWith != nil { if errWith[0] != ErrBankAccountDisabled { t.Fatal(errWith) } } } + +func TestSetAccounts(t *testing.T) { + SetAccounts() + if len(accounts) != 0 { + t.Error("expected 0") + } + SetAccounts(validAccount, invalidAccount) + if len(accounts) != 2 { + t.Error("expected 2") + } +} + +func TestAppendAccounts(t *testing.T) { + SetAccounts() + if len(accounts) != 0 { + t.Error("expected 0") + } + AppendAccounts(validAccount, invalidAccount) + if len(accounts) != 2 { + t.Error("expected 2") + } +} diff --git a/portfolio/banking/banking_types.go b/portfolio/banking/banking_types.go index e8932c07..012e7816 100644 --- a/portfolio/banking/banking_types.go +++ b/portfolio/banking/banking_types.go @@ -7,14 +7,12 @@ import ( const ( // ErrBankAccountNotFound message to return when bank account was not found ErrBankAccountNotFound = "bank account ID: %v not found" - // ErrAccountCannotBeNil message to return when bank account is nil - ErrAccountCannotBeNil = "Account cannot be nil" // ErrAccountCannotBeEmpty message to return when bank account number is empty ErrAccountCannotBeEmpty = "Bank Account Number cannot be empty" // ErrBankAccountDisabled message to return when bank account is disabled ErrBankAccountDisabled = "Bank Account is disabled" - // ErrBSBRequiredforAUD message to return when currency is AUD but no bsb is set - ErrBSBRequiredforAUD = "BSB must be set for AUD values" + // ErrBSBRequiredForAUD message to return when currency is AUD but no bsb is set + ErrBSBRequiredForAUD = "BSB must be set for AUD values" // ErrIBANSwiftNotSet message to return when no iban or swift value set ErrIBANSwiftNotSet = "IBAN/SWIFT values not set" // ErrCurrencyNotSupportedByAccount message to return when the requested @@ -22,6 +20,11 @@ const ( ErrCurrencyNotSupportedByAccount = "requested currency is not supported by account" ) +var ( + accounts []Account + m sync.Mutex +) + // Account holds differing bank account details by supported funding // currency type Account struct { @@ -41,7 +44,3 @@ type Account struct { SupportedCurrencies string `json:"supportedCurrencies"` SupportedExchanges string `json:"supportedExchanges,omitempty"` } - -// Accounts holds all bank account details -var Accounts []Account -var m = &sync.Mutex{} diff --git a/portfolio/portfolio_test.go b/portfolio/portfolio_test.go index 73082f15..020d875c 100644 --- a/portfolio/portfolio_test.go +++ b/portfolio/portfolio_test.go @@ -3,7 +3,6 @@ package portfolio import ( "errors" "testing" - "time" "github.com/thrasher-corp/gocryptotrader/core" "github.com/thrasher-corp/gocryptotrader/currency" @@ -14,6 +13,7 @@ const ( ) func TestGetEthereumBalance(t *testing.T) { + t.Parallel() b := Base{} address := "0xb794f5ea0ba39494ce839613fffba74279579268" nonsenseAddress := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" @@ -34,6 +34,7 @@ func TestGetEthereumBalance(t *testing.T) { } func TestGetCryptoIDBalance(t *testing.T) { + t.Parallel() b := Base{} ltcAddress := "LX2LMYXtuv5tiYEMztSSoEZcafFPYJFRK1" _, err := b.GetCryptoIDAddress(ltcAddress, currency.LTC) @@ -43,6 +44,7 @@ func TestGetCryptoIDBalance(t *testing.T) { } func TestGetAddressBalance(t *testing.T) { + t.Parallel() ltcAddress := "LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL" ltc := currency.LTC description := "Description of Wallet" @@ -75,6 +77,7 @@ func TestGetAddressBalance(t *testing.T) { } func TestGetRippleBalance(t *testing.T) { + t.Parallel() b := Base{} nonsenseAddress := "Wigwham" _, err := b.GetRippleBalance(nonsenseAddress) @@ -90,6 +93,7 @@ func TestGetRippleBalance(t *testing.T) { } func TestExchangeExists(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), @@ -108,6 +112,7 @@ func TestExchangeExists(t *testing.T) { } func TestAddressExists(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), @@ -126,6 +131,7 @@ func TestAddressExists(t *testing.T) { } func TestExchangeAddressExists(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), @@ -144,6 +150,7 @@ func TestExchangeAddressExists(t *testing.T) { } func TestAddExchangeAddress(t *testing.T) { + t.Parallel() newBase := Base{} newBase.AddExchangeAddress("OKEX", currency.BTC, 100) newBase.AddExchangeAddress("OKEX", currency.BTC, 200) @@ -154,6 +161,7 @@ func TestAddExchangeAddress(t *testing.T) { } func TestUpdateAddressBalance(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), @@ -173,6 +181,7 @@ func TestUpdateAddressBalance(t *testing.T) { } func TestRemoveAddress(t *testing.T) { + t.Parallel() var newBase Base if err := newBase.RemoveAddress("", "MEOW", currency.LTC); err == nil { t.Error("invalid address should throw an error") @@ -210,6 +219,7 @@ func TestRemoveAddress(t *testing.T) { } func TestRemoveExchangeAddress(t *testing.T) { + t.Parallel() newBase := Base{} exchangeName := "BallerExchange" coinType := currency.LTC @@ -227,6 +237,7 @@ func TestRemoveExchangeAddress(t *testing.T) { } func TestUpdateExchangeAddressBalance(t *testing.T) { + t.Parallel() newBase := Base{} newBase.AddExchangeAddress("someaddress", currency.LTC, 0.02) b := Base{} @@ -240,6 +251,7 @@ func TestUpdateExchangeAddressBalance(t *testing.T) { } func TestAddAddress(t *testing.T) { + t.Parallel() var newBase Base if err := newBase.AddAddress("", "MEOW", currency.LTC, 1); err == nil { t.Error("invalid address should throw an error") @@ -298,22 +310,9 @@ func TestAddAddress(t *testing.T) { } func TestUpdatePortfolio(t *testing.T) { + t.Parallel() newBase := Base{} - err := newBase.AddAddress("someaddress", - currency.LTC.String(), - currency.NewCode("LTCWALLETTEST"), - 0.02) - if err != nil { - t.Fatal(err) - } - - err = newBase.UpdatePortfolio( - []string{"LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL"}, - currency.LTC) - if err != nil { - t.Error("UpdatePortfolio error", err) - } - err = newBase.UpdatePortfolio([]string{"Testy"}, currency.LTC) + err := newBase.UpdatePortfolio([]string{"Testy"}, currency.LTC) if err == nil { t.Error("UpdatePortfolio error cannot be nil") } @@ -326,22 +325,19 @@ func TestUpdatePortfolio(t *testing.T) { t.Error("UpdatePortfolio error", err) } err = newBase.UpdatePortfolio( - []string{"LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL", "Testy"}, currency.LTC, + []string{"Testy"}, currency.LTC, ) if err == nil { t.Error("UpdatePortfolio error cannot be nil") } - time.Sleep(time.Second * 5) err = newBase.UpdatePortfolio([]string{ - "0xb794f5ea0ba39494ce839613fffba74279579268", - "0xe853c56864a2ebe4576a807d26fdc4a0ada51919"}, + "0xb794f5ea0ba39494ce839613fffba74279579268"}, currency.ETH) if err != nil { t.Error(err) } err = newBase.UpdatePortfolio([]string{ - "0xb794f5ea0ba39494ce839613fffba74279579268", "TESTY"}, currency.ETH) if err == nil { @@ -363,7 +359,6 @@ func TestUpdatePortfolio(t *testing.T) { } err = newBase.UpdatePortfolio([]string{ - "r962iS5subzbVeXZN8MTzyEuuaQKo5qksh", "TESTY"}, currency.XRP) if err == nil { @@ -372,6 +367,7 @@ func TestUpdatePortfolio(t *testing.T) { } func TestGetPortfolioByExchange(t *testing.T) { + t.Parallel() newBase := Base{} newBase.AddExchangeAddress("OKEX", currency.LTC, 0.07) newBase.AddExchangeAddress("Bitfinex", currency.LTC, 0.05) @@ -401,6 +397,7 @@ func TestGetPortfolioByExchange(t *testing.T) { } func TestGetExchangePortfolio(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("OKEX", ExchangeAddress, currency.LTC, 0.03) if err != nil { @@ -428,6 +425,7 @@ func TestGetExchangePortfolio(t *testing.T) { } func TestGetPersonalPortfolio(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", PersonalAddress, currency.N2O, 0.02) if err != nil { @@ -454,6 +452,7 @@ func TestGetPersonalPortfolio(t *testing.T) { } func TestGetPortfolioSummary(t *testing.T) { + t.Parallel() newBase := Base{} // Personal holdings err := newBase.AddAddress("someaddress", PersonalAddress, currency.LTC, 1) @@ -513,6 +512,7 @@ func TestGetPortfolioSummary(t *testing.T) { } func TestGetPortfolioGroupedCoin(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), currency.LTC, 0.02) if err != nil { @@ -530,6 +530,7 @@ func TestGetPortfolioGroupedCoin(t *testing.T) { } func TestSeed(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("someaddress", currency.LTC.String(), currency.LTC, 0.02) if err != nil { @@ -541,6 +542,7 @@ func TestSeed(t *testing.T) { } func TestIsExchangeSupported(t *testing.T) { + t.Parallel() newBase := seedPortFolioForTest(t) ret := newBase.IsExchangeSupported("BTC Markets", core.BitcoinDonationAddress) if !ret { @@ -553,6 +555,7 @@ func TestIsExchangeSupported(t *testing.T) { } func TestIsColdStorage(t *testing.T) { + t.Parallel() newBase := seedPortFolioForTest(t) ret := newBase.IsColdStorage(core.BitcoinDonationAddress) if !ret { @@ -569,6 +572,7 @@ func TestIsColdStorage(t *testing.T) { } func TestIsWhiteListed(t *testing.T) { + t.Parallel() b := seedPortFolioForTest(t) ret := b.IsWhiteListed(core.BitcoinDonationAddress) if !ret { @@ -585,6 +589,7 @@ func TestIsWhiteListed(t *testing.T) { } func TestStartPortfolioWatcher(t *testing.T) { + t.Parallel() newBase := Base{} err := newBase.AddAddress("LX2LMYXtuv5tiYEMztSSoEZcafFPYJFRK1", currency.LTC.String(), diff --git a/portfolio/withdraw/validate_test.go b/portfolio/withdraw/validate_test.go index 00aedc89..0984a10c 100644 --- a/portfolio/withdraw/validate_test.go +++ b/portfolio/withdraw/validate_test.go @@ -128,24 +128,22 @@ func TestMain(m *testing.M) { os.Exit(0) } p.Addresses[1].SupportedExchanges = "BTC Markets,Binance" - - banking.Accounts = append(banking.Accounts, - banking.Account{ - Enabled: true, - ID: "test-bank-01", - BankName: "Test Bank", - BankAddress: "42 Bank Street", - BankPostalCode: "13337", - BankPostalCity: "Satoshiville", - BankCountry: "Japan", - AccountName: "Satoshi Nakamoto", - AccountNumber: "0234", - BSBNumber: "123456", - SWIFTCode: "91272837", - IBAN: "98218738671897", - SupportedCurrencies: "AUD,USD", - SupportedExchanges: "test-exchange", - }, + banking.AppendAccounts(banking.Account{ + Enabled: true, + ID: "test-bank-01", + BankName: "Test Bank", + BankAddress: "42 Bank Street", + BankPostalCode: "13337", + BankPostalCity: "Satoshiville", + BankCountry: "Japan", + AccountName: "Satoshi Nakamoto", + AccountNumber: "0234", + BSBNumber: "123456", + SWIFTCode: "91272837", + IBAN: "98218738671897", + SupportedCurrencies: "AUD,USD", + SupportedExchanges: "test-exchange", + }, ) os.Exit(m.Run())