From 07e288c7df802e2f898f0f221a15339b8614f1cb Mon Sep 17 00:00:00 2001 From: edwin Date: Tue, 5 Mar 2024 17:44:32 +0800 Subject: [PATCH] pkg/exchange: add tests for query k line --- .../v2/testdata/get_k_line_request.json | 27 +++ pkg/exchange/bitget/exchange_test.go | 159 ++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 pkg/exchange/bitget/bitgetapi/v2/testdata/get_k_line_request.json diff --git a/pkg/exchange/bitget/bitgetapi/v2/testdata/get_k_line_request.json b/pkg/exchange/bitget/bitgetapi/v2/testdata/get_k_line_request.json new file mode 100644 index 0000000000..4f1dd32435 --- /dev/null +++ b/pkg/exchange/bitget/bitgetapi/v2/testdata/get_k_line_request.json @@ -0,0 +1,27 @@ +{ + "code":"00000", + "msg":"success", + "requestTime":1709629803685, + "data":[ + [ + "1709352000000", + "62308.42", + "62308.43", + "61760", + "62014.17", + "987.377637", + "61283110.57046518", + "61283110.57046518" + ], + [ + "1709366400000", + "62014.17", + "62122.8", + "61648.26", + "61825.64", + "1271.183413", + "78680550.55539777", + "78680550.55539777" + ] + ] +} diff --git a/pkg/exchange/bitget/exchange_test.go b/pkg/exchange/bitget/exchange_test.go index b2087972bf..d5b2f5108b 100644 --- a/pkg/exchange/bitget/exchange_test.go +++ b/pkg/exchange/bitget/exchange_test.go @@ -5,7 +5,9 @@ import ( "math" "net/http" "os" + "strconv" "testing" + "time" "github.com/stretchr/testify/assert" @@ -233,3 +235,160 @@ func TestExchange_QueryTickers(t *testing.T) { assert.ErrorContains(err, "Invalid IP") }) } + +func TestExchange_QueryKLines(t *testing.T) { + var ( + assert = assert.New(t) + ex = New("key", "secret", "passphrase") + url = "/api/v2/spot/market/candles" + expBtcSymbol = "BTCUSDT" + interval = types.Interval4h + expBtcKlines = []types.KLine{ + { + Exchange: types.ExchangeBitget, + Symbol: expBtcSymbol, + StartTime: types.Time(types.NewMillisecondTimestampFromInt(1709352000000).Time()), + EndTime: types.Time(types.NewMillisecondTimestampFromInt(1709352000000).Time().Add(interval.Duration() - time.Millisecond)), + Interval: interval, + Open: fixedpoint.MustNewFromString("62308.42"), + Close: fixedpoint.MustNewFromString("62014.17"), + High: fixedpoint.MustNewFromString("62308.43"), + Low: fixedpoint.MustNewFromString("61760"), + Volume: fixedpoint.MustNewFromString("987.377637"), + QuoteVolume: fixedpoint.MustNewFromString("61283110.57046518"), + Closed: false, + }, + { + Exchange: types.ExchangeBitget, + Symbol: expBtcSymbol, + StartTime: types.Time(types.NewMillisecondTimestampFromInt(1709366400000).Time()), + EndTime: types.Time(types.NewMillisecondTimestampFromInt(1709366400000).Time().Add(interval.Duration() - time.Millisecond)), + Interval: interval, + Open: fixedpoint.MustNewFromString("62014.17"), + Close: fixedpoint.MustNewFromString("61825.64"), + High: fixedpoint.MustNewFromString("62122.8"), + Low: fixedpoint.MustNewFromString("61648.26"), + Volume: fixedpoint.MustNewFromString("1271.183413"), + QuoteVolume: fixedpoint.MustNewFromString("78680550.55539777"), + Closed: false, + }, + } + ) + + t.Run("succeeds without time range", func(t *testing.T) { + transport := &httptesting.MockTransport{} + ex.client.HttpClient.Transport = transport + + f, err := os.ReadFile("bitgetapi/v2/testdata/get_k_line_request.json") + assert.NoError(err) + + transport.GET(url, func(req *http.Request) (*http.Response, error) { + query := req.URL.Query() + assert.Len(query, 3) + assert.Contains(query, "symbol") + assert.Contains(query, "granularity") + assert.Contains(query, "limit") + assert.Equal(query["symbol"], []string{expBtcSymbol}) + assert.Equal(query["granularity"], []string{interval.String()}) + assert.Equal(query["limit"], []string{strconv.Itoa(defaultKLineLimit)}) + return httptesting.BuildResponseString(http.StatusOK, string(f)), nil + }) + + klines, err := ex.QueryKLines(context.Background(), expBtcSymbol, interval, types.KLineQueryOptions{}) + assert.NoError(err) + assert.Equal(expBtcKlines, klines) + }) + + t.Run("succeeds with time range", func(t *testing.T) { + var ( + transport = &httptesting.MockTransport{} + limit = 50 + startTime = time.Now() + endTime = startTime.Add(8 * time.Hour) + startTimeMs = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10) + endTimeMs = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10) + ) + + ex.client.HttpClient.Transport = transport + + f, err := os.ReadFile("bitgetapi/v2/testdata/get_k_line_request.json") + assert.NoError(err) + + transport.GET(url, func(req *http.Request) (*http.Response, error) { + query := req.URL.Query() + assert.Len(query, 5) + assert.Contains(query, "symbol") + assert.Contains(query, "granularity") + assert.Contains(query, "limit") + assert.Contains(query, "startTime") + assert.Contains(query, "endTime") + assert.Equal(query["symbol"], []string{expBtcSymbol}) + assert.Equal(query["granularity"], []string{interval.String()}) + assert.Equal(query["limit"], []string{strconv.Itoa(limit)}) + assert.Equal(query["startTime"], []string{startTimeMs}) + assert.Equal(query["endTime"], []string{endTimeMs}) + + return httptesting.BuildResponseString(http.StatusOK, string(f)), nil + }) + + klines, err := ex.QueryKLines(context.Background(), expBtcSymbol, interval, types.KLineQueryOptions{ + Limit: limit, + StartTime: &startTime, + EndTime: &endTime, + }) + assert.NoError(err) + assert.Equal(expBtcKlines, klines) + }) + + t.Run("error", func(t *testing.T) { + transport := &httptesting.MockTransport{} + ex.client.HttpClient.Transport = transport + + f, err := os.ReadFile("bitgetapi/v2/testdata/request_error.json") + assert.NoError(err) + + transport.GET(url, func(req *http.Request) (*http.Response, error) { + return httptesting.BuildResponseString(http.StatusBadRequest, string(f)), nil + }) + + _, err = ex.QueryKLines(context.Background(), expBtcSymbol, interval, types.KLineQueryOptions{}) + assert.ErrorContains(err, "Invalid IP") + }) + + t.Run("reach max duration", func(t *testing.T) { + transport := &httptesting.MockTransport{} + ex.client.HttpClient.Transport = transport + + transport.GET(url, func(req *http.Request) (*http.Response, error) { + return httptesting.BuildResponse(http.StatusBadRequest, nil), nil + }) + + before31Days := time.Now().Add(-31 * 24 * time.Hour) + _, err := ex.QueryKLines(context.Background(), expBtcSymbol, types.Interval1m, types.KLineQueryOptions{ + EndTime: &before31Days, + }) + assert.ErrorContains(err, "are greater than max duration") + }) + + t.Run("end time before start time", func(t *testing.T) { + transport := &httptesting.MockTransport{} + ex.client.HttpClient.Transport = transport + + transport.GET(url, func(req *http.Request) (*http.Response, error) { + return httptesting.BuildResponse(http.StatusBadRequest, nil), nil + }) + + startTime := time.Now() + endTime := startTime.Add(-time.Hour) + _, err := ex.QueryKLines(context.Background(), expBtcSymbol, types.Interval1m, types.KLineQueryOptions{ + StartTime: &startTime, + EndTime: &endTime, + }) + assert.ErrorContains(err, "before start time") + }) + + t.Run("unexpected duraiton", func(t *testing.T) { + _, err := ex.QueryKLines(context.Background(), expBtcSymbol, "87h", types.KLineQueryOptions{}) + assert.ErrorContains(err, "not supported") + }) +}