Kucoin: Fix intermittent TestPushData failure (#2116)

* Testing: Fix FixtureToDataHandlerWithErrors logging []byte

* Kucoin: Fix global mutexes and maps

Highlighted by:
```
go test -count 2 -run TestPushData
```

that the second run wasn't finding a futures orderbook, because the
instance had changed but kucoin was using a global map
This commit is contained in:
Gareth Kirwan
2025-12-01 07:07:13 +07:00
committed by GitHub
parent dbf3b772b6
commit 6ae40f3688
4 changed files with 20 additions and 24 deletions

View File

@@ -31,11 +31,12 @@ import (
// Exchange implements exchange.IBotExchange and contains additional specific api methods for interacting with Kucoin
type Exchange struct {
exchange.Base
obmMutex sync.Mutex
obm *orderbookManager
fetchedFuturesOrderbookMutex sync.Mutex
fetchedFuturesOrderbook map[string]bool
}
var locker sync.Mutex
const (
kucoinAPIURL = "https://api.kucoin.com/api"
tradeBaseURL = "https://www.kucoin.com/"

View File

@@ -72,7 +72,6 @@ func TestMain(m *testing.M) {
asset.Margin: marginTradablePair,
asset.Futures: futuresTradablePair,
}
fetchedFuturesOrderbook = map[string]bool{}
os.Exit(m.Run())
}
@@ -4088,13 +4087,14 @@ func TestGetCurrencyTradeURL(t *testing.T) {
// testInstance returns a local Kucoin for isolated testing
func testInstance(tb testing.TB) *Exchange {
tb.Helper()
kucoin := new(Exchange)
require.NoError(tb, testexch.Setup(kucoin), "Test instance Setup must not error")
kucoin.obm = &orderbookManager{
e := new(Exchange)
require.NoError(tb, testexch.Setup(e), "Test instance Setup must not error")
e.obm = &orderbookManager{
state: make(map[currency.Code]map[currency.Code]map[asset.Item]*update),
jobs: make(chan job, maxWSOrderbookJobs),
}
return kucoin
e.fetchedFuturesOrderbook = map[string]bool{}
return e
}
func TestGetTradingPairActualFees(t *testing.T) {

View File

@@ -30,11 +30,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/log"
)
var (
fetchedFuturesOrderbookMutex sync.Mutex
fetchedFuturesOrderbook map[string]bool
)
const (
publicBullets = "/v1/bullet-public"
privateBullets = "/v1/bullet-private"
@@ -121,9 +116,9 @@ func (e *Exchange) WsConnect() error {
if !e.Websocket.IsEnabled() || !e.IsEnabled() {
return websocket.ErrWebsocketNotEnabled
}
fetchedFuturesOrderbookMutex.Lock()
fetchedFuturesOrderbook = map[string]bool{}
fetchedFuturesOrderbookMutex.Unlock()
e.fetchedFuturesOrderbookMutex.Lock()
e.fetchedFuturesOrderbook = map[string]bool{}
e.fetchedFuturesOrderbookMutex.Unlock()
var dialer gws.Dialer
dialer.HandshakeTimeout = e.Config.HTTPTimeout
dialer.Proxy = http.ProxyFromEnvironment
@@ -503,12 +498,12 @@ func (e *Exchange) processFuturesMarkPriceAndIndexPrice(respData []byte, instrum
// ensureFuturesOrderbookSnapshotLoaded makes sure an initial futures orderbook snapshot is loaded
func (e *Exchange) ensureFuturesOrderbookSnapshotLoaded(ctx context.Context, symbol string) error {
fetchedFuturesOrderbookMutex.Lock()
defer fetchedFuturesOrderbookMutex.Unlock()
if fetchedFuturesOrderbook[symbol] {
e.fetchedFuturesOrderbookMutex.Lock()
defer e.fetchedFuturesOrderbookMutex.Unlock()
if e.fetchedFuturesOrderbook[symbol] {
return nil
}
fetchedFuturesOrderbook[symbol] = true
e.fetchedFuturesOrderbook[symbol] = true
enabledPairs, err := e.GetEnabledPairs(asset.Futures)
if err != nil {
return err
@@ -1097,8 +1092,8 @@ type job struct {
// setupOrderbookManager sets up the orderbook manager for websocket orderbook data handling.
func (e *Exchange) setupOrderbookManager(ctx context.Context) {
locker.Lock()
defer locker.Unlock()
e.obmMutex.Lock()
defer e.obmMutex.Unlock()
if e.obm == nil {
e.obm = &orderbookManager{
state: make(map[currency.Code]map[currency.Code]map[asset.Item]*update),

View File

@@ -133,7 +133,7 @@ func MockWsInstance[T any, PT interface {
// FixtureError contains an error and the message that caused it
type FixtureError struct {
Err error
Msg []byte
Msg string
}
// FixtureToDataHandler squirts the contents of a file to a reader function (probably e.wsHandleData) and asserts no errors are returned
@@ -163,7 +163,7 @@ func FixtureToDataHandlerWithErrors(tb testing.TB, fixturePath string, reader fu
if err := reader(tb.Context(), msg); err != nil {
errs = append(errs, FixtureError{
Err: err,
Msg: msg,
Msg: string(msg),
})
}
}