mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
* Currency: Remove Pair Index formatting/parsing This feature was originally for exchanges with only one pair (e.g. KRW) which made parsing easier. However there's no examples of this left, and we can reduce complexity overall by removing it. * Exchange: Partial assertify tests and fixes * Currency: Fix panic on a delimiterless small currency
1039 lines
27 KiB
Go
1039 lines
27 KiB
Go
package currency
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
defaultPair = "BTCUSD"
|
|
defaultPairWDelimiter = "BTC-USD"
|
|
)
|
|
|
|
func TestLower(t *testing.T) {
|
|
t.Parallel()
|
|
pair, err := NewPairFromString(defaultPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected, err := NewPairFromString(defaultPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if actual := pair.Lower(); actual.String() != expected.Lower().String() {
|
|
t.Errorf("Lower(): %s was not equal to expected value: %s",
|
|
actual,
|
|
expected.Lower())
|
|
}
|
|
}
|
|
|
|
func TestUpper(t *testing.T) {
|
|
t.Parallel()
|
|
pair, err := NewPairFromString(defaultPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected, err := NewPairFromString(defaultPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if actual := pair.Upper(); actual.String() != expected.String() {
|
|
t.Errorf("Upper(): %s was not equal to expected value: %s",
|
|
actual, expected)
|
|
}
|
|
}
|
|
|
|
func TestPairUnmarshalJSON(t *testing.T) {
|
|
var p Pair
|
|
assert.NoError(t, p.UnmarshalJSON([]byte(`"btc_usd"`)), "UnmarshalJSON should not error")
|
|
assert.Equal(t, "btc", p.Base.String(), "Base should be correct")
|
|
assert.Equal(t, "usd", p.Quote.String(), "Quote should be correct")
|
|
assert.Equal(t, "_", p.Delimiter, "Delimiter should be correct")
|
|
|
|
assert.ErrorIs(t, p.UnmarshalJSON([]byte(`"btcusd"`)), errCannotCreatePair, "UnmarshalJSON with no delimiter should error")
|
|
|
|
assert.NoError(t, p.UnmarshalJSON([]byte(`""`)), "UnmarshalJSON should not error on empty value")
|
|
assert.Equal(t, EMPTYPAIR, p, "UnmarshalJSON empty value should give EMPTYPAIR")
|
|
assert.NoError(t, p.UnmarshalJSON([]byte(`null`)), "UnmarshalJSON should not error on empty value")
|
|
assert.Equal(t, EMPTYPAIR, p, "UnmarshalJSON null value should give EMPTYPAIR")
|
|
}
|
|
|
|
func TestPairMarshalJSON(t *testing.T) {
|
|
quickstruct := struct {
|
|
Pair *Pair `json:"superPair"`
|
|
}{
|
|
&Pair{Base: BTC, Quote: USD, Delimiter: "-"},
|
|
}
|
|
|
|
encoded, err := json.Marshal(quickstruct)
|
|
if err != nil {
|
|
t.Fatal("Pair MarshalJSON() error", err)
|
|
}
|
|
|
|
expected := `{"superPair":"BTC-USD"}`
|
|
if string(encoded) != expected {
|
|
t.Errorf("Pair MarshalJSON() error expected %s but received %s",
|
|
expected, string(encoded))
|
|
}
|
|
}
|
|
|
|
func TestIsCryptoPair(t *testing.T) {
|
|
if !NewPair(BTC, LTC).IsCryptoPair() {
|
|
t.Error("TestIsCryptoPair. Expected true result")
|
|
}
|
|
|
|
if NewPair(BTC, USD).IsCryptoPair() {
|
|
t.Error("TestIsCryptoPair. Expected false result")
|
|
}
|
|
}
|
|
|
|
func TestIsCryptoFiatPair(t *testing.T) {
|
|
if !NewPair(BTC, USD).IsCryptoFiatPair() {
|
|
t.Error("TestIsCryptoPair. Expected true result")
|
|
}
|
|
|
|
if NewPair(BTC, LTC).IsCryptoFiatPair() {
|
|
t.Error("TestIsCryptoPair. Expected false result")
|
|
}
|
|
}
|
|
|
|
func TestIsFiatPair(t *testing.T) {
|
|
if !NewPair(AUD, USD).IsFiatPair() {
|
|
t.Error("TestIsFiatPair. Expected true result")
|
|
}
|
|
|
|
if NewPair(BTC, AUD).IsFiatPair() {
|
|
t.Error("TestIsFiatPair. Expected false result")
|
|
}
|
|
}
|
|
|
|
func TestIsCryptoStablePair(t *testing.T) {
|
|
if !NewPair(BTC, USDT).IsCryptoStablePair() {
|
|
t.Error("TestIsCryptoStablePair. Expected true result")
|
|
}
|
|
|
|
if !NewPair(DAI, USDT).IsCryptoStablePair() {
|
|
t.Error("TestIsCryptoStablePair. Expected true result")
|
|
}
|
|
|
|
if NewPair(AUD, USDT).IsCryptoStablePair() {
|
|
t.Error("TestIsCryptoStablePair. Expected false result")
|
|
}
|
|
}
|
|
|
|
func TestIsStablePair(t *testing.T) {
|
|
if !NewPair(USDT, DAI).IsStablePair() {
|
|
t.Error("TestIsStablePair. Expected true result")
|
|
}
|
|
|
|
if NewPair(USDT, AUD).IsStablePair() {
|
|
t.Error("TestIsStablePair. Expected false result")
|
|
}
|
|
|
|
if NewPair(USDT, LTC).IsStablePair() {
|
|
t.Error("TestIsStablePair. Expected false result")
|
|
}
|
|
}
|
|
|
|
func TestString(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if actual, expected := defaultPair, pair.String(); actual != expected {
|
|
t.Errorf("String(): %s was not equal to expected value: %s",
|
|
actual, expected)
|
|
}
|
|
}
|
|
|
|
func TestFirstCurrency(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if actual, expected := pair.Base, BTC; !actual.Equal(expected) {
|
|
t.Errorf(
|
|
"GetFirstCurrency(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestSecondCurrency(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if actual, expected := pair.Quote, USD; !actual.Equal(expected) {
|
|
t.Errorf(
|
|
"GetSecondCurrency(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestPair(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if actual, expected := pair.String(), defaultPair; actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestDisplay(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := NewPairDelimiter(defaultPairWDelimiter, "wow")
|
|
if err == nil {
|
|
t.Fatal("error cannot be nil")
|
|
}
|
|
pair, err := NewPairDelimiter(defaultPairWDelimiter, "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual := pair.String()
|
|
expected := defaultPairWDelimiter
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
actual = EMPTYFORMAT.Format(pair)
|
|
expected = "btcusd"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
actual = pair.Format(PairFormat{Delimiter: "~", Uppercase: true}).String()
|
|
expected = "BTC~USD"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestEquall(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
secondPair := NewPair(BTC, USD)
|
|
actual := pair.Equal(secondPair)
|
|
expected := true
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
secondPair.Quote = ETH
|
|
actual = pair.Equal(secondPair)
|
|
expected = false
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
secondPair = NewPair(USD, BTC)
|
|
actual = pair.Equal(secondPair)
|
|
expected = false
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestEqualIncludeReciprocal(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
secondPair := NewPair(BTC, USD)
|
|
actual := pair.EqualIncludeReciprocal(secondPair)
|
|
expected := true
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
secondPair.Quote = ETH
|
|
actual = pair.EqualIncludeReciprocal(secondPair)
|
|
expected = false
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
secondPair = NewPair(USD, BTC)
|
|
actual = pair.EqualIncludeReciprocal(secondPair)
|
|
expected = true
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Equal(): %v was not equal to expected value: %v",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestSwap(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if actual, expected := pair.Swap().String(), "USDBTC"; actual != expected {
|
|
t.Errorf(
|
|
"TestSwap: %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestEmpty(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if pair.IsEmpty() {
|
|
t.Error("Empty() returned true when the pair was initialised")
|
|
}
|
|
|
|
p := NewPair(NewCode(""), NewCode(""))
|
|
if !p.IsEmpty() {
|
|
t.Error("Empty() returned true when the pair wasn't initialised")
|
|
}
|
|
}
|
|
|
|
func TestNewPair(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPair(BTC, USD)
|
|
if expected, actual := defaultPair, pair.String(); actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestNewPairWithDelimiter(t *testing.T) {
|
|
t.Parallel()
|
|
pair := NewPairWithDelimiter("BTC", "USD", "-test-")
|
|
actual := pair.String()
|
|
expected := "BTC-test-USD"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
pair = NewPairWithDelimiter("BTC", "USD", "")
|
|
actual = pair.String()
|
|
expected = defaultPair
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestNewPairDelimiter(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := NewPairDelimiter("", "")
|
|
if err == nil {
|
|
t.Fatal("error cannot be nil")
|
|
}
|
|
_, err = NewPairDelimiter("BTC_USD", "wow")
|
|
if err == nil {
|
|
t.Fatal("error cannot be nil")
|
|
}
|
|
|
|
_, err = NewPairDelimiter("BTC_USD", " ")
|
|
if err == nil {
|
|
t.Fatal("error cannot be nil")
|
|
}
|
|
|
|
pair, err := NewPairDelimiter(defaultPairWDelimiter, "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual := pair.String()
|
|
expected := defaultPairWDelimiter
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
actual = pair.Delimiter
|
|
expected = "-"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Delmiter: %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
pair, err = NewPairDelimiter("BTC-MOVE-0626", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual = pair.String()
|
|
expected = "BTC-MOVE-0626"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
pair, err = NewPairDelimiter("fBTC-USDT", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual = pair.String()
|
|
expected = "fbtc-USDT"
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestNewPairFromString(t *testing.T) {
|
|
t.Parallel()
|
|
pairStr := defaultPairWDelimiter
|
|
pair, err := NewPairFromString(pairStr)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual := pair.String()
|
|
expected := defaultPairWDelimiter
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
|
|
pairStr = defaultPair
|
|
pair, err = NewPairFromString(pairStr)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
actual = pair.String()
|
|
expected = defaultPair
|
|
if actual != expected {
|
|
t.Errorf(
|
|
"Pair(): %s was not equal to expected value: %s",
|
|
actual, expected,
|
|
)
|
|
}
|
|
pairMap := map[string]Pair{
|
|
"BTC_USDT-20230630-45000-C": {Base: NewCode("BTC"), Delimiter: UnderscoreDelimiter, Quote: NewCode("USDT-20230630-45000-C")},
|
|
"BTC-USD-221007": {Base: NewCode("BTC"), Delimiter: DashDelimiter, Quote: NewCode("USD-221007")},
|
|
"IHT_ETH": {Base: NewCode("IHT"), Delimiter: UnderscoreDelimiter, Quote: NewCode("ETH")},
|
|
"BTC-USD-220930-30000-P": {Base: NewCode("BTC"), Delimiter: DashDelimiter, Quote: NewCode("USD-220930-30000-P")},
|
|
"XBTUSDTM": {Base: NewCode("XBT"), Delimiter: "", Quote: NewCode("USDTM")},
|
|
"BTC-PERPETUAL": {Base: NewCode("BTC"), Delimiter: DashDelimiter, Quote: NewCode("PERPETUAL")},
|
|
"SOL-21OCT22-20-C": {Base: NewCode("SOL"), Delimiter: DashDelimiter, Quote: NewCode("21OCT22-20-C")},
|
|
"SOL-FS-30DEC22_28OCT22": {Base: NewCode("SOL"), Delimiter: DashDelimiter, Quote: NewCode("FS-30DEC22_28OCT22")},
|
|
}
|
|
for key, expectedPair := range pairMap {
|
|
pair, err = NewPairFromString(key)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !pair.Equal(expectedPair) || pair.Delimiter != expectedPair.Delimiter {
|
|
t.Errorf("Pair(): %s was not equal to expected value: %s", pair.String(), expectedPair.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNewPairFromFormattedPairs(t *testing.T) {
|
|
t.Parallel()
|
|
p1, err := NewPairDelimiter("BTC-USDT", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p2, err := NewPairDelimiter("LTC-USD", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pairs := Pairs{
|
|
p1,
|
|
p2,
|
|
}
|
|
|
|
p, err := NewPairFromFormattedPairs("BTCUSDT", pairs, PairFormat{
|
|
Uppercase: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if p.String() != "BTC-USDT" {
|
|
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
|
|
}
|
|
|
|
p, err = NewPairFromFormattedPairs("btcusdt", pairs, PairFormat{Uppercase: false})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if p.String() != "BTC-USDT" {
|
|
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
|
|
}
|
|
|
|
// Now a wrong one, will default to NewPairFromString
|
|
p, err = NewPairFromFormattedPairs("ethusdt", pairs, EMPTYFORMAT)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if p.String() != "ethusdt" && p.Base.String() != "eth" {
|
|
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
|
|
}
|
|
}
|
|
|
|
func TestContainsCurrency(t *testing.T) {
|
|
p := NewPair(BTC, USD)
|
|
|
|
if !p.Contains(BTC) {
|
|
t.Error("TestContains: Expected currency was not found")
|
|
}
|
|
|
|
if p.Contains(ETH) {
|
|
t.Error("TestContains: Non-existent currency was found")
|
|
}
|
|
}
|
|
|
|
func TestFormatPairs(t *testing.T) {
|
|
_, err := FormatPairs([]string{""}, "-")
|
|
assert.ErrorIs(t, err, errEmptyPairString, "Should error on empty string")
|
|
|
|
_, err = FormatPairs([]string{"NO"}, "")
|
|
assert.ErrorIs(t, err, errNoDelimiter, "Should error on a small string with no delimiter")
|
|
|
|
newP, err := FormatPairs([]string{defaultPairWDelimiter}, "-")
|
|
assert.NoError(t, err)
|
|
require.NotEmpty(t, newP)
|
|
assert.Equal(t, defaultPairWDelimiter, newP[0].String(), "Pair should format correctly")
|
|
|
|
newP, err = FormatPairs([]string{defaultPair}, "")
|
|
assert.NoError(t, err)
|
|
require.NotEmpty(t, newP)
|
|
assert.Equal(t, defaultPair, newP[0].String(), "Pair should format correctly")
|
|
|
|
newP, err = FormatPairs([]string{"ETHUSD"}, "")
|
|
assert.NoError(t, err)
|
|
require.NotEmpty(t, newP)
|
|
assert.Equal(t, "ETHUSD", newP[0].String(), "Pair should format correctly")
|
|
}
|
|
|
|
func TestCopyPairFormat(t *testing.T) {
|
|
pairOne := NewPair(BTC, USD)
|
|
pairOne.Delimiter = "-"
|
|
|
|
var pairs []Pair
|
|
pairs = append(pairs, pairOne, NewPair(LTC, USD))
|
|
|
|
testPair := NewPair(BTC, USD)
|
|
testPair.Delimiter = "~"
|
|
|
|
result := CopyPairFormat(testPair, pairs, false)
|
|
if result.String() != defaultPairWDelimiter {
|
|
t.Error("TestCopyPairFormat: Expected pair was not found")
|
|
}
|
|
|
|
np := NewPair(ETH, USD)
|
|
result = CopyPairFormat(np, pairs, true)
|
|
if result.String() != "" {
|
|
t.Error("TestCopyPairFormat: Unexpected non empty pair returned")
|
|
}
|
|
}
|
|
|
|
func TestFindPairDifferences(t *testing.T) {
|
|
pairList, err := NewPairsFromStrings([]string{defaultPairWDelimiter, "ETH-USD", "LTC-USD"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
dash, err := NewPairsFromStrings([]string{"DASH-USD"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Test new pair update
|
|
diff, err := pairList.FindDifferences(dash, PairFormat{Delimiter: DashDelimiter, Uppercase: true})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(diff.New) != 1 && len(diff.Remove) != 3 && diff.FormatDifference {
|
|
t.Error("TestFindPairDifferences: Unexpected values")
|
|
}
|
|
|
|
diff, err = pairList.FindDifferences(Pairs{}, EMPTYFORMAT)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(diff.New) != 0 && len(diff.Remove) != 3 && !diff.FormatDifference {
|
|
t.Error("TestFindPairDifferences: Unexpected values")
|
|
}
|
|
|
|
diff, err = Pairs{}.FindDifferences(pairList, EMPTYFORMAT)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(diff.New) != 3 && len(diff.Remove) != 0 && diff.FormatDifference {
|
|
t.Error("TestFindPairDifferences: Unexpected values")
|
|
}
|
|
|
|
// Test that the supplied pair lists are the same, so
|
|
// no newPairs or removedPairs
|
|
diff, err = pairList.FindDifferences(pairList, PairFormat{Delimiter: DashDelimiter, Uppercase: true})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(diff.New) != 0 && len(diff.Remove) != 0 && !diff.FormatDifference {
|
|
t.Error("TestFindPairDifferences: Unexpected values")
|
|
}
|
|
|
|
_, err = pairList.FindDifferences(Pairs{EMPTYPAIR}, EMPTYFORMAT)
|
|
if !errors.Is(err, ErrCurrencyPairEmpty) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, ErrCurrencyPairEmpty)
|
|
}
|
|
|
|
_, err = Pairs{EMPTYPAIR}.FindDifferences(pairList, EMPTYFORMAT)
|
|
if !errors.Is(err, ErrCurrencyPairEmpty) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, ErrCurrencyPairEmpty)
|
|
}
|
|
|
|
// Test duplication
|
|
duplication, err := NewPairsFromStrings([]string{defaultPairWDelimiter, "ETH-USD", "LTC-USD", "ETH-USD"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = pairList.FindDifferences(duplication, EMPTYFORMAT)
|
|
if !errors.Is(err, ErrPairDuplication) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, ErrPairDuplication)
|
|
}
|
|
|
|
// This will allow for the removal of the duplicated item to be returned if
|
|
// contained in the original list.
|
|
diff, err = duplication.FindDifferences(pairList, EMPTYFORMAT)
|
|
if !errors.Is(err, nil) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
|
}
|
|
|
|
if len(diff.Remove) != 1 {
|
|
t.Fatal("expected removal value in pair difference struct")
|
|
}
|
|
|
|
if !diff.Remove[0].Equal(pairList[1]) {
|
|
t.Fatal("unexpected value returned", diff.Remove[0], pairList[1])
|
|
}
|
|
}
|
|
|
|
func TestPairsToStringArray(t *testing.T) {
|
|
var pairs Pairs
|
|
pairs = append(pairs, NewPair(BTC, USD))
|
|
|
|
expected := []string{defaultPair}
|
|
actual := pairs.Strings()
|
|
|
|
if actual[0] != expected[0] {
|
|
t.Error("TestPairsToStringArray: Unexpected values")
|
|
}
|
|
}
|
|
|
|
func TestRandomPairFromPairs(t *testing.T) {
|
|
// Test that an empty pairs array returns an empty currency pair
|
|
var emptyPairs Pairs
|
|
result, err := emptyPairs.GetRandomPair()
|
|
if !errors.Is(err, ErrCurrencyPairsEmpty) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, ErrCurrencyPairsEmpty)
|
|
}
|
|
if !result.IsEmpty() {
|
|
t.Error("TestRandomPairFromPairs: Unexpected values")
|
|
}
|
|
|
|
// Test that a populated pairs array returns a non-empty currency pair
|
|
var pairs Pairs
|
|
pairs = append(pairs, NewPair(BTC, USD))
|
|
result, err = pairs.GetRandomPair()
|
|
if !errors.Is(err, nil) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
|
}
|
|
|
|
if result.IsEmpty() {
|
|
t.Error("TestRandomPairFromPairs: Unexpected values")
|
|
}
|
|
|
|
// Test that a populated pairs array over a number of attempts returns ALL
|
|
// currency pairs
|
|
pairs = append(pairs, NewPair(ETH, USD))
|
|
expectedResults := make(map[string]bool)
|
|
for i := 0; i < 50; i++ {
|
|
result, err = pairs.GetRandomPair()
|
|
if !errors.Is(err, nil) {
|
|
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
|
}
|
|
expectedResults[result.String()] = true
|
|
}
|
|
|
|
for x := range pairs {
|
|
if !expectedResults[pairs[x].String()] {
|
|
t.Error("TestRandomPairFromPairs: Unexpected values")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIsInvalid(t *testing.T) {
|
|
p := NewPair(LTC, LTC)
|
|
if !p.IsInvalid() {
|
|
t.Error("IsInvalid() error expect true but received false")
|
|
}
|
|
}
|
|
|
|
func TestMatchPairsWithNoDelimiter(t *testing.T) {
|
|
p1, err := NewPairDelimiter("BTC-USDT", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p2, err := NewPairDelimiter("LTC-USD", "-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p3, err := NewPairFromStrings("EQUAD", "BTC")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p4, err := NewPairFromStrings("HTDF", "USDT")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p5, err := NewPairFromStrings("BETHER", "ETH")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pairs := Pairs{
|
|
p1,
|
|
p2,
|
|
p3,
|
|
p4,
|
|
p5,
|
|
}
|
|
|
|
p, err := MatchPairsWithNoDelimiter("BTCUSDT", pairs, PairFormat{
|
|
Uppercase: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Quote.String() != "USDT" && p.Base.String() != "BTC" {
|
|
t.Error("unexpected response")
|
|
}
|
|
|
|
p, err = MatchPairsWithNoDelimiter("EQUADBTC", pairs, PairFormat{
|
|
Uppercase: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Base.String() != "EQUAD" && p.Quote.String() != "BTC" {
|
|
t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String())
|
|
}
|
|
|
|
p, err = MatchPairsWithNoDelimiter("EQUADBTC", pairs, PairFormat{
|
|
Uppercase: true,
|
|
Delimiter: "/",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Base.String() != "EQUAD" && p.Quote.String() != "BTC" {
|
|
t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String())
|
|
}
|
|
|
|
p, err = MatchPairsWithNoDelimiter("HTDFUSDT", pairs, PairFormat{
|
|
Uppercase: true,
|
|
Delimiter: "/",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Base.String() != "HTDF" && p.Quote.String() != "USDT" {
|
|
t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String())
|
|
}
|
|
|
|
p, err = MatchPairsWithNoDelimiter("BETHERETH", pairs, PairFormat{
|
|
Uppercase: true,
|
|
Delimiter: "/",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Base.String() != "BETHER" && p.Quote.String() != "ETH" {
|
|
t.Errorf("unexpected response base: %v quote: %v", p.Base.String(), p.Quote.String())
|
|
}
|
|
}
|
|
|
|
func TestPairFormat_Format(t *testing.T) {
|
|
type fields struct {
|
|
Uppercase bool
|
|
Delimiter string
|
|
Separator string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
arg Pair
|
|
want string
|
|
}{
|
|
{
|
|
name: "empty",
|
|
fields: fields{},
|
|
arg: EMPTYPAIR,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "empty format",
|
|
fields: fields{},
|
|
arg: Pair{
|
|
Delimiter: "<>",
|
|
Base: AAA,
|
|
Quote: BTC,
|
|
},
|
|
want: "aaabtc",
|
|
},
|
|
{
|
|
name: "format",
|
|
fields: fields{
|
|
Uppercase: true,
|
|
Delimiter: "!!!",
|
|
},
|
|
arg: Pair{
|
|
Delimiter: "<>",
|
|
Base: AAA,
|
|
Quote: BTC,
|
|
},
|
|
want: "AAA!!!BTC",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
f := &PairFormat{
|
|
Uppercase: tt.fields.Uppercase,
|
|
Delimiter: tt.fields.Delimiter,
|
|
Separator: tt.fields.Separator,
|
|
}
|
|
if got := f.Format(tt.arg); got != tt.want {
|
|
t.Errorf("PairFormat.Format() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOther(t *testing.T) {
|
|
received, err := NewPair(DAI, XRP).Other(DAI)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !received.Equal(XRP) {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
received, err = NewPair(DAI, XRP).Other(XRP)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !received.Equal(DAI) {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
if _, err := NewPair(DAI, XRP).Other(BTC); !errors.Is(err, ErrCurrencyCodeEmpty) {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
}
|
|
|
|
func TestIsPopulated(t *testing.T) {
|
|
if receiver := NewPair(BTC, USDT).IsPopulated(); !receiver {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
if receiver := NewPair(BTC, NewCode("USD-1245")).IsPopulated(); !receiver {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
if receiver := NewPair(BTC, EMPTYCODE).IsPopulated(); receiver {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
if receiver := NewPair(EMPTYCODE, EMPTYCODE).IsPopulated(); receiver {
|
|
t.Fatal("unexpected value")
|
|
}
|
|
}
|
|
|
|
func TestGetOrderParameters(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
p := NewPair(BTC, USDT)
|
|
testCases := []struct {
|
|
Pair Pair
|
|
currency Code
|
|
market bool
|
|
selling bool
|
|
expectedParams *OrderParameters
|
|
expectedError error
|
|
}{
|
|
{expectedError: ErrCurrencyPairEmpty},
|
|
{Pair: p, expectedError: ErrCurrencyCodeEmpty},
|
|
{Pair: p, currency: XRP, selling: true, market: true, expectedError: ErrCurrencyNotAssociatedWithPair},
|
|
|
|
{Pair: p, currency: BTC, selling: true, market: true, expectedParams: &OrderParameters{SellingCurrency: BTC, PurchasingCurrency: USDT, IsBuySide: false, IsAskLiquidity: false, Pair: p}},
|
|
{Pair: p, currency: BTC, selling: false, market: true, expectedParams: &OrderParameters{SellingCurrency: USDT, PurchasingCurrency: BTC, IsBuySide: true, IsAskLiquidity: true, Pair: p}},
|
|
{Pair: p, currency: BTC, selling: true, market: false, expectedParams: &OrderParameters{SellingCurrency: BTC, PurchasingCurrency: USDT, IsBuySide: false, IsAskLiquidity: true, Pair: p}},
|
|
{Pair: p, currency: BTC, selling: false, market: false, expectedParams: &OrderParameters{SellingCurrency: USDT, PurchasingCurrency: BTC, IsBuySide: true, IsAskLiquidity: false, Pair: p}},
|
|
|
|
{Pair: p, currency: USDT, selling: true, market: true, expectedParams: &OrderParameters{SellingCurrency: USDT, PurchasingCurrency: BTC, IsBuySide: true, IsAskLiquidity: true, Pair: p}},
|
|
{Pair: p, currency: USDT, selling: false, market: true, expectedParams: &OrderParameters{SellingCurrency: BTC, PurchasingCurrency: USDT, IsBuySide: false, IsAskLiquidity: false, Pair: p}},
|
|
{Pair: p, currency: USDT, selling: true, market: false, expectedParams: &OrderParameters{SellingCurrency: USDT, PurchasingCurrency: BTC, IsBuySide: true, IsAskLiquidity: false, Pair: p}},
|
|
{Pair: p, currency: USDT, selling: false, market: false, expectedParams: &OrderParameters{SellingCurrency: BTC, PurchasingCurrency: USDT, IsBuySide: false, IsAskLiquidity: true, Pair: p}},
|
|
}
|
|
|
|
for i, tc := range testCases {
|
|
tc := tc
|
|
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
|
t.Parallel()
|
|
var resp *OrderParameters
|
|
var err error
|
|
switch {
|
|
case tc.market && tc.selling:
|
|
resp, err = tc.Pair.MarketSellOrderParameters(tc.currency)
|
|
case tc.market && !tc.selling:
|
|
resp, err = tc.Pair.MarketBuyOrderParameters(tc.currency)
|
|
case !tc.market && tc.selling:
|
|
resp, err = tc.Pair.LimitSellOrderParameters(tc.currency)
|
|
case !tc.market && !tc.selling:
|
|
resp, err = tc.Pair.LimitBuyOrderParameters(tc.currency)
|
|
}
|
|
|
|
if !errors.Is(err, tc.expectedError) {
|
|
t.Fatalf("received %v, expected %v", err, tc.expectedError)
|
|
}
|
|
|
|
if tc.expectedParams == nil {
|
|
if resp != nil {
|
|
t.Fatalf("received %v, expected nil", resp)
|
|
}
|
|
return
|
|
}
|
|
|
|
if resp.SellingCurrency != tc.expectedParams.SellingCurrency {
|
|
t.Fatalf("SellingCurrency received %v, expected %v", resp.SellingCurrency, tc.expectedParams.SellingCurrency)
|
|
}
|
|
|
|
if resp.PurchasingCurrency != tc.expectedParams.PurchasingCurrency {
|
|
t.Fatalf("PurchasingCurrency received %v, expected %v", resp.PurchasingCurrency, tc.expectedParams.PurchasingCurrency)
|
|
}
|
|
|
|
if resp.IsBuySide != tc.expectedParams.IsBuySide {
|
|
t.Fatalf("BuySide received %v, expected %v", resp.IsBuySide, tc.expectedParams.IsBuySide)
|
|
}
|
|
|
|
if resp.IsAskLiquidity != tc.expectedParams.IsAskLiquidity {
|
|
t.Fatalf("AskLiquidity received %v, expected %v", resp.IsAskLiquidity, tc.expectedParams.IsAskLiquidity)
|
|
}
|
|
|
|
if resp.Pair != tc.expectedParams.Pair {
|
|
t.Fatalf("Pair received %v, expected %v", resp.Pair, tc.expectedParams.Pair)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsAssociated(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
Pair Pair
|
|
associate Pair
|
|
expectedResult bool
|
|
}{
|
|
{Pair: NewPair(BTC, USDT), associate: NewPair(BTC, USDT), expectedResult: true},
|
|
{Pair: NewPair(USDT, BTC), associate: NewPair(BTC, USDT), expectedResult: true},
|
|
{Pair: NewPair(BTC, USDT), associate: NewPair(USDT, BTC), expectedResult: true},
|
|
{Pair: NewPair(BTC, USDT), associate: NewPair(XRP, USDT), expectedResult: true},
|
|
{Pair: NewPair(BTC, LTC), associate: NewPair(XRP, USDT), expectedResult: false},
|
|
{Pair: NewPair(MA, LTC), associate: NewPair(LTC, USDT), expectedResult: true},
|
|
}
|
|
|
|
for x := range testCases {
|
|
x := x
|
|
t.Run(strconv.Itoa(x), func(t *testing.T) {
|
|
t.Parallel()
|
|
if testCases[x].Pair.IsAssociated(testCases[x].associate) != testCases[x].expectedResult {
|
|
t.Fatalf("Test %d failed. Expected %v, received %v", x, testCases[x].expectedResult, testCases[x].Pair.IsAssociated(testCases[x].associate))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPair_GetFormatting(t *testing.T) {
|
|
t.Parallel()
|
|
p := NewPair(BTC, USDT)
|
|
pFmt, err := p.GetFormatting()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !pFmt.Uppercase || pFmt.Delimiter != "" {
|
|
t.Error("incorrect formatting")
|
|
}
|
|
|
|
p = NewPairWithDelimiter("eth", "usdt", "/")
|
|
pFmt, err = p.GetFormatting()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if pFmt.Uppercase || pFmt.Delimiter != "/" {
|
|
t.Error("incorrect formatting")
|
|
}
|
|
|
|
p = NewPairWithDelimiter("eth", "USDT", "/")
|
|
_, err = p.GetFormatting()
|
|
if !errors.Is(err, errPairFormattingInconsistent) {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestNewBTCUSD(t *testing.T) {
|
|
t.Parallel()
|
|
p := NewBTCUSD()
|
|
if !p.Base.Equal(BTC) {
|
|
t.Fatal("expected base BTC from function NewBTCUSD")
|
|
}
|
|
if !p.Quote.Equal(USD) {
|
|
t.Fatal("expected quote USD from function NewBTCUSD")
|
|
}
|
|
}
|
|
|
|
func TestNewBTCUSDT(t *testing.T) {
|
|
t.Parallel()
|
|
p := NewBTCUSDT()
|
|
if !p.Base.Equal(BTC) {
|
|
t.Fatal("expected base BTC from function NewBTCUSDT")
|
|
}
|
|
if !p.Quote.Equal(USDT) {
|
|
t.Fatal("expected quote USDT from function NewBTCUSDT")
|
|
}
|
|
}
|