mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
142 lines
5.4 KiB
Go
142 lines
5.4 KiB
Go
package subscription
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
|
)
|
|
|
|
var (
|
|
btcusdtPair = currency.NewBTCUSDT()
|
|
ethusdcPair = currency.NewPair(currency.ETH, currency.USDC)
|
|
ltcusdcPair = currency.NewPair(currency.LTC, currency.USDC)
|
|
)
|
|
|
|
// TestSubscriptionString exercises the String method
|
|
func TestSubscriptionString(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{
|
|
Channel: "candles",
|
|
Asset: asset.Spot,
|
|
Pairs: currency.Pairs{btcusdtPair, ethusdcPair.Format(currency.PairFormat{Delimiter: "/"})},
|
|
}
|
|
assert.Equal(t, "candles spot BTC/USDT,ETH/USDC", s.String(), "Subscription String should return correct value")
|
|
s.Key = 42
|
|
assert.Equal(t, "42: candles spot BTC/USDT,ETH/USDC", s.String(), "String with a non-MatchableKey")
|
|
}
|
|
|
|
// TestState exercises the state getter
|
|
func TestState(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{}
|
|
assert.Equal(t, InactiveState, s.State(), "State should return initial state")
|
|
s.state = SubscribedState
|
|
assert.Equal(t, SubscribedState, s.State(), "State should return correct state")
|
|
}
|
|
|
|
// TestSetState exercises the state setter
|
|
func TestSetState(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
s := &Subscription{state: UnsubscribedState}
|
|
|
|
for i := InactiveState; i <= UnsubscribedState; i++ {
|
|
assert.NoErrorf(t, s.SetState(i), "State should not error setting state %s", i)
|
|
}
|
|
assert.ErrorIs(t, s.SetState(UnsubscribedState), ErrInStateAlready, "SetState should error on same state")
|
|
assert.ErrorIs(t, s.SetState(UnsubscribedState+1), ErrInvalidState, "Setting an invalid state should error")
|
|
}
|
|
|
|
// TestEnsureKeyed exercises the key getter and ensures it sets a self-pointer key for non
|
|
func TestEnsureKeyed(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{}
|
|
k1, ok := s.EnsureKeyed().(MatchableKey)
|
|
if assert.True(t, ok, "EnsureKeyed should return a MatchableKey") {
|
|
assert.Same(t, s, k1.GetSubscription(), "Key should point to the same struct")
|
|
}
|
|
type platypus string
|
|
s = &Subscription{
|
|
Key: platypus("Gerald"),
|
|
Channel: "orderbook",
|
|
}
|
|
k2 := s.EnsureKeyed()
|
|
assert.IsType(t, platypus(""), k2, "EnsureKeyed should return a platypus")
|
|
assert.Equal(t, s.Key, k2, "Key should be the key provided")
|
|
}
|
|
|
|
// TestSubscriptionMarshaling ensures json Marshalling is clean and concise
|
|
// Since there is no UnmarshalJSON, this just exercises the json field tags of Subscription, and regressions in conciseness
|
|
func TestSubscriptionMarshaling(t *testing.T) {
|
|
t.Parallel()
|
|
j, err := json.Marshal(&Subscription{Key: 42, Channel: CandlesChannel})
|
|
assert.NoError(t, err, "Marshalling should not error")
|
|
assert.JSONEq(t, `{"enabled":false,"channel":"candles"}`, string(j), "Marshalling should be clean and concise")
|
|
|
|
j, err = json.Marshal(&Subscription{Enabled: true, Channel: OrderbookChannel, Interval: kline.FiveMin, Levels: 4})
|
|
assert.NoError(t, err, "Marshalling should not error")
|
|
assert.JSONEq(t, `{"enabled":true,"channel":"orderbook","interval":"5m","levels":4}`, string(j), "Marshalling should be clean and concise")
|
|
|
|
j, err = json.Marshal(&Subscription{Enabled: true, Channel: OrderbookChannel, Interval: kline.FiveMin, Levels: 4, Pairs: currency.Pairs{currency.NewBTCUSDT()}})
|
|
assert.NoError(t, err, "Marshalling should not error")
|
|
assert.JSONEq(t, `{"enabled":true,"channel":"orderbook","pairs":"BTCUSDT","interval":"5m","levels":4}`, string(j), "Marshalling should be clean and concise")
|
|
|
|
j, err = json.Marshal(&Subscription{Enabled: true, Channel: MyTradesChannel, Authenticated: true})
|
|
assert.NoError(t, err, "Marshalling should not error")
|
|
assert.JSONEq(t, `{"enabled":true,"channel":"myTrades","authenticated":true}`, string(j), "Marshalling should be clean and concise")
|
|
}
|
|
|
|
func TestSubscriptionClone(t *testing.T) {
|
|
t.Parallel()
|
|
params := map[string]any{"a": 42}
|
|
a := &Subscription{
|
|
Channel: TickerChannel,
|
|
Interval: kline.OneHour,
|
|
Pairs: currency.Pairs{btcusdtPair},
|
|
Params: params,
|
|
}
|
|
a.EnsureKeyed()
|
|
b := a.Clone()
|
|
assert.IsType(t, new(Subscription), b, "Clone should return a Subscription pointer")
|
|
assert.NotSame(t, a, b, "Clone should return a new Subscription")
|
|
assert.Nil(t, b.Key, "Clone should have a nil key")
|
|
b.Pairs[0].Delimiter = "🐳"
|
|
assert.Empty(t, a.Pairs[0].Delimiter, "Pairs should be (relatively) deep copied")
|
|
b.Params["a"] = 12
|
|
assert.Equal(t, 42, a.Params["a"], "Params should be (relatively) deep copied")
|
|
assert.NotEqual(t, params, b.Params, "Params should be cloned")
|
|
assert.Equal(t, params, a.Params, "Original Params should be left alone")
|
|
a.m.Lock()
|
|
assert.True(t, b.m.TryLock(), "Clone should use a different Mutex")
|
|
}
|
|
|
|
// TestSetKey exercises SetKey
|
|
func TestSetKey(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{}
|
|
s.SetKey(14)
|
|
assert.Equal(t, 14, s.Key, "SetKey should set a key correctly")
|
|
}
|
|
|
|
// TestSetPairs exercises SetPairs
|
|
func TestSetPairs(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{}
|
|
s.SetPairs(currency.Pairs{btcusdtPair})
|
|
assert.Equal(t, "BTCUSDT", s.Pairs.Join(), "SetPairs should set a key correctly")
|
|
}
|
|
|
|
// TestAddPairs exercises AddPairs
|
|
func TestAddPairs(t *testing.T) {
|
|
t.Parallel()
|
|
s := &Subscription{}
|
|
s.AddPairs()
|
|
assert.Empty(t, s.Pairs, "Should not have added any pairs")
|
|
s.AddPairs(btcusdtPair)
|
|
assert.Len(t, s.Pairs, 1, "Should not have added any pairs")
|
|
}
|