exchanges: Limit mock test JSON data size by truncating slices and maps (#1968)

* set limiter to first level mock data list and updated unit tests

* address nested slices length limit

* minor fix recording file and update unit tests

* minor updates on unit tests

* re-record mock files and minor fix on the unit tests ti adapt the mock data change

* improve http recording limit value and fix issues with mock data in binance

* added MockDataSliceLimit in request items and resolve minor unit test issues

* resolve missed conflict

* rename mock variables, resolve unit test issues, and other updates

* minor fix to CheckJSON and update unit tests

* minor unit test fix

* further optimization on mock CheckJSON method, unit tests, and re-record poloniex

* common and recording unit tests fix

* minor linter issues fix

* unit tests format fix

* fix miscellaneous error

* unit tests fix and minor docs update

* re-record and reduce mock file size

* indentation fix

* minor assertion test fix

* reverted log.Printf line in live testing

* rename variables

* update NewVCRServer unit test

* replace string comparison with *net.OpError check

* restructur net error test

* exchanges/mock: Remove redundant error assertion message in TestNewVCRServer

---------

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
Samuael A.
2025-08-26 03:27:07 +03:00
committed by GitHub
parent 370666cd21
commit fc0f262c42
47 changed files with 11143 additions and 503139 deletions

View File

@@ -21,8 +21,8 @@ const (
// SendHTTPRequest sends an unauthenticated HTTP request
func (e *Exchange) SendHTTPRequest(ctx context.Context, path string, result any) error {
// This is used to generate the *http.Request, used in conjunction with the
// generate functionality below.
// This is used to generate the *http.Request, used in conjunction with the
// generate functionality below.
item := &request.Item{
Method: http.MethodGet,
Path: path,

View File

@@ -281,7 +281,7 @@ func TestHandleReconnectResponse(t *testing.T) {
}
data, err := json.Marshal(testURL)
require.NoError(t, err, "json.Marshal must not error")
require.NoError(t, err, "Marshal must not error")
err = s.handleReconnectResponse(data)
require.NoError(t, err, "handleReconnectResponse must not error")

View File

@@ -252,12 +252,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, path string, result any)
// This is used to generate the *http.Request, used in conjunction with the
// generate functionality below.
item := &request.Item{
Method: http.MethodGet,
Path: path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
// Request function that closes over the above request.Item values, which
@@ -402,13 +403,14 @@ func (e *Exchange) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL,
headers["X-MBX-APIKEY"] = creds.Key
fullPath := common.EncodeURLValues(endpointPath+path, params) + "&signature=" + hex.EncodeToString(hmacSigned)
return &request.Item{
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -709,12 +709,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpointPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {
@@ -738,13 +739,14 @@ func (e *Exchange) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodGet,
Path: endpointPath + path,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + path,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {
@@ -783,13 +785,14 @@ func (e *Exchange) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL,
headers["X-MBX-APIKEY"] = creds.Key
fullPath := common.EncodeURLValues(endpointPath+path, params) + "&signature=" + hex.EncodeToString(hmacSigned)
return &request.Item{
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {
@@ -1061,13 +1064,14 @@ func (e *Exchange) GetWsAuthStreamKey(ctx context.Context) (string, error) {
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodPost,
Path: endpointPath + userAccountStream,
Headers: headers,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpointPath + userAccountStream,
Headers: headers,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
err = e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
@@ -1102,12 +1106,13 @@ func (e *Exchange) MaintainWsAuthStreamKey(ctx context.Context) error {
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodPut,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPut,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {

View File

@@ -40,12 +40,10 @@ func TestMain(m *testing.M) {
}
}
}
e.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
log.Printf(sharedtestvalues.LiveTesting, e.Name)
if err := e.UpdateTradablePairs(context.Background(), true); err != nil {
log.Fatalf("Binance UpdateTradablePairs error: %s", err)
}
os.Exit(m.Run())
}

View File

@@ -28,10 +28,8 @@ func TestMain(m *testing.M) {
if err := testexch.MockHTTPInstance(e); err != nil {
log.Fatalf("Binance MockHTTPInstance error: %s", err)
}
if err := e.UpdateTradablePairs(context.Background(), true); err != nil {
log.Fatalf("Binance UpdateTradablePairs error: %s", err)
}
os.Exit(m.Run())
}

View File

@@ -1091,7 +1091,7 @@ func TestGetExchangeInfo(t *testing.T) {
info, err := e.GetExchangeInfo(t.Context())
require.NoError(t, err, "GetExchangeInfo must not error")
if mockTests {
exp := time.Date(2024, 5, 10, 6, 8, 1, int(707*time.Millisecond), time.UTC)
exp := time.Date(2025, 8, 7, 21, 55, 41, int(167*time.Millisecond), time.UTC)
assert.Truef(t, info.ServerTime.Time().Equal(exp), "expected %v received %v", exp.UTC(), info.ServerTime.Time().UTC())
} else {
assert.WithinRange(t, info.ServerTime.Time(), time.Now().Add(-24*time.Hour), time.Now().Add(24*time.Hour), "ServerTime should be within a day of now")
@@ -2034,7 +2034,7 @@ func TestSubscribeBadResp(t *testing.T) {
func TestWsTickerUpdate(t *testing.T) {
t.Parallel()
pressXToJSON := []byte(`{"stream":"btcusdt@ticker","data":{"e":"24hrTicker","E":1580254809477,"s":"BTCUSDT","p":"420.97000000","P":"4.720","w":"9058.27981278","x":"8917.98000000","c":"9338.96000000","Q":"0.17246300","b":"9338.03000000","B":"0.18234600","a":"9339.70000000","A":"0.14097600","o":"8917.99000000","h":"9373.19000000","l":"8862.40000000","v":"72229.53692000","q":"654275356.16896672","O":1580168409456,"C":1580254809456,"F":235294268,"L":235894703,"n":600436}}`)
pressXToJSON := []byte(`{"stream":"btcusdt@ticker","data":{"e":"24hrTicker","E":1580254809477,"s":"ETHBTC","p":"420.97000000","P":"4.720","w":"9058.27981278","x":"8917.98000000","c":"9338.96000000","Q":"0.17246300","b":"9338.03000000","B":"0.18234600","a":"9339.70000000","A":"0.14097600","o":"8917.99000000","h":"9373.19000000","l":"8862.40000000","v":"72229.53692000","q":"654275356.16896672","O":1580168409456,"C":1580254809456,"F":235294268,"L":235894703,"n":600436}}`)
err := e.wsHandleData(pressXToJSON)
if err != nil {
t.Error(err)
@@ -2046,7 +2046,7 @@ func TestWsKlineUpdate(t *testing.T) {
pressXToJSON := []byte(`{"stream":"btcusdt@kline_1m","data":{
"e": "kline",
"E": 1234567891,
"s": "BTCUSDT",
"s": "ETHBTC",
"k": {
"t": 1234000001,
"T": 1234600001,
@@ -2079,7 +2079,7 @@ func TestWsTradeUpdate(t *testing.T) {
pressXToJSON := []byte(`{"stream":"btcusdt@trade","data":{
"e": "trade",
"E": 1234567891,
"s": "BTCUSDT",
"s": "ETHBTC",
"t": 12345,
"p": "0.001",
"q": "100",
@@ -2321,7 +2321,11 @@ func TestGetHistoricCandles(t *testing.T) {
}
startTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
_, err := e.GetHistoricCandles(t.Context(), currency.NewBTCUSDT(), asset.Spot, kline.Interval(time.Hour*7), startTime, end)
enabledPairs, err := e.GetEnabledPairs(asset.Spot)
require.NoError(t, err, "GetEnabledPairs must not error")
_, err = e.GetHistoricCandles(t.Context(), enabledPairs[0], asset.Spot, kline.Interval(time.Hour*7), startTime, end)
require.ErrorIs(t, err, kline.ErrRequestExceedsExchangeLimits)
}
@@ -2760,9 +2764,11 @@ func TestFetchExchangeLimits(t *testing.T) {
func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()
spotEnabled, err := e.GetEnabledPairs(asset.Spot)
require.NoError(t, err, "GetEnabledPairs must not error")
tests := map[asset.Item]currency.Pair{
asset.Spot: currency.NewBTCUSDT(),
asset.Spot: spotEnabled[0],
asset.Margin: currency.NewPair(currency.ETH, currency.BTC),
}
for _, a := range []asset.Item{asset.CoinMarginedFutures, asset.USDTMarginedFutures} {

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{"stream":"btcusdt@ticker","data":{"e":"24hrTicker","E":1580254809477,"s":"BTCUSDT","p":"420.97000000","P":"4.720","w":"9058.27981278","x":"8917.98000000","c":"9338.96000000","Q":"0.17246300","b":"9338.03000000","B":"0.18234600","a":"9339.70000000","A":"0.14097600","o":"8917.99000000","h":"9373.19000000","l":"8862.40000000","v":"72229.53692000","q":"654275356.16896672","O":1580168409456,"C":1580254809456,"F":235294268,"L":235894703,"n":600436}}
{"stream":"btcusdt@kline_1m","data":{"e": "kline","E": 123456789,"s": "BTCUSDT","k": {"t": 123400000,"T": 123460000,"s": "BTCUSDT","i": "1m","f": 100,"L": 200,"o": "0.0010","c": "0.0020","h": "0.0025","l": "0.0015","v": "1000","n": 100,"x": false,"q": "1.0000","V": "500","Q": "0.500","B": "123456"}}}
{"stream":"btcusdt@trade","data":{"e": "trade","E": 123456789,"s": "BTCUSDT","t": 12345,"p": "0.001","q": "100","b": 88,"a": 50,"T": 123456785,"m": true,"M": true}}
{"stream":"btcusdt@depth","data":{"e": "depthUpdate","E": 123456788,"s": "BTCUSDT","U": 157,"u": 160,"b": [["6621.45", "0.3"]],"a": [["6622.46", "1.5"]]}}
{"stream":"BNBBTC@ticker","data":{"e":"24hrTicker","E":1580254809477,"s":"BNBBTC","p":"420.97000000","P":"4.720","w":"9058.27981278","x":"8917.98000000","c":"9338.96000000","Q":"0.17246300","b":"9338.03000000","B":"0.18234600","a":"9339.70000000","A":"0.14097600","o":"8917.99000000","h":"9373.19000000","l":"8862.40000000","v":"72229.53692000","q":"654275356.16896672","O":1580168409456,"C":1580254809456,"F":235294268,"L":235894703,"n":600436}}
{"stream":"BNBBTC@kline_1m","data":{"e": "kline","E": 1234567880,"s": "BNBBTC","k": {"t": 1234000000,"T": 1234600000,"s": "BNBBTC","i": "1m","f": 100,"L": 200,"o": "0.0010","c": "0.0020","h": "0.0025","l": "0.0015","v": "1000","n": 100,"x": false,"q": "1.0000","V": "500","Q": "0.500","B": "123456"}}}
{"stream":"BNBBTC@trade","data":{"e": "trade","E": 1234567880,"s": "BNBBTC","t": 12345,"p": "0.001","q": "100","b": 88,"a": 50,"T": 123456785,"m": true,"M": true}}
{"stream":"BNBBTC@depth","data":{"e": "depthUpdate","E": 1234567880,"s": "BNBBTC","U": 157,"u": 160,"b": [["6621.45", "0.3"]],"a": [["6622.46", "1.5"]]}}
{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e": "balanceUpdate","E": 1573200697110,"a": "BTC","d": "100.00000000","T": 1573200697068}}
{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e": "listStatus","E": 1564035303637,"s": "ETHBTC","g": 2,"c": "OCO","l": "EXEC_STARTED","L": "EXECUTING","r": "NONE","C": "F4QN4G8DlFATFlIUQ0cjdD","T": 1564035303625,"O": [{"s": "ETHBTC","i": 17,"c": "AJYsMjErWJesZvqlJCTUgL"},{"s": "ETHBTC","i": 18,"c": "bfYPSQdLoqAJeNrOr9adzq"}]}}
{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e":"executionReport","E":1616627567900,"s":"BTCUSDT","c":"c4wyKsIhoAaittTYlIVLqk","S":"BUY","o":"LIMIT","f":"GTC","q":"0.00028400","p":"52789.10000000","P":"0.00000000","F":"0.00000000","g":-1,"C":"","x":"NEW","X":"NEW","r":"NONE","i":5340845958,"l":"0.00000000","z":"0.00000000","L":"0.00000000","n":"0","N":"BTC","T":1616627567900,"t":-1,"I":11388173160,"w":true,"m":false,"M":false,"O":1616627567900,"Z":"0.00000000","Y":"0.00000000","Q":"0.00000000","W":1616627567900}}
{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e":"executionReport","E":1616627567900,"s":"BNBBTC","c":"c4wyKsIhoAaittTYlIVLqk","S":"BUY","o":"LIMIT","f":"GTC","q":"0.00028400","p":"52789.10000000","P":"0.00000000","F":"0.00000000","g":-1,"C":"","x":"NEW","X":"NEW","r":"NONE","i":5340845958,"l":"0.00000000","z":"0.00000000","L":"0.00000000","n":"0","N":"BTC","T":1616627567900,"t":-1,"I":11388173160,"w":true,"m":false,"M":false,"O":1616627567900,"Z":"0.00000000","Y":"0.00000000","Q":"0.00000000","W":1616627567900}}
{"stream":"jTfvpakT2yT0hVIo5gYWVihZhdM2PrBgJUZ5PyfZ4EVpCkx4Uoxk5timcrQc","data":{"e":"outboundAccountPosition","E":1616628815745,"u":1616628815745,"B":[{"a":"BTC","f":"0.00225109","l":"0.00123000"},{"a":"BNB","f":"0.00000000","l":"0.00000000"},{"a":"USDT","f":"54.43390661","l":"0.00000000"}]}}

View File

@@ -1660,12 +1660,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpointPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {
return item, nil
@@ -1687,13 +1688,14 @@ func (e *Exchange) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodGet,
Path: endpointPath + path,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + path,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {
@@ -1728,13 +1730,14 @@ func (e *Exchange) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL,
headers["X-MBX-APIKEY"] = creds.Key
fullPath := common.EncodeURLValues(endpointPath+path, params) + "&signature=" + hex.EncodeToString(hmacSigned)
return &request.Item{
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: fullPath,
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {
@@ -1775,13 +1778,14 @@ func (e *Exchange) GetWsAuthStreamKey(ctx context.Context) (string, error) {
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodPost,
Path: endpointPath + userAccountStream,
Headers: headers,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpointPath + userAccountStream,
Headers: headers,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
err = e.SendPayload(ctx, spotDefaultRate, func() (*request.Item, error) {
@@ -1820,12 +1824,13 @@ func (e *Exchange) MaintainWsAuthStreamKey(ctx context.Context) error {
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodPut,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPut,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, spotDefaultRate, func() (*request.Item, error) {
@@ -1856,12 +1861,13 @@ func (e *Exchange) CloseUserDataStream(ctx context.Context) error {
headers := make(map[string]string)
headers["X-MBX-APIKEY"] = creds.Key
item := &request.Item{
Method: http.MethodDelete,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodDelete,
Path: path,
Headers: headers,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, spotDefaultRate, func() (*request.Item, error) {

View File

@@ -1862,12 +1862,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, epl, func() (*request.Item, error) {
@@ -1913,14 +1914,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["X-BFX-SIGNATURE"] = hex.EncodeToString(hmac)
return &request.Item{
Method: method,
Path: fullPath,
Headers: headers,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: fullPath,
Headers: headers,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}
@@ -1962,15 +1964,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchan
headers["bfx-signature"] = hex.EncodeToString(hmac)
return &request.Item{
Method: method,
Path: ePoint + bitfinexAPIVersion2 + path,
Headers: headers,
Body: body,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: ePoint + bitfinexAPIVersion2 + path,
Headers: headers,
Body: body,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}

View File

@@ -268,12 +268,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
return item, nil

View File

@@ -533,12 +533,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
return item, nil
@@ -581,15 +582,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["Content-Type"] = "application/x-www-form-urlencoded"
return &request.Item{
Method: http.MethodPost,
Path: endpoint + path,
Headers: headers,
Body: bytes.NewBufferString(payload),
Result: &intermediary,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpoint + path,
Headers: headers,
Body: bytes.NewBufferString(payload),
Result: &intermediary,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -838,12 +838,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: path,
Result: &respCheck,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: path,
Result: &respCheck,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
err = e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
@@ -896,14 +897,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["api-signature"] = hex.EncodeToString(hmac)
return &request.Item{
Method: verb,
Path: endpoint + path,
Headers: headers,
Body: strings.NewReader(payload),
Result: &respCheck,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: verb,
Path: endpoint + path,
Headers: headers,
Body: strings.NewReader(payload),
Result: &respCheck,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}
err = e.SendPayload(ctx, request.Auth, newRequest, request.AuthenticatedRequest)

View File

@@ -488,12 +488,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
return item, nil
@@ -543,15 +544,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
readerValues := bytes.NewBufferString(encodedValues)
return &request.Item{
Method: http.MethodPost,
Path: fullPath,
Headers: headers,
Body: readerValues,
Result: &interim,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: fullPath,
Headers: headers,
Body: readerValues,
Result: &interim,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -24,6 +24,6 @@ func TestMain(m *testing.M) {
e.API.AuthenticatedSupport = true
e.SetCredentials(apiKey, apiSecret, customerID, "", "", "")
}
log.Printf(sharedtestvalues.LiveTesting, b.Name)
log.Printf(sharedtestvalues.LiveTesting, e.Name)
os.Exit(m.Run())
}

View File

@@ -771,12 +771,13 @@ func (e *Exchange) CancelBatch(ctx context.Context, ids []string) (BatchCancelRe
// SendHTTPRequest sends an unauthenticated HTTP request
func (e *Exchange) SendHTTPRequest(ctx context.Context, path string, result any) error {
item := &request.Item{
Method: http.MethodGet,
Path: path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
return item, nil
@@ -827,14 +828,15 @@ func (e *Exchange) SendAuthenticatedRequest(ctx context.Context, method, path st
headers["BM-AUTH-SIGNATURE"] = base64.StdEncoding.EncodeToString(hmac)
return &request.Item{
Method: method,
Path: btcMarketsAPIURL + btcMarketsAPIVersion + path,
Headers: headers,
Body: body,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: btcMarketsAPIURL + btcMarketsAPIVersion + path,
Headers: headers,
Body: body,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}

View File

@@ -441,12 +441,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, method,
p = btseFuturesPath + btseFuturesAPIPath
}
item := &request.Item{
Method: method,
Path: ePoint + p + endpoint,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: ePoint + p + endpoint,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {
return item, nil
@@ -518,14 +519,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["btse-sign"] = hex.EncodeToString(hmac)
return &request.Item{
Method: method,
Path: host,
Headers: headers,
Body: body,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: host,
Headers: headers,
Body: body,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}
return e.SendPayload(ctx, f, newRequest, request.AuthenticatedRequest)

View File

@@ -2513,12 +2513,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ePath exchange.URL, path
}
err = e.SendPayload(ctx, f, func() (*request.Item, error) {
return &request.Item{
Method: http.MethodGet,
Path: endpointPath + bybitAPIVersion + path,
Result: response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + bybitAPIVersion + path,
Result: response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.UnauthenticatedRequest)
if err != nil {
@@ -2576,14 +2577,15 @@ func (e *Exchange) SendAuthHTTPRequestV5(ctx context.Context, ePath exchange.URL
}
headers["X-BAPI-SIGN"] = hmacSignedStr
return &request.Item{
Method: method,
Path: endpointPath + common.EncodeURLValues(path, params),
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpointPath + common.EncodeURLValues(path, params),
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if response.RetCode != 0 && response.RetMsg != "" {

View File

@@ -665,12 +665,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
@@ -714,14 +715,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["Content-Type"] = "application/json"
return &request.Item{
Method: method,
Path: endpoint + path,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpoint + path,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}
return e.SendPayload(ctx, request.Unset, newRequest, request.AuthenticatedRequest)

View File

@@ -295,15 +295,16 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, apiRequ
headers["Content-Type"] = "application/json"
return &request.Item{
Method: http.MethodPost,
Path: endpoint,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &rawMsg,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpoint,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &rawMsg,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, requestType)
if err != nil {

View File

@@ -711,12 +711,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl req
}
return e.SendPayload(ctx, epl, func() (*request.Item, error) {
return &request.Item{
Method: http.MethodGet,
Path: endpoint + deribitAPIVersion + "/" + path,
Result: data,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + deribitAPIVersion + "/" + path,
Result: data,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.UnauthenticatedRequest)
}
@@ -2232,13 +2233,14 @@ func (e *Exchange) SendHTTPAuthRequest(ctx context.Context, ep exchange.URL, epl
}
err = e.SendPayload(ctx, epl, func() (*request.Item, error) {
return &request.Item{
Method: method,
Path: endpoint + deribitAPIVersion + "/" + common.EncodeURLValues(path, params),
Headers: headers,
Result: &tempData,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpoint + deribitAPIVersion + "/" + common.EncodeURLValues(path, params),
Headers: headers,
Result: &tempData,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -241,6 +241,7 @@ type Base struct {
Features Features
HTTPTimeout time.Duration
HTTPRecording bool
HTTPMockDataSliceLimit int // Use with HTTPRecording to reduce the size of recorded mock data
HTTPDebugging bool
BypassConfigFormatUpgrades bool
WebsocketResponseCheckTimeout time.Duration

View File

@@ -293,12 +293,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, p
}
item := &request.Item{
Method: http.MethodGet,
Path: urlPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: urlPath + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
return item, nil
@@ -335,15 +336,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, epath excha
headers["Content-Type"] = "application/x-www-form-urlencoded"
return &request.Item{
Method: method,
Path: path,
Headers: headers,
Body: strings.NewReader(payload),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: path,
Headers: headers,
Body: strings.NewReader(payload),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}

View File

@@ -944,14 +944,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
payload = string(byteData)
}
return &request.Item{
Method: method,
Path: urlPath,
Headers: headers,
Body: strings.NewReader(payload),
Result: &intermediary,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: urlPath,
Headers: headers,
Body: strings.NewReader(payload),
Result: &intermediary,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {
@@ -982,12 +983,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, epl req
return err
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, epl, func() (*request.Item, error) {
return item, nil

View File

@@ -397,12 +397,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
@@ -450,14 +451,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["Cache-Control"] = "no-cache"
return &request.Item{
Method: method,
Path: endpoint + "/v1/" + path,
Headers: headers,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpoint + "/v1/" + path,
Headers: headers,
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}

View File

@@ -425,12 +425,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, marketRequests, func() (*request.Item, error) {
@@ -452,13 +453,14 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte(creds.Key+":"+creds.Secret))
item := &request.Item{
Method: method,
Path: ePoint + "/" + endpoint,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: ePoint + "/" + endpoint,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, f, func() (*request.Item, error) {

View File

@@ -883,12 +883,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
var tempResp json.RawMessage
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: &tempResp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: &tempResp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
err = e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
@@ -967,14 +968,15 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
}
return &request.Item{
Method: method,
Path: ePoint + common.EncodeURLValues(endpoint, values),
Headers: headers,
Body: bytes.NewReader(body),
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: ePoint + common.EncodeURLValues(endpoint, values),
Headers: headers,
Body: bytes.NewReader(body),
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}

View File

@@ -1185,14 +1185,15 @@ func (e *Exchange) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep excha
}
return &request.Item{
Method: method,
Path: common.EncodeURLValues(ePoint+endpoint, values),
Headers: headers,
Body: body,
Result: &tempResp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: common.EncodeURLValues(ePoint+endpoint, values),
Headers: headers,
Body: body,
Result: &tempResp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}

View File

@@ -728,12 +728,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
var rawMessage json.RawMessage
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: &rawMessage,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: &rawMessage,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
err = e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
@@ -796,15 +797,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["API-Sign"] = base64.StdEncoding.EncodeToString(hmac)
return &request.Item{
Method: http.MethodPost,
Path: endpoint + path,
Headers: headers,
Body: strings.NewReader(encoded),
Result: &interim,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpoint + path,
Headers: headers,
Body: strings.NewReader(encoded),
Result: &interim,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -365,13 +365,14 @@ func (e *Exchange) SendFuturesAuthRequest(ctx context.Context, method, path stri
}
return &request.Item{
Method: method,
Path: futuresURL + common.EncodeURLValues(path, data),
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: futuresURL + common.EncodeURLValues(path, data),
Headers: headers,
Result: &interim,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}

View File

@@ -2438,12 +2438,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ePath exchange.URL, epl
}
err = e.SendPayload(ctx, epl, func() (*request.Item, error) {
return &request.Item{
Method: http.MethodGet,
Path: endpointPath + path,
Result: resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpointPath + path,
Result: resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.UnauthenticatedRequest)
if err != nil {
@@ -2507,14 +2508,15 @@ func (e *Exchange) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL,
"Content-Type": "application/json",
}
return &request.Item{
Method: method,
Path: endpointPath + path,
Headers: headers,
Body: body,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpointPath + path,
Headers: headers,
Body: body,
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
if err != nil {

View File

@@ -178,12 +178,13 @@ func (e *Exchange) GetInstanceServers(ctx context.Context) (*WSInstanceServers,
return nil, err
}
return &request.Item{
Method: http.MethodPost,
Path: endpointPath + publicBullets,
Result: &response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpointPath + publicBullets,
Result: &response,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.UnauthenticatedRequest)
}

View File

@@ -490,12 +490,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
@@ -568,13 +569,14 @@ func (e *Exchange) SendAuthHTTPRequest(ctx context.Context, method, endpoint str
headers["Content-Type"] = "application/x-www-form-urlencoded"
item := &request.Item{
Method: method,
Path: endpoint,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: endpoint,
Headers: headers,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {

View File

@@ -4,10 +4,13 @@ import (
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/encoding/json"
)
func TestMatchURLVals(t *testing.T) {
t.Parallel()
testVal, testVal2, testVal3, emptyVal := url.Values{}, url.Values{}, url.Values{}, url.Values{}
testVal.Add("test", "test")
testVal2.Add("test2", "test2")
@@ -17,87 +20,39 @@ func TestMatchURLVals(t *testing.T) {
nonceVal1.Add("nonce", "012349723587")
nonceVal2.Add("nonce", "9327373874")
expected := false
received := MatchURLVals(testVal, emptyVal)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
tests := []struct {
a url.Values
b url.Values
exp bool
}{
{testVal, emptyVal, false},
{emptyVal, testVal, false},
{testVal, testVal2, false},
{testVal2, testVal, false},
{testVal, testVal3, false},
{nonceVal1, testVal2, false},
{emptyVal, emptyVal, true},
{testVal, testVal, true},
{nonceVal1, nonceVal2, true},
}
received = MatchURLVals(emptyVal, testVal)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(testVal, testVal2)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(testVal2, testVal)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(testVal, testVal3)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(nonceVal1, testVal2)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
expected = true
received = MatchURLVals(emptyVal, emptyVal)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(testVal, testVal)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
}
received = MatchURLVals(nonceVal1, nonceVal2)
if received != expected {
t.Errorf("MatchURLVals error expected %v received %v",
expected,
received)
for _, tc := range tests {
got := MatchURLVals(tc.a, tc.b)
assert.Equalf(t, tc.exp, got, "MatchURLVals should return correctly for (%q, %q)", tc.a, tc.b)
}
}
func TestDeriveURLValsFromJSON(t *testing.T) {
type class struct {
Numbers []int `json:"numbers"`
Number float64 `json:"number"`
SomeString string `json:"somestring"`
}
test1 := struct {
Things []string `json:"things"`
Data struct {
Numbers []int `json:"numbers"`
Number float64 `json:"number"`
SomeString string `json:"somestring"`
} `json:"data"`
Data class `json:"data"`
}{
Things: []string{"hello", "world"},
Data: struct {
Numbers []int `json:"numbers"`
Number float64 `json:"number"`
SomeString string `json:"somestring"`
}{
Data: class{
Numbers: []int{1, 3, 3, 7},
Number: 3.14,
SomeString: "hello, peoples",
@@ -105,14 +60,11 @@ func TestDeriveURLValsFromJSON(t *testing.T) {
}
payload, err := json.Marshal(test1)
if err != nil {
t.Error("marshal error", err)
}
require.NoError(t, err, "Marshal must not error")
_, err = DeriveURLValsFromJSONMap(payload)
if err != nil {
t.Error("DeriveURLValsFromJSON error", err)
}
values, err := DeriveURLValsFromJSONMap(payload)
assert.NoError(t, err, "DeriveURLValsFromJSONMap should not error")
assert.Len(t, values, 2)
test2 := map[string]string{
"val": "1",
@@ -125,17 +77,13 @@ func TestDeriveURLValsFromJSON(t *testing.T) {
}
payload, err = json.Marshal(test2)
if err != nil {
t.Error("marshal error", err)
}
require.NoError(t, err, "Marshal must not error")
vals, err := DeriveURLValsFromJSONMap(payload)
if err != nil {
t.Error("DeriveURLValsFromJSON error", err)
}
if vals["val"][0] != "1" {
t.Error("DeriveURLValsFromJSON unexpected value",
vals["val"][0])
values, err = DeriveURLValsFromJSONMap(payload)
require.NoError(t, err, "DeriveURLValsFromJSONMap must not error")
require.Equal(t, 7, len(values), "DeriveURLValsFromJSONMap must return the correct number of values")
for key, val := range values {
require.Len(t, val, 1)
assert.Equalf(t, test2[key], val[0], "DeriveURLValsFromJSON should return the correct value for %s", key)
}
}

View File

@@ -19,6 +19,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/encoding/json"
)
// defaultDataSliceLimit the mock slice data size limit to a default of 5
const defaultDataSliceLimit = 5
// HTTPResponse defines expected response from the end point including request
// data for pathing on the VCR server
type HTTPResponse struct {
@@ -30,7 +33,8 @@ type HTTPResponse struct {
// HTTPRecord will record the request and response to a default JSON file for
// mocking purposes
func HTTPRecord(res *http.Response, service string, respContents []byte) error {
// mockDataSliceLimit defaults to 5
func HTTPRecord(res *http.Response, service string, respContents []byte, mockDataSliceLimit int) error {
if res == nil {
return errors.New("http.Response cannot be nil")
}
@@ -47,7 +51,9 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
return errors.New("service not supplied cannot access correct mock file")
}
service = strings.ToLower(service)
if mockDataSliceLimit == 0 {
mockDataSliceLimit = defaultDataSliceLimit
}
outputFilePath := filepath.Join(DefaultDirectory, service, service+".json")
_, err := os.Stat(outputFilePath)
if err != nil {
@@ -77,8 +83,13 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
m.Routes = make(map[string]map[string][]HTTPResponse)
}
items, err := getExcludedItems()
if err != nil {
return err
}
var httpResponse HTTPResponse
cleanedContents, err := CheckResponsePayload(respContents)
cleanedContents, err := CheckResponsePayload(respContents, items, mockDataSliceLimit)
if err != nil {
return err
}
@@ -108,11 +119,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
return urlErr
}
httpResponse.BodyParams, urlErr = GetFilteredURLVals(vals)
if urlErr != nil {
return urlErr
}
httpResponse.BodyParams = GetFilteredURLVals(vals, items)
case textPlain:
payload := res.Request.Header.Get("X-Gemini-Payload")
j, dErr := base64.StdEncoding.DecodeString(payload)
@@ -126,15 +133,8 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
httpResponse.BodyParams = body
}
httpResponse.Headers, err = GetFilteredHeader(res)
if err != nil {
return err
}
httpResponse.QueryString, err = GetFilteredURLVals(res.Request.URL.Query())
if err != nil {
return err
}
httpResponse.Headers = GetFilteredHeader(res, items)
httpResponse.QueryString = GetFilteredURLVals(res.Request.URL.Query(), items)
_, ok := m.Routes[res.Request.URL.Path]
if !ok {
@@ -245,54 +245,37 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
// GetFilteredHeader filters excluded http headers for insertion into a mock
// test file
func GetFilteredHeader(res *http.Response) (http.Header, error) {
items, err := GetExcludedItems()
if err != nil {
return res.Header, err
}
func GetFilteredHeader(res *http.Response, items Exclusion) http.Header {
for i := range items.Headers {
if res.Request.Header.Get(items.Headers[i]) != "" {
res.Request.Header.Set(items.Headers[i], "")
}
}
return res.Request.Header, nil
return res.Request.Header
}
// GetFilteredURLVals filters excluded url value variables for insertion into a
// mock test file
func GetFilteredURLVals(vals url.Values) (string, error) {
items, err := GetExcludedItems()
if err != nil {
return "", err
}
for key, val := range vals {
func GetFilteredURLVals(vals url.Values, items Exclusion) string {
for key := range vals {
for i := range items.Variables {
if strings.EqualFold(items.Variables[i], val[0]) {
if strings.EqualFold(items.Variables[i], key) {
vals.Set(key, "")
}
}
}
return vals.Encode(), nil
return vals.Encode()
}
// CheckResponsePayload checks to see if there are any response body variables
// that should not be there.
func CheckResponsePayload(data []byte) ([]byte, error) {
items, err := GetExcludedItems()
if err != nil {
return nil, err
}
func CheckResponsePayload(data []byte, items Exclusion, mockDataSliceLimit int) ([]byte, error) {
var intermediary any
err = json.Unmarshal(data, &intermediary)
if err != nil {
if err := json.Unmarshal(data, &intermediary); err != nil {
return nil, err
}
payload, err := CheckJSON(intermediary, &items)
payload, err := CheckJSON(intermediary, &items, mockDataSliceLimit)
if err != nil {
return nil, err
}
@@ -302,7 +285,6 @@ func CheckResponsePayload(data []byte) ([]byte, error) {
// Reflection consts
const (
Int64 = "int64"
Float64 = "float64"
Slice = "slice"
String = "string"
@@ -311,22 +293,23 @@ const (
)
// CheckJSON recursively parses json data to retract keywords, quite intensive.
func CheckJSON(data any, excluded *Exclusion) (any, error) {
if d, ok := data.([]any); ok {
func CheckJSON(data any, excluded *Exclusion, limit int) (any, error) {
if value, ok := data.([]any); ok {
var sData []any
for i := range d {
v := d[i]
switch v.(type) {
case map[string]any, []any:
checkedData, err := CheckJSON(v, excluded)
for i := range value {
switch subvalue := value[i].(type) {
case []any, map[string]any:
checkedData, err := CheckJSON(subvalue, excluded, limit)
if err != nil {
return nil, err
}
sData = append(sData, checkedData)
if limit > 0 && len(sData) >= limit {
return sData, nil
}
default:
// Primitive value doesn't need exclusions applied, e.g. float64 or string
sData = append(sData, v)
sData = append(sData, subvalue)
}
}
return sData, nil
@@ -337,67 +320,55 @@ func CheckJSON(data any, excluded *Exclusion) (any, error) {
return nil, err
}
var context map[string]any
err = json.Unmarshal(conv, &context)
var contextValue map[string]any
err = json.Unmarshal(conv, &contextValue)
if err != nil {
return nil, err
}
if len(context) == 0 {
if len(contextValue) == 0 {
// Nil for some reason, should error out before in json.Unmarshal
return nil, nil
return contextValue, nil
}
for key, val := range context {
for key, val := range contextValue {
switch reflect.ValueOf(val).Kind().String() {
case String:
if IsExcluded(key, excluded.Variables) {
context[key] = "" // Zero val string
}
case Int64:
if IsExcluded(key, excluded.Variables) {
context[key] = 0 // Zero val int
contextValue[key] = "" // Zero val string
}
case Float64:
if IsExcluded(key, excluded.Variables) {
context[key] = 0.0 // Zero val float
contextValue[key] = 0.0 // Zero val float
}
case Slice:
slice, ok := val.([]any)
if !ok {
return nil, common.GetTypeAssertError("[]any", val)
}
if len(slice) < 1 {
switch {
case len(slice) == 0:
// Empty slice found
context[key] = slice
} else {
if _, ok := slice[0].(map[string]any); ok {
var cleanSlice []any
for i := range slice {
cleanMap, sErr := CheckJSON(slice[i], excluded)
if sErr != nil {
return nil, sErr
}
cleanSlice = append(cleanSlice, cleanMap)
}
context[key] = cleanSlice
} else if IsExcluded(key, excluded.Variables) {
context[key] = nil // Zero val slice
contextValue[key] = slice
case IsExcluded(key, excluded.Variables):
contextValue[key] = nil // Zero val slice
default:
contextValue[key], err = CheckJSON(slice, excluded, limit)
if err != nil {
return nil, err
}
}
case Bool, Invalid: // Skip these bad boys for now
default:
// Recursively check map data
contextValue, err := CheckJSON(val, excluded)
contextValue[key], err = CheckJSON(val, excluded, limit)
if err != nil {
return nil, err
}
context[key] = contextValue
}
}
return context, nil
return contextValue, nil
}
// IsExcluded cross references the key with the excluded variables
@@ -443,9 +414,9 @@ type Exclusion struct {
Variables []string `json:"variables"`
}
// GetExcludedItems checks to see if the variable is in the exclusion list as to
// getExcludedItems checks to see if the variable is in the exclusion list as to
// not display secure items in mock file generator output
func GetExcludedItems() (Exclusion, error) {
func getExcludedItems() (Exclusion, error) {
m.Lock()
defer m.Unlock()
if !set {

View File

@@ -3,39 +3,38 @@ package mock
import (
"net/http"
"net/url"
"strings"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/encoding/json"
)
func TestGetFilteredHeader(t *testing.T) {
items, err := getExcludedItems()
require.NoError(t, err, "getExcludedItems must not error")
assert.NotNil(t, items, "getExcludedItems should not return nil")
resp := http.Response{}
resp.Request = &http.Request{}
resp.Request.Header = http.Header{}
resp.Request.Header.Set("Key", "RiskyVals")
fMap, err := GetFilteredHeader(&resp)
if err != nil {
t.Error(err)
}
if fMap.Get("Key") != "" {
t.Error("risky vals where not replaced correctly")
}
fMap := GetFilteredHeader(&resp, items)
assert.Empty(t, fMap.Get("Key"), "risky values should be removed")
}
func TestGetFilteredURLVals(t *testing.T) {
items, err := getExcludedItems()
require.NoError(t, err, "getExcludedItems must not error")
assert.NotNil(t, items, "getExcludedItems should not return nil")
superSecretData := "Dr Seuss"
shadyVals := url.Values{}
shadyVals.Set("real_name", superSecretData)
cleanVals, err := GetFilteredURLVals(shadyVals)
if err != nil {
t.Error("GetFilteredURLVals error", err)
}
if strings.Contains(cleanVals, superSecretData) {
t.Error("Super secret data found")
}
cleanVals := GetFilteredURLVals(shadyVals, items)
assert.NotContains(t, cleanVals, superSecretData, "exclusion real_name should be removed")
}
func TestCheckResponsePayload(t *testing.T) {
@@ -46,22 +45,26 @@ func TestCheckResponsePayload(t *testing.T) {
}
payload, err := json.Marshal(testbody)
if err != nil {
t.Fatal("json marshal error", err)
}
require.NoError(t, err, "json marshal must not error")
data, err := CheckResponsePayload(payload)
if err != nil {
t.Error("CheckBody error", err)
}
items, err := getExcludedItems()
require.NoError(t, err, "getExcludedItems must not error")
assert.NotNil(t, items, "getExcludedItems should not return nil")
data, err := CheckResponsePayload(payload, items, 5)
assert.NoError(t, err, "CheckResponsePayload should not error")
expected := `{
"stuff": "REAAAAHHHHH"
}`
assert.Equal(t, expected, string(data))
}
if string(data) != expected {
t.Error("unexpected returned data")
}
func TestGetExcludedItems(t *testing.T) {
exclusionList, err := getExcludedItems()
require.NoError(t, err, "getExcludedItems must not error")
assert.NotEmpty(t, exclusionList.Headers, "Headers should not be empty")
assert.NotEmpty(t, exclusionList.Variables, "Variables should not be empty")
}
type TestStructLevel0 struct {
@@ -81,130 +84,123 @@ type TestStructLevel1 struct {
}
type TestStructLevel2 struct {
OkayVal string `json:"okayVal"`
OkayVal2 float64 `json:"okayVal2"`
BadVal float32 `json:"name"`
BadVal2 int32 `json:"real_name"`
OtherData TestStructLevel3 `json:"moreOtherVals"`
OkayVal string `json:"okayVal"`
OkayVal2 float64 `json:"okayVal2"`
OkayVal3 map[string]any `json:"okayVal3"`
OkayVal4 map[string]any `json:"okayVal4"`
OkayVal5 []any `json:"okayVal5"`
BadVal int64 `json:"receiver_name"`
BadVal2 string `json:"account_number"`
BadVal3 []any `json:"secret"`
}
type TestStructLevel3 struct {
OkayVal string `json:"okayVal"`
OkayVal2 float64 `json:"okayVal2"`
BadVal int64 `json:"receiver_name"`
BadVal2 string `json:"account_number"`
var testVal = []TestStructLevel0{
{
StringVal: "somestringstuff",
FloatVal: 3.14,
IntVal: 1337,
StructVal: TestStructLevel1{
OkayVal: "stuff",
OkayVal2: 120938,
BadVal: "CritcalBankingStuff",
BadVal2: 1337,
OtherData: TestStructLevel2{
OkayVal: "stuff",
OkayVal2: 129219809899009009080980,
OkayVal3: map[string]any{"a": 1},
OkayVal4: map[string]any{},
OkayVal5: []any{},
BadVal: 1337,
BadVal2: "Super Secret Password",
BadVal3: []any{123, 'a'},
},
},
MixedSlice: []any{
[]map[string]any{{"id": 0}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {}},
[]any{float64(1586994000000), "6615.23000000", 'a', 1234, false, int64(17866372632), 0},
"abcd",
},
},
{
StringVal: "somestringstuff",
FloatVal: 3.14,
},
{
StringVal: "somestringstuff",
FloatVal: 3.14,
IntVal: 1337,
},
{
StringVal: "somestringstuff",
IntVal: 1337,
},
{},
{},
{},
}
func TestCheckJSON(t *testing.T) {
level3 := TestStructLevel3{
OkayVal: "stuff",
OkayVal2: 129219,
BadVal: 1337,
BadVal2: "Super Secret Password",
}
exclusionList, err := getExcludedItems()
require.NoError(t, err, "getExcludedItems must not error")
assert.NotNil(t, exclusionList, "getExcludedItems should not return nil")
level2 := TestStructLevel2{
OkayVal: "stuff",
OkayVal2: 129219,
BadVal: 0.222,
BadVal2: 1337888888,
OtherData: level3,
}
data, err := json.Marshal(testVal)
require.NoError(t, err, "Marshal must not error")
require.NotNil(t, data, "Marshal must not return nil")
level1 := TestStructLevel1{
OkayVal: "stuff",
OkayVal2: 120938,
BadVal: "CritcalBankingStuff",
BadVal2: 1337,
OtherData: level2,
}
var input any
err = json.Unmarshal(data, &input)
require.NoError(t, err, "Unmarshal must not error")
sliceOfPrimitives := []any{
[]any{float64(1586994000000), "6615.23000000"},
[]any{float64(1586994300000), "6624.74000000"},
}
testVal := TestStructLevel0{
StringVal: "somestringstuff",
FloatVal: 3.14,
IntVal: 1337,
StructVal: level1,
MixedSlice: sliceOfPrimitives,
}
exclusionList, err := GetExcludedItems()
if err != nil {
t.Error("GetExcludedItems error", err)
}
vals, err := CheckJSON(testVal, &exclusionList)
if err != nil {
t.Error("Check JSON error", err)
}
vals, err := CheckJSON(input, &exclusionList, 4)
assert.NoError(t, err, "CheckJSON should not error")
payload, err := json.Marshal(vals)
if err != nil {
t.Fatal("json marshal error", err)
}
require.NoError(t, err, "Marshal must not error")
newStruct := TestStructLevel0{}
newStruct := []TestStructLevel0{}
err = json.Unmarshal(payload, &newStruct)
if err != nil {
t.Fatal("Umarshal error", err)
}
require.NoError(t, err, "Umarshal must not error")
if newStruct.StructVal.BadVal != "" {
t.Error("Value not wiped correctly")
}
if newStruct.StructVal.BadVal2 != 0 {
t.Error("Value not wiped correctly")
}
if newStruct.StructVal.OtherData.BadVal != 0 {
t.Error("Value not wiped correctly")
}
if newStruct.StructVal.OtherData.BadVal2 != 0 {
t.Error("Value not wiped correctly")
}
if newStruct.StructVal.OtherData.OtherData.BadVal != 0 {
t.Error("Value not wiped correctly")
}
if newStruct.StructVal.OtherData.OtherData.BadVal2 != "" {
t.Error("Value not wiped correctly")
}
vals, err = CheckJSON(sliceOfPrimitives, &exclusionList)
if err != nil {
t.Error("Check JSON error", err)
}
payload, err = json.Marshal(vals)
if err != nil {
t.Fatal("json marshal error", err)
}
var newSlice []any
err = json.Unmarshal(payload, &newSlice)
if err != nil {
t.Fatal("Unmarshal error", err)
}
assert.Len(t, newStruct, 4)
assert.Empty(t, newStruct[0].StructVal.BadVal, "Value not wiped correctly")
assert.Empty(t, newStruct[0].StructVal.BadVal2, "Value not wiped correctly")
assert.Empty(t, newStruct[0].StructVal.OtherData.BadVal, "BadVal should be removed")
assert.Empty(t, newStruct[0].StructVal.OtherData.BadVal2, "BadVal2 should be removed")
assert.Len(t, newStruct[0].MixedSlice[0], 4)
assert.Len(t, newStruct[0].MixedSlice[1], 7)
}
func TestGetExcludedItems(t *testing.T) {
exclusionList, err := GetExcludedItems()
if err != nil {
t.Error("GetExcludedItems error", err)
}
func TestHTTPRecord(t *testing.T) {
t.Parallel()
if len(exclusionList.Headers) == 0 {
t.Error("Header exclusion list not popoulated")
}
service := "mock"
outputDirPath := filepath.Join("..", service, "testdata")
err := os.Mkdir(outputDirPath, 0o755)
require.NoError(t, err)
if len(exclusionList.Variables) == 0 {
t.Error("Variable exclusion list not popoulated")
filePath := filepath.Join(outputDirPath, "http.json")
err = os.WriteFile(filePath, []byte(`{"routes": null}`), 0o644)
require.NoError(t, err)
_, err = os.Stat(filePath)
require.NoError(t, err, "file not created properly")
defer func() {
require.NoErrorf(t, os.Remove(filePath), "Remove test exclusion file %q must not error", filePath)
require.NoErrorf(t, os.Remove(outputDirPath), "Remove test exclusion dir %q must not error", outputDirPath)
}()
content, err := json.Marshal(testVal)
require.NoError(t, err, "Marshal must not error")
require.NotNil(t, content, "Marshal must not return nil")
response := &http.Response{
Request: &http.Request{
Method: http.MethodGet,
URL: &url.URL{},
},
}
err = HTTPRecord(response, "mock", content, 4)
require.NoError(t, err, "HTTPRecord must not error")
}

View File

@@ -29,6 +29,11 @@ const (
textPlain = "text/plain"
)
// error declarations
var (
errJSONMockFilePathRequired = errors.New("no path to json mock file found")
)
// VCRMock defines the main mock JSON file and attributes
type VCRMock struct {
Routes map[string]map[string][]HTTPResponse `json:"routes"`
@@ -38,7 +43,7 @@ type VCRMock struct {
// purposes and returns the server connection details
func NewVCRServer(path string) (string, *http.Client, error) {
if path == "" {
return "", nil, errors.New("no path to json mock file found")
return "", nil, errJSONMockFilePathRequired
}
var mockFile VCRMock
@@ -162,7 +167,7 @@ func RegisterHandler(pattern string, mock map[string][]HTTPResponse, mux *http.S
reqVals, err := DeriveURLValsFromJSONMap(readBody)
if err != nil {
log.Fatalf("Mock Test Failure - %v", err)
log.Fatalf("DeriveURLValsFromJSONMap Mock Test Failure - %v", err)
}
payload, err := MatchAndGetResponse(httpResponses, reqVals, false)

View File

@@ -2,11 +2,13 @@ package mock
import (
"bytes"
"net"
"net/http"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/encoding/json"
)
@@ -24,9 +26,7 @@ const (
func TestNewVCRServer(t *testing.T) {
_, _, err := NewVCRServer("")
if err == nil {
t.Error("NewVCRServer error cannot be nil")
}
assert.ErrorIs(t, err, errJSONMockFilePathRequired)
// Set up mock data
test1 := VCRMock{}
@@ -38,41 +38,30 @@ func TestNewVCRServer(t *testing.T) {
Amount: 1,
Currency: "bitcoin",
})
if err != nil {
t.Fatal("marshal error", err)
}
require.NoError(t, err, "Marshal must not error")
testValue := HTTPResponse{Data: rp, QueryString: queryString, BodyParams: queryString}
test1.Routes["/test"][http.MethodGet] = []HTTPResponse{testValue}
payload, err := json.Marshal(test1)
if err != nil {
t.Fatal("marshal error", err)
}
require.NoError(t, err, "Marshal must not error")
err = os.WriteFile(testFile, payload, os.ModePerm)
if err != nil {
t.Fatal("marshal error", err)
}
require.NoError(t, err, "WriteFile must not error")
deets, client, err := NewVCRServer(testFile)
if err != nil {
t.Error("NewVCRServer error", err)
}
assert.NoError(t, err, "NewVCRServer should not error")
err = common.SetHTTPClient(client) // Set common package global HTTP Client
if err != nil {
t.Fatal(err)
}
require.NoError(t, err)
_, err = common.SendHTTPRequest(t.Context(),
http.MethodGet,
"http://localhost:300/somethingElse?"+queryString,
nil,
bytes.NewBufferString(""), true)
if err == nil {
t.Error("Sending http request expected an error")
}
var netErr *net.OpError
assert.ErrorAs(t, err, &netErr, "SendHTTPRequest should return a net.OpError for an invalid host")
// Expected good outcome
r, err := common.SendHTTPRequest(t.Context(),
@@ -80,47 +69,24 @@ func TestNewVCRServer(t *testing.T) {
deets,
nil,
bytes.NewBufferString(""), true)
if err != nil {
t.Error("Sending http request error", err)
}
if !strings.Contains(string(r), "404 page not found") {
t.Error("Was not expecting any value returned:", r)
}
assert.NoError(t, err, "SendHTTPRequest should not error")
assert.Contains(t, string(r), "404 page not found", "SendHTTPRequest return should only contain 404")
r, err = common.SendHTTPRequest(t.Context(),
http.MethodGet,
deets+"/test?"+queryString,
nil,
bytes.NewBufferString(""), true)
if err != nil {
t.Error("Sending http request error", err)
}
assert.NoError(t, err, "SendHTTPRequest should not error")
var res responsePayload
err = json.Unmarshal(r, &res)
if err != nil {
t.Error("unmarshal error", err)
}
if res.Price != 8000 {
t.Error("response error expected 8000 but received:",
res.Price)
}
if res.Amount != 1 {
t.Error("response error expected 1 but received:",
res.Amount)
}
if res.Currency != "bitcoin" {
t.Error("response error expected \"bitcoin\" but received:",
res.Currency)
}
assert.NoError(t, err, "Unmarshal should not error")
assert.Equalf(t, 8000.0, res.Price, "response error expected 8000 but received: %f", res.Price)
assert.Equalf(t, 1.0, res.Amount, "response error expected 1 but received: %f", res.Amount)
assert.Equalf(t, "bitcoin", res.Currency, "response error expected \"bitcoin\" but received: %s", res.Currency)
// clean up test.json file
err = os.Remove(testFile)
if err != nil {
t.Fatal("Remove error", err)
}
require.NoError(t, err, "Remove testFile must not error")
}

View File

@@ -5919,14 +5919,15 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, f reque
headers["OK-ACCESS-PASSPHRASE"] = creds.ClientID
}
return &request.Item{
Method: strings.ToUpper(httpMethod),
Path: endpoint + requestPath,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: strings.ToUpper(httpMethod),
Path: endpoint + requestPath,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &resp,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}
if err := e.SendPayload(ctx, f, newRequest, requestType); err != nil {

View File

@@ -1741,7 +1741,7 @@ func TestMarshalOrder(t *testing.T) {
Price: 1000,
}
j, err := json.Marshal(orderSubmit)
require.NoError(t, err, "json.Marshal must not error")
require.NoError(t, err, "Marshal must not error")
exp := []byte(`{"Exchange":"test","Type":4,"Side":"BUY","Pair":"BTC-USDT","AssetType":"spot","TimeInForce":"","ReduceOnly":false,"Leverage":0,"Price":1000,"Amount":1,"QuoteAmount":0,"TriggerPrice":0,"TriggerPriceType":0,"ClientID":"","ClientOrderID":"","AutoBorrow":false,"MarginType":"multi","RetrieveFees":false,"RetrieveFeeDelay":0,"RiskManagementModes":{"Mode":"","TakeProfit":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopLoss":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0},"StopEntry":{"Enabled":false,"TriggerPriceType":0,"Price":0,"LimitPrice":0,"OrderType":0}},"Hidden":false,"Iceberg":false,"TrackingMode":0,"TrackingValue":0}`)
assert.Equal(t, exp, j)
}

View File

@@ -909,12 +909,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
@@ -948,15 +949,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
path := fmt.Sprintf("%s/%s", ePoint, poloniexAPITradingEndpoint)
return &request.Item{
Method: method,
Path: path,
Headers: headers,
Body: bytes.NewBufferString(values.Encode()),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: method,
Path: path,
Headers: headers,
Body: bytes.NewBufferString(values.Encode()),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}

File diff suppressed because it is too large Load Diff

View File

@@ -256,7 +256,7 @@ func (r *Requester) doRequest(ctx context.Context, endpoint EndpointLimit, newRe
if p.HTTPRecording {
// This dumps http responses for future mocking implementations
err = mock.HTTPRecord(resp, r.name, contents)
err = mock.HTTPRecord(resp, r.name, contents, p.HTTPMockDataSliceLimit)
if err != nil {
return fmt.Errorf("mock recording failure %w, request %v: resp: %v", err, req, resp)
}

View File

@@ -41,16 +41,17 @@ type Requester struct {
// Item is a temp item for requests
type Item struct {
Method string
Path string
Headers map[string]string
Body io.Reader
Result any
NonceEnabled bool
Verbose bool
HTTPDebugging bool
HTTPRecording bool
IsReserved bool
Method string
Path string
Headers map[string]string
Body io.Reader
Result any
NonceEnabled bool
Verbose bool
HTTPDebugging bool
HTTPRecording bool
HTTPMockDataSliceLimit int // Limits slices per HTTP record to reduce mock data size.
IsReserved bool
// HeaderResponse for inspection of header contents package side useful for
// pagination
HeaderResponse *http.Header

View File

@@ -277,12 +277,13 @@ func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
}
item := &request.Item{
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodGet,
Path: endpoint + path,
Result: result,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}
return e.SendPayload(ctx, request.Unset, func() (*request.Item, error) {
@@ -322,15 +323,16 @@ func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
headers["Content-Type"] = "application/x-www-form-urlencoded"
return &request.Item{
Method: http.MethodPost,
Path: endpoint,
Headers: headers,
Body: strings.NewReader(encoded),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
Method: http.MethodPost,
Path: endpoint,
Headers: headers,
Body: strings.NewReader(encoded),
Result: result,
NonceEnabled: true,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
HTTPMockDataSliceLimit: e.HTTPMockDataSliceLimit,
}, nil
}, request.AuthenticatedRequest)
}

View File

@@ -16,6 +16,7 @@
"account_number",
"username",
"login",
"secret",
"apiKey"
]
}