Files
gocryptotrader/exchanges/gateio/gateio_wrapper_test.go
Ryan O'Hara-Reid cf54764cb7 GateIO: Update websocket orderbook manager (#1989)
* gateio: websocket ob manager fix (cherry-pick me)

* fix(gateio): update websocket orderbook manager to support delay and deadline parameters
    feat(subscriptions): mv ChannelKey type for subscription management from gateio to subscriptions
    test(gateio): enhance tests for orderbook update manager and subscription keys

* ai: nits

* linter: fix

* Fix asset typo and add in case test

* cranktakular: nits

* cranktakular: nits after merge master

* bump time delay for cache

* fix bug where on error it never initiates another orderbook fetch

* lint: fix

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* linter: fix

* Update exchanges/gateio/gateio_wrapper_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/gateio_wrapper.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/gateio_wrapper_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* Update exchanges/gateio/gateio_wrapper.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* bossking: nits

* Update exchanges/gateio/ws_ob_update_manager_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* apply patch

* rm error state as this was on the same thread as cacheStateQueuing and had the potential to drop messages, add tests.

* linter: fix

* mock live request

* misc: fix

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/gateio/ws_ob_update_manager.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* field name from mtx -> m

* lint: fix

* race: check fix

* thrasher-: patch adams

---------

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
2025-11-27 12:21:17 +11:00

154 lines
5.4 KiB
Go

package gateio
import (
"fmt"
"testing"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
testexch "github.com/thrasher-corp/gocryptotrader/internal/testing/exchange"
)
func TestCancelAllOrders(t *testing.T) {
t.Parallel()
_, err := e.CancelAllOrders(t.Context(), nil)
require.ErrorIs(t, err, order.ErrCancelOrderIsNil)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{Pair: currency.EMPTYPAIR, AssetType: 1336})
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{Pair: currency.NewBTCUSDT(), AssetType: 1336})
require.ErrorIs(t, err, asset.ErrNotSupported)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{
Pair: currency.NewBTCUSDT(),
AssetType: asset.Options,
Side: order.ClosePosition,
})
require.ErrorIs(t, err, order.ErrSideIsInvalid)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{
Pair: currency.NewPair(currency.BTC, currency.EMPTYCODE),
AssetType: asset.USDTMarginedFutures,
Side: order.Long,
})
require.ErrorIs(t, err, errInvalidSettlementQuote)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{
Pair: currency.NewPair(currency.BTC, currency.EMPTYCODE),
AssetType: asset.USDTMarginedFutures,
Side: order.Short,
})
require.ErrorIs(t, err, errInvalidSettlementQuote)
_, err = e.CancelAllOrders(t.Context(), &order.Cancel{
Pair: currency.NewPair(currency.BTC, currency.EMPTYCODE),
AssetType: asset.USDTMarginedFutures,
Side: order.AnySide,
})
require.ErrorIs(t, err, errInvalidSettlementQuote)
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
for _, a := range e.GetAssetTypes(false) {
t.Run(a.String(), func(t *testing.T) {
t.Parallel()
r := &order.Cancel{
OrderID: "1",
AccountID: "1",
AssetType: a,
Pair: currency.EMPTYPAIR,
}
_, err := e.CancelAllOrders(t.Context(), r)
assert.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
r.Pair = getPair(t, a)
_, err = e.CancelAllOrders(t.Context(), r)
assert.NoError(t, err)
})
}
}
func TestMessageID(t *testing.T) {
t.Parallel()
id := e.MessageID()
require.Len(t, id, 32, "message ID must be 32 characters long for usage as a request ID")
got, err := uuid.FromString(id)
require.NoError(t, err, "ID string must convert back to a UUID")
require.Equal(t, uuid.V7, got.Version(), "message ID must be a UUID v7")
require.Len(t, got.String(), 36, "UUID v7 string representation must be 36 characters long")
}
// 7610378 143.3 ns/op 48 B/op 2 allocs/op
func BenchmarkMessageID(b *testing.B) {
for b.Loop() {
_ = e.MessageID()
}
}
func TestFetchOrderbook(t *testing.T) {
t.Parallel()
testexch.UpdatePairsOnce(t, e)
availSpot, err := e.GetAvailablePairs(asset.Spot)
require.NoError(t, err, "GetAvailablePairs must not error")
availMargin, err := e.GetAvailablePairs(asset.Margin)
require.NoError(t, err, "GetAvailablePairs must not error")
marginPairNotInSpot, err := availMargin.Remove(availSpot...).GetRandomPair()
require.NoError(t, err, "GetRandomPair must not error")
availOptions, err := e.GetAvailablePairs(asset.Options)
require.NoError(t, err, "GetAvailablePairs must not error")
optionsPair, err := availOptions.GetRandomPair()
require.NoError(t, err, "GetRandomPair must not error")
availDelivery, err := e.GetAvailablePairs(asset.DeliveryFutures)
require.NoError(t, err, "GetAvailablePairs must not error")
deliveryPair, err := availDelivery.GetRandomPair()
require.NoError(t, err, "GetRandomPair must not error")
for _, tc := range []struct {
pair currency.Pair
a asset.Item
err error
}{
{pair: currency.EMPTYPAIR, a: asset.Spot, err: currency.ErrCurrencyPairEmpty},
{pair: marginPairNotInSpot, a: asset.Margin, err: errNoSpotInstrument},
{pair: marginPairNotInSpot, a: asset.Binary, err: asset.ErrNotSupported},
{pair: currency.NewBTCUSDT(), a: asset.Spot},
{pair: currency.NewBTCUSDT(), a: asset.USDTMarginedFutures},
{pair: deliveryPair, a: asset.DeliveryFutures},
{pair: optionsPair, a: asset.Options},
} {
t.Run(fmt.Sprintf("%s-%s: expected err:%v", tc.pair, tc.a, tc.err), func(t *testing.T) {
t.Parallel()
got, err := e.fetchOrderbook(t.Context(), tc.pair, tc.a, 1)
if tc.err != nil {
require.ErrorIs(t, err, tc.err)
return
}
require.NoError(t, err)
assert.Equal(t, e.Name, got.Exchange, "Exchange name should be correct")
assert.True(t, tc.pair.Equal(got.Pair), "Pair should be correct")
assert.Equal(t, tc.a, got.Asset, "Asset should be correct")
assert.LessOrEqual(t, len(got.Asks), 1, "Asks count should not exceed limit, but may be empty especially for options")
assert.LessOrEqual(t, len(got.Bids), 1, "Bids count should not exceed limit, but may be empty especially for options")
assert.NotZero(t, got.LastUpdated, "Last updated timestamp should be set")
assert.NotZero(t, got.LastUpdateID, "Last update ID should be set")
assert.NotZero(t, got.LastPushed, "Last pushed timestamp should be set")
assert.LessOrEqual(t, got.LastUpdated, got.LastPushed, "Last updated timestamp should be before last pushed timestamp")
})
}
}