mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
* buffer/orderbook: shift orderbook update logic from buffer package to orderbook package * Update exchanges/orderbook/depth.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * linter: fixes * spelling: fix * samboss: add in some todos * sammy nit: add unlock on error * sammy nits: rm ptr to slice field buffer in orderbookHolder * sammy nits: Add more coverage bro * sammy nits: even more coverage * gk: nits on commentary * gk: nits change sort.Slice to slices.SortFunc * gk: fix commentary on buffer clearing * gk: nits fin * linter: fix * Update exchange/websocket/buffer/buffer.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchange/websocket/buffer/buffer.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/tranches.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/orderbook.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchange/websocket/buffer/buffer_test.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchange/websocket/buffer/buffer_test.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/incremental_updates.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * gk: refresh action types and names * gk nits: consolidate error vars and naming * gk nits: more name changes * gk nits; buffer tests update * gk nits: error var names change * linter: FIX * it gets inlined but there is an alloc * rn field in TODO * Update exchanges/binance/binance_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/binance/binance_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * orderbook: shift verify/validate funcs to validate.go and rn Verify() -> Validate() * orderbook: validate even in presence of checksum and allow cowboy mode * buffer; fix test * kraken: fix futures orderbook by reversing incoming bids * okx: change default spread pair * Update exchanges/orderbook/validate.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/validate.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/validate.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/validate.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * Update exchanges/orderbook/validate.go Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> * gk: initial nits * rn fields V(v)erifyorderbook to V(v)alidateOrderbook * buffer/orderbook: nilguard in validate and change method receiver w -> o --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com> Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
375 lines
15 KiB
Go
375 lines
15 KiB
Go
package orderbook
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func newSnapshot(length int) *Book {
|
|
return &Book{
|
|
Bids: newBids(length),
|
|
Asks: newAsks(length, length),
|
|
LastUpdated: time.Now(),
|
|
LastPushed: time.Now(),
|
|
LastUpdateID: 1,
|
|
}
|
|
}
|
|
|
|
func newBids(length int) Levels {
|
|
bids := make(Levels, length)
|
|
for i := range length {
|
|
bids[i] = Level{Price: 1337 - float64(i), Amount: 1, ID: int64(i + 1)}
|
|
}
|
|
return bids
|
|
}
|
|
|
|
func newAsks(idOffset, length int) Levels {
|
|
asks := make(Levels, length)
|
|
for i := range length {
|
|
asks[i] = Level{Price: 1338 + float64(i), Amount: 1, ID: int64(i + 1 + idOffset)}
|
|
}
|
|
return asks
|
|
}
|
|
|
|
func TestProcessUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(69)))
|
|
assert.ErrorIs(t, d.ProcessUpdate(&Update{}), ErrEmptyUpdate)
|
|
assert.ErrorIs(t, d.ProcessUpdate(&Update{AllowEmpty: true}), ErrEmptyUpdate, "exercise validation error return from last ProcessUpdate call which invalidates the orderbook")
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
assert.NoError(t, d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}, SkipOutOfOrderLastUpdateID: true}))
|
|
ob, err := d.Retrieve()
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, int64(69420), ob.Asks[0].ID, "Update above should skip insertion")
|
|
d.options.restSnapshot = true // Simulate the snapshot has been loaded from REST
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}})
|
|
assert.ErrorIs(t, err, errRESTSnapshot)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}})
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{Action: InsertAction, Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}})
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
d.validateOrderbook = true
|
|
d.askLevels.Levels[0].Amount = 0
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}})
|
|
assert.ErrorIs(t, err, errAmountInvalid)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}})
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}, ExpectedChecksum: 1337})
|
|
require.ErrorIs(t, err, errChecksumGeneratorUnset)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}, ExpectedChecksum: 1337, GenerateChecksum: func(*Book) uint32 { return 1336 }})
|
|
require.ErrorIs(t, err, errChecksumMismatch)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}, ExpectedChecksum: 1337, GenerateChecksum: func(*Book) uint32 { return 1337 }})
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
d.askLevels.Levels[0].Amount = 0
|
|
d.validateOrderbook = false // Disable verification
|
|
err = d.ProcessUpdate(&Update{UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 69420, ID: 69420}}, ExpectedChecksum: 1337, GenerateChecksum: func(*Book) uint32 { return 1337 }})
|
|
require.NoError(t, err, "must not error when ValidateOrderbook is false")
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err := d.update(&Update{})
|
|
assert.ErrorIs(t, err, errInvalidAction, "update should error correctly")
|
|
|
|
err = d.update(&Update{Action: UpdateAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1338, Amount: 69420, ID: 69420}}})
|
|
assert.ErrorIs(t, err, errUpdateFailed, "update should error correctly")
|
|
assert.ErrorContains(t, err, "Update")
|
|
err = d.update(&Update{Action: UpdateAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1338, Amount: 69420, ID: 21}}})
|
|
assert.NoError(t, err, "update should not error")
|
|
ob, err := d.Retrieve()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 69420.0, ob.Asks[0].Amount, "First ask amount should be correct")
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.update(&Update{Action: DeleteAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1338, Amount: 1, ID: 69420}}})
|
|
assert.ErrorIs(t, err, errDeleteFailed, "update should error correctly")
|
|
assert.ErrorContains(t, err, "Delete")
|
|
err = d.update(&Update{Action: DeleteAction, UpdateTime: time.Now(), Asks: Levels{{ID: 21}}})
|
|
assert.NoError(t, err, "update should not error")
|
|
ob, err = d.Retrieve()
|
|
require.NoError(t, err)
|
|
assert.NotEqual(t, 21, ob.Asks[0].ID, "Ask element should be deleted")
|
|
assert.Len(t, ob.Asks, 19, "Asks length should be correct")
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.update(&Update{Action: InsertAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1338, Amount: 1, ID: 21}}})
|
|
assert.ErrorIs(t, err, errUpdateFailed, "update should error correctly")
|
|
assert.ErrorContains(t, err, "Insert")
|
|
err = d.update(&Update{Action: InsertAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 1, ID: 69420}}})
|
|
assert.NoError(t, err, "update should not error")
|
|
ob, err = d.Retrieve()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(69420), ob.Asks[0].ID, "First ask ID should be correct")
|
|
|
|
require.NoError(t, d.LoadSnapshot(newSnapshot(20)))
|
|
err = d.update(&Update{Action: UpdateOrInsertAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1338, Amount: 0, ID: 21}}})
|
|
assert.ErrorIs(t, err, errUpdateFailed, "update should error correctly")
|
|
assert.ErrorContains(t, err, "UpdateOrInsert")
|
|
err = d.update(&Update{Action: UpdateOrInsertAction, UpdateTime: time.Now(), Asks: Levels{{Price: 1337.5, Amount: 1, ID: 69420}}})
|
|
assert.NoError(t, err, "update should not error")
|
|
ob, err = d.Retrieve()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(69420), ob.Asks[0].ID, "First ask ID should be correct")
|
|
}
|
|
|
|
func TestUpdateBidAskByID(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
err := d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates := &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 1}},
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 2}},
|
|
}
|
|
|
|
err = d.updateBidAskByID(updates)
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet, "UpdateBidAskByID should error correctly")
|
|
|
|
updates.UpdateTime = time.Now()
|
|
err = d.updateBidAskByID(updates)
|
|
assert.NoError(t, err, "UpdateBidAskByID should not error")
|
|
|
|
ob, err := d.Retrieve()
|
|
assert.NoError(t, err, "Retrieve should not error")
|
|
assert.Equal(t, 2.0, ob.Asks[0].Amount, "First ask amount should be correct")
|
|
assert.Equal(t, 2.0, ob.Bids[0].Amount, "First bid amount should be correct")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 666}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
// random unmatching IDs
|
|
err = d.updateBidAskByID(updates)
|
|
assert.ErrorIs(t, err, errIDCannotBeMatched, "UpdateBidAskByID should error correctly")
|
|
|
|
updates = &Update{
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 69}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.updateBidAskByID(updates)
|
|
assert.ErrorIs(t, err, errIDCannotBeMatched, "UpdateBidAskByID should error correctly")
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
err := d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates := &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 1}},
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 2}},
|
|
}
|
|
|
|
err = d.delete(updates, false)
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet, "delete should error correctly")
|
|
|
|
updates.UpdateTime = time.Now()
|
|
err = d.delete(updates, false)
|
|
assert.NoError(t, err, "delete should not error")
|
|
|
|
ob, err := d.Retrieve()
|
|
assert.NoError(t, err, "Retrieve should not error")
|
|
assert.Empty(t, ob.Asks, "Asks should be empty")
|
|
assert.Empty(t, ob.Bids, "Bids should be empty")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 1}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.delete(updates, false)
|
|
assert.ErrorIs(t, err, errIDCannotBeMatched, "delete should error correctly")
|
|
|
|
updates = &Update{
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 2}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.delete(updates, false)
|
|
assert.ErrorIs(t, err, errIDCannotBeMatched, "delete should error correctly")
|
|
|
|
updates = &Update{
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 2}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.delete(updates, true)
|
|
assert.NoError(t, err, "delete should not error")
|
|
}
|
|
|
|
func TestInsert(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
err := d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates := &Update{
|
|
Asks: Levels{{Price: 1337, Amount: 2, ID: 3}},
|
|
}
|
|
err = d.insert(updates)
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet, "insert should error correctly")
|
|
|
|
updates.UpdateTime = time.Now()
|
|
|
|
err = d.insert(updates)
|
|
assert.ErrorIs(t, err, errCollisionDetected, "insert should error correctly on collision")
|
|
|
|
err = d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 3}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
|
|
err = d.insert(updates)
|
|
assert.ErrorIs(t, err, errCollisionDetected, "insert should error correctly on collision")
|
|
|
|
err = d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1338, Amount: 2, ID: 3}},
|
|
Asks: Levels{{Price: 1336, Amount: 2, ID: 4}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.insert(updates)
|
|
assert.NoError(t, err, "InsertBidAskByID should not error")
|
|
|
|
ob, err := d.Retrieve()
|
|
assert.NoError(t, err, "Retrieve should not error")
|
|
assert.Len(t, ob.Asks, 2, "Should have correct Asks")
|
|
assert.Len(t, ob.Bids, 2, "Should have correct Bids")
|
|
}
|
|
|
|
func TestUpdateOrInsert(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
err := d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates := &Update{
|
|
Bids: Levels{{Price: 1338, Amount: 0, ID: 3}},
|
|
Asks: Levels{{Price: 1336, Amount: 2, ID: 4}},
|
|
}
|
|
err = d.updateOrInsert(updates)
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet, "updateOrInsert should error correctly")
|
|
|
|
updates.UpdateTime = time.Now()
|
|
err = d.updateOrInsert(updates)
|
|
assert.ErrorIs(t, err, errAmountCannotBeLessOrEqualToZero, "updateOrInsert should error correctly")
|
|
|
|
err = d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1338, Amount: 2, ID: 3}},
|
|
Asks: Levels{{Price: 1336, Amount: 0, ID: 4}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.updateOrInsert(updates)
|
|
assert.ErrorIs(t, err, errAmountCannotBeLessOrEqualToZero, "updateOrInsert should error correctly")
|
|
|
|
err = d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1337, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1338, Amount: 2, ID: 3}},
|
|
Asks: Levels{{Price: 1336, Amount: 2, ID: 4}},
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.updateOrInsert(updates)
|
|
assert.NoError(t, err, "updateOrInsert should not error")
|
|
|
|
ob, err := d.Retrieve()
|
|
assert.NoError(t, err, "Retrieve should not error")
|
|
assert.Len(t, ob.Asks, 2, "Should have correct Asks")
|
|
assert.Len(t, ob.Bids, 2, "Should have correct Bids")
|
|
}
|
|
|
|
func TestUpdateBidAskByPrice(t *testing.T) {
|
|
t.Parallel()
|
|
d := NewDepth(id)
|
|
err := d.LoadSnapshot(&Book{Bids: Levels{{Price: 1337, Amount: 1, ID: 1}}, Asks: Levels{{Price: 1338, Amount: 10, ID: 2}}, LastUpdated: time.Now(), LastPushed: time.Now()})
|
|
assert.NoError(t, err, "LoadSnapshot should not error")
|
|
|
|
err = d.updateBidAskByPrice(&Update{})
|
|
assert.ErrorIs(t, err, ErrLastUpdatedNotSet, "UpdateBidAskByPrice should error correctly")
|
|
|
|
err = d.updateBidAskByPrice(&Update{UpdateTime: time.Now()})
|
|
assert.NoError(t, err, "UpdateBidAskByPrice should not error")
|
|
|
|
updates := &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 2, ID: 1}},
|
|
Asks: Levels{{Price: 1338, Amount: 3, ID: 2}},
|
|
UpdateID: 1,
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.updateBidAskByPrice(updates)
|
|
assert.NoError(t, err, "UpdateBidAskByPrice should not error")
|
|
|
|
ob, err := d.Retrieve()
|
|
assert.NoError(t, err, "Retrieve should not error")
|
|
assert.Equal(t, 3.0, ob.Asks[0].Amount, "Asks amount should be correct")
|
|
assert.Equal(t, 2.0, ob.Bids[0].Amount, "Bids amount should be correct")
|
|
|
|
updates = &Update{
|
|
Bids: Levels{{Price: 1337, Amount: 0, ID: 1}},
|
|
Asks: Levels{{Price: 1338, Amount: 0, ID: 2}},
|
|
UpdateID: 2,
|
|
UpdateTime: time.Now(),
|
|
}
|
|
err = d.updateBidAskByPrice(updates)
|
|
assert.NoError(t, err, "UpdateBidAskByPrice should not error")
|
|
|
|
askLen, err := d.GetAskLength()
|
|
assert.NoError(t, err, "GetAskLength should not error")
|
|
assert.Zero(t, askLen, "Ask Length should be correct")
|
|
|
|
bidLen, err := d.GetBidLength()
|
|
assert.NoError(t, err, "GetBidLength should not error")
|
|
assert.Zero(t, bidLen, "Bid Length should be correct")
|
|
}
|
|
|
|
func TestString(t *testing.T) {
|
|
t.Parallel()
|
|
for _, tc := range []struct {
|
|
action ActionType
|
|
expected string
|
|
}{
|
|
{action: UpdateAction, expected: "Update"},
|
|
{action: InsertAction, expected: "Insert"},
|
|
{action: UpdateOrInsertAction, expected: "UpdateOrInsert"},
|
|
{action: DeleteAction, expected: "Delete"},
|
|
{action: UnknownAction, expected: "Unknown"},
|
|
{action: ActionType(69), expected: "Unknown(69)"},
|
|
} {
|
|
t.Run(tc.expected, func(t *testing.T) {
|
|
t.Parallel()
|
|
assert.Equal(t, tc.expected, tc.action.String(), "String representation should match")
|
|
})
|
|
}
|
|
}
|