From 4de4e3dc14eb83eeed0a109cff3374bf02048d90 Mon Sep 17 00:00:00 2001 From: Ryan O'Hara-Reid Date: Mon, 11 Nov 2024 14:46:14 +1100 Subject: [PATCH] stream/buffer: Improve orderbook verification conditions and fix TestUpdateByIDAndAction test (#1682) * don't need to verify if checksum available; don't retroactively verify snapshots * glorious: nits + allow checksum/validation to be done on updateByIDAndAction * possible slice manipulation issue fix for test * thrasher: nit * this should fix it now * for subsystem usage disallow deploying a book twice * reverts strict policy using deploy, it's used in a bunch of tests I don't want to touch just yet, left a note * rm unused variable * glorious: nits --------- Co-authored-by: Ryan O'Hara-Reid --- exchanges/orderbook/orderbook.go | 17 +- exchanges/orderbook/orderbook_test.go | 27 +- exchanges/stream/buffer/buffer.go | 61 +- exchanges/stream/buffer/buffer_test.go | 824 +++++++++---------------- 4 files changed, 346 insertions(+), 583 deletions(-) diff --git a/exchanges/orderbook/orderbook.go b/exchanges/orderbook/orderbook.go index 540180be..5773864f 100644 --- a/exchanges/orderbook/orderbook.go +++ b/exchanges/orderbook/orderbook.go @@ -79,8 +79,7 @@ func (s *Service) Update(b *Base) error { return s.Mux.Publish(book, m1.ID) } -// DeployDepth used for subsystem deployment creates a depth item in the struct -// then returns a ptr to that Depth item +// DeployDepth used for subsystem deployment creates a depth item in the struct then returns a ptr to that Depth item func (s *Service) DeployDepth(exchange string, p currency.Pair, a asset.Item) (*Depth, error) { if exchange == "" { return nil, errExchangeNameUnset @@ -112,13 +111,15 @@ func (s *Service) DeployDepth(exchange string, p currency.Pair, a asset.Item) (* s.books[strings.ToLower(exchange)] = m1 } book, ok := m1.m[mapKey] - if !ok { - book = NewDepth(m1.ID) - book.exchange = exchange - book.pair = p - book.asset = a - m1.m[mapKey] = book + if ok { + // Maybe in future we should return an error here and be more strict. + return book, nil } + book = NewDepth(m1.ID) + book.exchange = exchange + book.pair = p + book.asset = a + m1.m[mapKey] = book return book, nil } diff --git a/exchanges/orderbook/orderbook_test.go b/exchanges/orderbook/orderbook_test.go index 33b7d5a2..127393b6 100644 --- a/exchanges/orderbook/orderbook_test.go +++ b/exchanges/orderbook/orderbook_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/dispatch" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -321,28 +322,18 @@ func TestBaseGetDepth(t *testing.T) { func TestDeployDepth(t *testing.T) { c, err := currency.NewPairFromStrings("BTC", "USD") - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) _, err = DeployDepth("", c, asset.Spot) - if !errors.Is(err, errExchangeNameUnset) { - t.Fatalf("expecting %s error but received %v", errExchangeNameUnset, err) - } + require.ErrorIs(t, err, errExchangeNameUnset) _, err = DeployDepth("test", currency.EMPTYPAIR, asset.Spot) - if !errors.Is(err, errPairNotSet) { - t.Fatalf("expecting %s error but received %v", errPairNotSet, err) - } + require.ErrorIs(t, err, errPairNotSet) _, err = DeployDepth("test", c, asset.Empty) - if !errors.Is(err, errAssetTypeNotSet) { - t.Fatalf("expecting %s error but received %v", errAssetTypeNotSet, err) - } + require.ErrorIs(t, err, errAssetTypeNotSet) d, err := DeployDepth("test", c, asset.Spot) - if err != nil { - t.Fatal(err) - } - if d == nil { - t.Fatal("depth ptr shall not be nill") - } + require.NoError(t, err) + require.NotNil(t, d) + _, err = DeployDepth("test", c, asset.Spot) + require.NoError(t, err) } func TestCreateNewOrderbook(t *testing.T) { diff --git a/exchanges/stream/buffer/buffer.go b/exchanges/stream/buffer/buffer.go index 27d707b5..8294c3fb 100644 --- a/exchanges/stream/buffer/buffer.go +++ b/exchanges/stream/buffer/buffer.go @@ -170,20 +170,6 @@ func (w *Orderbook) Update(u *orderbook.Update) error { } } - var ret *orderbook.Base - if book.ob.VerifyOrderbook() { - // This is used here so as to not retrieve book if verification is off. - // On every update, this will retrieve and verify orderbook depth. - ret, err = book.ob.Retrieve() - if err != nil { - return err - } - err = ret.Verify() - if err != nil { - return book.ob.Invalidate(err) - } - } - // Publish all state changes, disregarding verbosity or sync requirements. book.ob.Publish() @@ -240,15 +226,17 @@ func (w *Orderbook) processBufferUpdate(o *orderbookHolder, u *orderbook.Update) return true, nil } -// processObUpdate processes updates either by its corresponding id or by -// price level +// processObUpdate processes updates either by its corresponding id or by price level func (w *Orderbook) processObUpdate(o *orderbookHolder, u *orderbook.Update) error { + // Both update methods require post processing to ensure the orderbook is in a valid state. if w.updateEntriesByID { - return o.updateByIDAndAction(u) - } - err := o.updateByPrice(u) - if err != nil { - return err + if err := o.updateByIDAndAction(u); err != nil { + return err + } + } else { + if err := o.updateByPrice(u); err != nil { + return err + } } if w.checksum != nil { compare, err := o.ob.Retrieve() @@ -260,6 +248,15 @@ func (w *Orderbook) processObUpdate(o *orderbookHolder, u *orderbook.Update) err return o.ob.Invalidate(err) } o.updateID = u.UpdateID + } else if o.ob.VerifyOrderbook() { + compare, err := o.ob.Retrieve() + if err != nil { + return err + } + err = compare.Verify() + if err != nil { + return o.ob.Invalidate(err) + } } return nil } @@ -277,24 +274,24 @@ func (o *orderbookHolder) updateByIDAndAction(updts *orderbook.Update) error { case orderbook.Amend: err := o.ob.UpdateBidAskByID(updts) if err != nil { - return fmt.Errorf("%v %w", errAmendFailure, err) + return fmt.Errorf("%w %w", errAmendFailure, err) } case orderbook.Delete: // edge case for Bitfinex as their streaming endpoint duplicates deletes bypassErr := o.ob.GetName() == "Bitfinex" && o.ob.IsFundingRate() err := o.ob.DeleteBidAskByID(updts, bypassErr) if err != nil { - return fmt.Errorf("%v %w", errDeleteFailure, err) + return fmt.Errorf("%w %w", errDeleteFailure, err) } case orderbook.Insert: err := o.ob.InsertBidAskByID(updts) if err != nil { - return fmt.Errorf("%v %w", errInsertFailure, err) + return fmt.Errorf("%w %w", errInsertFailure, err) } case orderbook.UpdateInsert: err := o.ob.UpdateInsertByID(updts) if err != nil { - return fmt.Errorf("%v %w", errUpdateInsertFailure, err) + return fmt.Errorf("%w %w", errUpdateInsertFailure, err) } default: return fmt.Errorf("%w [%d]", errInvalidAction, updts.Action) @@ -338,20 +335,6 @@ func (w *Orderbook) LoadSnapshot(book *orderbook.Base) error { return err } - if holder.ob.VerifyOrderbook() { - // This is used here so as to not retrieve book if verification is off. - // Checks to see if orderbook snapshot that was deployed has not been - // altered in any way - book, err = holder.ob.Retrieve() - if err != nil { - return err - } - err = book.Verify() - if err != nil { - return holder.ob.Invalidate(err) - } - } - holder.ob.Publish() w.dataHandler <- holder.ob return nil diff --git a/exchanges/stream/buffer/buffer_test.go b/exchanges/stream/buffer/buffer_test.go index 47f0b6d7..4b3b9a88 100644 --- a/exchanges/stream/buffer/buffer_test.go +++ b/exchanges/stream/buffer/buffer_test.go @@ -3,10 +3,14 @@ package buffer import ( "errors" "math/rand" - "strings" + "slices" + "strconv" "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/key" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" @@ -23,15 +27,17 @@ var ( {{Price: 4000, Amount: 0, ID: 6000}}, {{Price: 5000, Amount: 1, ID: 5000}}, } - - cp, _ = currency.NewPairFromString("BTCUSD") + offset = common.Counter{} ) -const ( - exchangeName = "exchangeTest" -) +const exchangeName = "exchangeTest" -func createSnapshot() (holder *Orderbook, asks, bids orderbook.Tranches, err error) { +// getExclusivePair returns a currency pair with a unique ID for testing as books are centralised and changes will affect other tests +func getExclusivePair() (currency.Pair, error) { + return currency.NewPairFromStrings(currency.BTC.String(), currency.USDT.String()+strconv.FormatInt(offset.IncrementAndGet(), 10)) +} + +func createSnapshot(pair currency.Pair, bookVerifiy ...bool) (holder *Orderbook, asks, bids orderbook.Tranches, err error) { asks = orderbook.Tranches{{Price: 4000, Amount: 1, ID: 6}} bids = orderbook.Tranches{{Price: 4000, Amount: 1, ID: 6}} @@ -40,9 +46,10 @@ func createSnapshot() (holder *Orderbook, asks, bids orderbook.Tranches, err err Asks: asks, Bids: bids, Asset: asset.Spot, - Pair: cp, + Pair: pair, PriceDuplication: true, LastUpdated: time.Now(), + VerifyOrderbook: len(bookVerifiy) > 0 && bookVerifiy[0], } newBook := make(map[key.PairAsset]*orderbookHolder) @@ -79,10 +86,12 @@ func bidAskGenerator() []orderbook.Tranche { } func BenchmarkUpdateBidsByPrice(b *testing.B) { - ob, _, _, err := createSnapshot() - if err != nil { - b.Error(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + ob, _, _, err := createSnapshot(cp) + require.NoError(b, err) + b.ResetTimer() for i := 0; i < b.N; i++ { bidAsks := bidAskGenerator() @@ -94,18 +103,17 @@ func BenchmarkUpdateBidsByPrice(b *testing.B) { Asset: asset.Spot, } holder := ob.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] - err = holder.updateByPrice(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, holder.updateByPrice(update)) } } func BenchmarkUpdateAsksByPrice(b *testing.B) { - ob, _, _, err := createSnapshot() - if err != nil { - b.Error(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + ob, _, _, err := createSnapshot(cp) + require.NoError(b, err) + b.ResetTimer() for i := 0; i < b.N; i++ { bidAsks := bidAskGenerator() @@ -117,10 +125,7 @@ func BenchmarkUpdateAsksByPrice(b *testing.B) { Asset: asset.Spot, } holder := ob.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] - err = holder.updateByPrice(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, holder.updateByPrice(update)) } } @@ -128,10 +133,12 @@ func BenchmarkUpdateAsksByPrice(b *testing.B) { // process calls // 890016 1688 ns/op 416 B/op 3 allocs/op func BenchmarkBufferPerformance(b *testing.B) { - holder, asks, bids, err := createSnapshot() - if err != nil { - b.Fatal(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + holder, asks, bids, err := createSnapshot(cp) + require.NoError(b, err) + holder.bufferEnabled = true update := &orderbook.Update{ Bids: bids, @@ -145,10 +152,7 @@ func BenchmarkBufferPerformance(b *testing.B) { randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] - err = holder.Update(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, holder.Update(update)) } } @@ -156,10 +160,12 @@ func BenchmarkBufferPerformance(b *testing.B) { // // 613964 2093 ns/op 440 B/op 4 allocs/op func BenchmarkBufferSortingPerformance(b *testing.B) { - holder, asks, bids, err := createSnapshot() - if err != nil { - b.Fatal(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + holder, asks, bids, err := createSnapshot(cp) + require.NoError(b, err) + holder.bufferEnabled = true holder.sortBuffer = true update := &orderbook.Update{ @@ -174,20 +180,19 @@ func BenchmarkBufferSortingPerformance(b *testing.B) { randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] - err = holder.Update(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, holder.Update(update)) } } // BenchmarkBufferSortingPerformance benchmark // 914500 1599 ns/op 440 B/op 4 allocs/op func BenchmarkBufferSortingByIDPerformance(b *testing.B) { - holder, asks, bids, err := createSnapshot() - if err != nil { - b.Fatal(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + holder, asks, bids, err := createSnapshot(cp) + require.NoError(b, err) + holder.bufferEnabled = true holder.sortBuffer = true holder.sortBufferByUpdateIDs = true @@ -203,10 +208,7 @@ func BenchmarkBufferSortingByIDPerformance(b *testing.B) { randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] - err = holder.Update(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, holder.Update(update)) } } @@ -216,10 +218,12 @@ func BenchmarkBufferSortingByIDPerformance(b *testing.B) { // 1225924 1028 ns/op 240 B/op 2 allocs/op CURRENT func BenchmarkNoBufferPerformance(b *testing.B) { - obl, asks, bids, err := createSnapshot() - if err != nil { - b.Fatal(err) - } + cp, err := getExclusivePair() + require.NoError(b, err) + + obl, asks, bids, err := createSnapshot(cp) + require.NoError(b, err) + update := &orderbook.Update{ Bids: bids, Asks: asks, @@ -233,18 +237,17 @@ func BenchmarkNoBufferPerformance(b *testing.B) { randomIndex := rand.Intn(4) //nolint:gosec // no need to import crypo/rand for testing update.Asks = itemArray[randomIndex] update.Bids = itemArray[randomIndex] - err = obl.Update(update) - if err != nil { - b.Fatal(err) - } + require.NoError(b, obl.Update(update)) } } func TestUpdates(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Error(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] err = book.updateByPrice(&orderbook.Update{ @@ -254,9 +257,7 @@ func TestUpdates(t *testing.T) { UpdateTime: time.Now(), Asset: asset.Spot, }) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) err = book.updateByPrice(&orderbook.Update{ Bids: itemArray[0], @@ -265,26 +266,22 @@ func TestUpdates(t *testing.T) { UpdateTime: time.Now(), Asset: asset.Spot, }) - if err != nil { - t.Error(err) - } + assert.NoError(t, err) askLen, err := book.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if askLen != 3 { - t.Error("Did not update") - } + require.NoError(t, err) + assert.Equal(t, 3, askLen) } // TestHittingTheBuffer logic test func TestHittingTheBuffer(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + holder.bufferEnabled = true holder.obBufferLimit = 5 for i := range itemArray { @@ -297,37 +294,28 @@ func TestHittingTheBuffer(t *testing.T) { UpdateTime: time.Now(), Asset: asset.Spot, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] askLen, err := book.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if askLen != 3 { - t.Errorf("expected 3 entries, received: %v", askLen) - } + require.NoError(t, err) + assert.Equal(t, 3, askLen) bidLen, err := book.ob.GetBidLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if bidLen != 3 { - t.Errorf("expected 3 entries, received: %v", bidLen) - } + require.NoError(t, err) + assert.Equal(t, 3, bidLen) } // TestInsertWithIDs logic test func TestInsertWithIDs(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + holder.bufferEnabled = true holder.updateEntriesByID = true holder.obBufferLimit = 5 @@ -345,35 +333,44 @@ func TestInsertWithIDs(t *testing.T) { Asset: asset.Spot, Action: orderbook.UpdateInsert, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] askLen, err := book.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - if askLen != 6 { - t.Errorf("expected 6 entries, received: %v", askLen) - } + require.NoError(t, err) + assert.Equal(t, 6, askLen) bidLen, err := book.ob.GetBidLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - if bidLen != 6 { - t.Errorf("expected 6 entries, received: %v", bidLen) - } + require.NoError(t, err) + assert.Equal(t, 6, bidLen) + + cp, err = getExclusivePair() + require.NoError(t, err) + + holder, _, _, err = createSnapshot(cp, true) + require.NoError(t, err) + + holder.checksum = nil + holder.updateIDProgression = false + err = holder.Update(&orderbook.Update{ + UpdateTime: time.Now(), + Asset: asset.Spot, + Asks: []orderbook.Tranche{{Price: 999999}}, + Pair: cp, + }) + require.NoError(t, err) } // TestSortIDs logic test func TestSortIDs(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + holder.bufferEnabled = true holder.sortBufferByUpdateIDs = true holder.sortBuffer = true @@ -389,39 +386,30 @@ func TestSortIDs(t *testing.T) { Asset: asset.Spot, UpdateTime: time.Now(), }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] askLen, err := book.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - if askLen != 3 { - t.Errorf("expected 3 entries, received: %v", askLen) - } + require.NoError(t, err) + assert.Equal(t, 3, askLen) bidLen, err := book.ob.GetBidLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - if bidLen != 3 { - t.Errorf("expected 3 entries, received: %v", bidLen) - } + require.NoError(t, err) + assert.Equal(t, 3, bidLen) } // TestOutOfOrderIDs logic test func TestOutOfOrderIDs(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + outOFOrderIDs := []int64{2, 1, 5, 3, 4, 6, 7} - if itemArray[0][0].Price != 1000 { - t.Errorf("expected sorted price to be 3000, received: %v", - itemArray[1][0].Price) - } + assert.Equal(t, 1000., itemArray[0][0].Price) + holder.bufferEnabled = true holder.sortBuffer = true holder.obBufferLimit = 5 @@ -434,30 +422,24 @@ func TestOutOfOrderIDs(t *testing.T) { Asset: asset.Spot, UpdateTime: time.Now(), }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] cpy, err := book.ob.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) // Index 1 since index 0 is price 7000 - if cpy.Asks[1].Price != 2000 { - t.Errorf("expected sorted price to be 2000, received: %v", cpy.Asks[1].Price) - } + assert.Equal(t, 2000., cpy.Asks[1].Price) } func TestOrderbookLastUpdateID(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } - if exp := float64(1000); itemArray[0][0].Price != exp { - t.Errorf("expected sorted price to be %f, received: %v", - exp, itemArray[1][0].Price) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + + assert.Equal(t, 1000., itemArray[0][0].Price) holder.checksum = func(*orderbook.Base, uint32) error { return errors.New("testerino") } @@ -469,14 +451,13 @@ func TestOrderbookLastUpdateID(t *testing.T) { Asset: asset.Spot, UpdateTime: time.Now(), }) - if !errors.Is(err, orderbook.ErrOrderbookInvalid) { - t.Fatalf("received: %v but expected: %v", err, orderbook.ErrOrderbookInvalid) - } + require.ErrorIs(t, err, orderbook.ErrOrderbookInvalid) - holder, _, _, err = createSnapshot() - if err != nil { - t.Fatal(err) - } + cp, err = getExclusivePair() + require.NoError(t, err) + + holder, _, _, err = createSnapshot(cp) + require.NoError(t, err) holder.checksum = func(*orderbook.Base, uint32) error { return nil } holder.updateIDProgression = true @@ -490,9 +471,7 @@ func TestOrderbookLastUpdateID(t *testing.T) { Asset: asset.Spot, UpdateTime: time.Now(), }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } // out of order @@ -502,63 +481,57 @@ func TestOrderbookLastUpdateID(t *testing.T) { UpdateID: 1, Asset: asset.Spot, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ob, err := holder.GetOrderbook(cp, asset.Spot) - if err != nil { - t.Fatal(err) - } - if exp := len(itemArray); ob.LastUpdateID != int64(exp) { - t.Errorf("expected last update id to be %d, received: %v", exp, ob.LastUpdateID) - } + require.NoError(t, err) + assert.Equal(t, int64(len(itemArray)), ob.LastUpdateID) } // TestRunUpdateWithoutSnapshot logic test func TestRunUpdateWithoutSnapshot(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + var holder Orderbook - asks := []orderbook.Tranche{ - {Price: 4000, Amount: 1, ID: 8}, - } - bids := []orderbook.Tranche{ - {Price: 5999, Amount: 1, ID: 8}, - {Price: 4000, Amount: 1, ID: 9}, - } + asks := []orderbook.Tranche{{Price: 4000, Amount: 1, ID: 8}} + bids := []orderbook.Tranche{{Price: 5999, Amount: 1, ID: 8}, {Price: 4000, Amount: 1, ID: 9}} holder.exchangeName = exchangeName - err := holder.Update(&orderbook.Update{ + err = holder.Update(&orderbook.Update{ Bids: bids, Asks: asks, Pair: cp, UpdateTime: time.Now(), Asset: asset.Spot, }) - if !errors.Is(err, errDepthNotFound) { - t.Fatalf("expected %v but received %v", errDepthNotFound, err) - } + require.ErrorIs(t, err, errDepthNotFound) } // TestRunUpdateWithoutAnyUpdates logic test func TestRunUpdateWithoutAnyUpdates(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + var obl Orderbook obl.exchangeName = exchangeName - err := obl.Update(&orderbook.Update{ + err = obl.Update(&orderbook.Update{ Bids: []orderbook.Tranche{}, Asks: []orderbook.Tranche{}, Pair: cp, UpdateTime: time.Now(), Asset: asset.Spot, }) - if !errors.Is(err, errUpdateNoTargets) { - t.Fatalf("expected %v but received %v", errUpdateNoTargets, err) - } + require.ErrorIs(t, err, errUpdateNoTargets) } // TestRunSnapshotWithNoData logic test func TestRunSnapshotWithNoData(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + var obl Orderbook obl.ob = make(map[key.PairAsset]*orderbookHolder) obl.dataHandler = make(chan interface{}, 1) @@ -568,55 +541,50 @@ func TestRunSnapshotWithNoData(t *testing.T) { snapShot1.Exchange = "test" obl.exchangeName = "test" snapShot1.LastUpdated = time.Now() - err := obl.LoadSnapshot(&snapShot1) - if err != nil { - t.Fatal(err) - } + require.NoError(t, obl.LoadSnapshot(&snapShot1)) } // TestLoadSnapshot logic test func TestLoadSnapshot(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + var obl Orderbook obl.dataHandler = make(chan interface{}, 100) obl.ob = make(map[key.PairAsset]*orderbookHolder) var snapShot1 orderbook.Base snapShot1.Exchange = "SnapshotWithOverride" - asks := []orderbook.Tranche{ - {Price: 4000, Amount: 1, ID: 8}, - } - bids := []orderbook.Tranche{ - {Price: 4000, Amount: 1, ID: 9}, - } + asks := []orderbook.Tranche{{Price: 4000, Amount: 1, ID: 8}} + bids := []orderbook.Tranche{{Price: 4000, Amount: 1, ID: 9}} snapShot1.Asks = asks snapShot1.Bids = bids snapShot1.Asset = asset.Spot snapShot1.Pair = cp snapShot1.LastUpdated = time.Now() - err := obl.LoadSnapshot(&snapShot1) - if err != nil { - t.Error(err) - } + require.NoError(t, obl.LoadSnapshot(&snapShot1)) } // TestFlushBuffer logic test func TestFlushBuffer(t *testing.T) { - obl, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } - if obl.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] == nil { - t.Error("expected ob to have ask entries") - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + obl, _, _, err := createSnapshot(cp) + require.NoError(t, err) + + assert.NotEmpty(t, obl.ob) obl.FlushBuffer() - if obl.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] != nil { - t.Error("expected ob be flushed") - } + assert.Empty(t, obl.ob) } // TestInsertingSnapShots logic test func TestInsertingSnapShots(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + var holder Orderbook holder.dataHandler = make(chan interface{}, 100) holder.ob = make(map[key.PairAsset]*orderbookHolder) @@ -655,10 +623,8 @@ func TestInsertingSnapShots(t *testing.T) { snapShot1.Asset = asset.Spot snapShot1.Pair = cp snapShot1.LastUpdated = time.Now() - err := holder.LoadSnapshot(&snapShot1) - if err != nil { - t.Fatal(err) - } + require.NoError(t, holder.LoadSnapshot(&snapShot1)) + var snapShot2 orderbook.Base snapShot2.Exchange = "WSORDERBOOKTEST2" asks = []orderbook.Tranche{ @@ -694,15 +660,12 @@ func TestInsertingSnapShots(t *testing.T) { snapShot2.Bids = bids snapShot2.Bids.SortBids() snapShot2.Asset = asset.Spot - snapShot2.Pair, err = currency.NewPairFromString("LTCUSD") - if err != nil { - t.Fatal(err) - } + snapShot2.Pair, err = getExclusivePair() + require.NoError(t, err) + snapShot2.LastUpdated = time.Now() - err = holder.LoadSnapshot(&snapShot2) - if err != nil { - t.Fatal(err) - } + require.NoError(t, holder.LoadSnapshot(&snapShot2)) + var snapShot3 orderbook.Base snapShot3.Exchange = "WSORDERBOOKTEST3" asks = []orderbook.Tranche{ @@ -738,67 +701,46 @@ func TestInsertingSnapShots(t *testing.T) { snapShot3.Bids = bids snapShot3.Bids.SortBids() snapShot3.Asset = asset.Futures - snapShot3.Pair, err = currency.NewPairFromString("LTCUSD") - if err != nil { - t.Fatal(err) - } + snapShot3.Pair, err = getExclusivePair() + require.NoError(t, err) + snapShot3.LastUpdated = time.Now() - err = holder.LoadSnapshot(&snapShot3) - if err != nil { - t.Fatal(err) - } + require.NoError(t, holder.LoadSnapshot(&snapShot3)) + ob, err := holder.GetOrderbook(snapShot1.Pair, snapShot1.Asset) - if err != nil { - t.Fatal(err) - } - if ob.Asks[0] != snapShot1.Asks[0] { - t.Errorf("loaded data mismatch. Expected %v, received %v", - snapShot1.Asks[0], - ob.Asks[0]) - } + require.NoError(t, err) + assert.Equal(t, snapShot1.Asks[0], ob.Asks[0]) + ob, err = holder.GetOrderbook(snapShot2.Pair, snapShot2.Asset) - if err != nil { - t.Fatal(err) - } - if ob.Asks[0] != snapShot2.Asks[0] { - t.Errorf("loaded data mismatch. Expected %v, received %v", - snapShot2.Asks[0], - ob.Asks[0]) - } + require.NoError(t, err) + assert.Equal(t, snapShot2.Asks[0], ob.Asks[0]) + ob, err = holder.GetOrderbook(snapShot3.Pair, snapShot3.Asset) - if err != nil { - t.Fatal(err) - } - if ob.Asks[0] != snapShot3.Asks[0] { - t.Errorf("loaded data mismatch. Expected %v, received %v", - snapShot3.Asks[0], - ob.Asks[0]) - } + require.NoError(t, err) + assert.Equal(t, snapShot3.Asks[0], ob.Asks[0]) } func TestGetOrderbook(t *testing.T) { - holder, _, _, err := createSnapshot() - if err != nil { - t.Fatal(err) - } + t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) + ob, err := holder.GetOrderbook(cp, asset.Spot) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + bufferOb := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] b, err := bufferOb.ob.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) + askLen, err := bufferOb.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) bidLen, err := bufferOb.ob.GetBidLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) + if askLen != len(ob.Asks) || bidLen != len(ob.Bids) || b.Asset != ob.Asset || @@ -814,27 +756,19 @@ func TestSetup(t *testing.T) { t.Parallel() w := Orderbook{} err := w.Setup(nil, nil, nil) - if !errors.Is(err, errExchangeConfigNil) { - t.Fatalf("expected error %v but received %v", errExchangeConfigNil, err) - } + require.ErrorIs(t, err, errExchangeConfigNil) exchangeConfig := &config.Exchange{} err = w.Setup(exchangeConfig, nil, nil) - if !errors.Is(err, errBufferConfigNil) { - t.Fatalf("expected error %v but received %v", errBufferConfigNil, err) - } + require.ErrorIs(t, err, errBufferConfigNil) bufferConf := &Config{} err = w.Setup(exchangeConfig, bufferConf, nil) - if !errors.Is(err, errUnsetDataHandler) { - t.Fatalf("expected error %v but received %v", errUnsetDataHandler, err) - } + require.ErrorIs(t, err, errUnsetDataHandler) exchangeConfig.Orderbook.WebsocketBufferEnabled = true err = w.Setup(exchangeConfig, bufferConf, make(chan interface{})) - if !errors.Is(err, errIssueBufferEnabledButNoLimit) { - t.Fatalf("expected error %v but received %v", errIssueBufferEnabledButNoLimit, err) - } + require.ErrorIs(t, err, errIssueBufferEnabledButNoLimit) exchangeConfig.Orderbook.WebsocketBufferLimit = 1337 exchangeConfig.Orderbook.WebsocketBufferEnabled = true @@ -843,9 +777,8 @@ func TestSetup(t *testing.T) { bufferConf.SortBufferByUpdateIDs = true bufferConf.UpdateEntriesByID = true err = w.Setup(exchangeConfig, bufferConf, make(chan interface{})) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + if w.obBufferLimit != 1337 || !w.bufferEnabled || !w.sortBuffer || @@ -860,22 +793,18 @@ func TestValidate(t *testing.T) { t.Parallel() w := Orderbook{} err := w.validate(nil) - if !errors.Is(err, errUpdateIsNil) { - t.Fatalf("expected error %v but received %v", errUpdateIsNil, err) - } - + require.ErrorIs(t, err, errUpdateIsNil) err = w.validate(&orderbook.Update{}) - if !errors.Is(err, errUpdateNoTargets) { - t.Fatalf("expected error %v but received %v", errUpdateNoTargets, err) - } + require.ErrorIs(t, err, errUpdateNoTargets) } func TestEnsureMultipleUpdatesViaPrice(t *testing.T) { t.Parallel() - holder, _, _, err := createSnapshot() - if err != nil { - t.Error(err) - } + cp, err := getExclusivePair() + require.NoError(t, err) + + holder, _, _, err := createSnapshot(cp) + require.NoError(t, err) asks := bidAskGenerator() book := holder.ob[key.PairAsset{Base: cp.Base.Item, Quote: cp.Quote.Item, Asset: asset.Spot}] @@ -886,18 +815,11 @@ func TestEnsureMultipleUpdatesViaPrice(t *testing.T) { UpdateTime: time.Now(), Asset: asset.Spot, }) - if err != nil { - t.Error(err) - } + require.NoError(t, err) askLen, err := book.ob.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if askLen <= 3 { - t.Errorf("Insufficient updates") - } + require.NoError(t, err) + assert.LessOrEqual(t, 3, askLen) } func deploySliceOrdered(size int) orderbook.Tranches { @@ -910,272 +832,149 @@ func deploySliceOrdered(size int) orderbook.Tranches { func TestUpdateByIDAndAction(t *testing.T) { t.Parallel() - holder := orderbookHolder{} + cp, err := getExclusivePair() + require.NoError(t, err) asks := deploySliceOrdered(100) - //nolint: gocritic - bids := append(asks[:0:0], asks...) + bids := slices.Clone(asks) bids.Reverse() book, err := orderbook.DeployDepth("test", cp, asset.Spot) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) - err = book.LoadSnapshot(append(bids[:0:0], bids...), append(asks[:0:0], asks...), 0, time.Now(), time.Now(), true) - if err != nil { - t.Fatal(err) - } + err = book.LoadSnapshot(slices.Clone(bids), slices.Clone(asks), 0, time.Now(), time.Now(), true) + require.NoError(t, err) ob, err := book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) - err = ob.Verify() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - holder.ob = book + require.NoError(t, ob.Verify()) + holder := orderbookHolder{ob: book} err = holder.updateByIDAndAction(&orderbook.Update{}) - if !errors.Is(err, errInvalidAction) { - t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidAction) - } + require.ErrorIs(t, err, errInvalidAction) err = holder.updateByIDAndAction(&orderbook.Update{ Action: orderbook.Amend, - Bids: []orderbook.Tranche{ - { - Price: 100, - ID: 6969, - }, - }, + Bids: []orderbook.Tranche{{Price: 100, ID: 6969}}, }) - if !strings.Contains(err.Error(), errAmendFailure.Error()) { - t.Fatalf("received: '%v' but expected: '%v'", err, errAmendFailure) - } + require.ErrorIs(t, err, errAmendFailure) + + err = book.LoadSnapshot(slices.Clone(bids), slices.Clone(asks), 0, time.Now(), time.Now(), true) + require.NoError(t, err) - err = book.LoadSnapshot(append(bids[:0:0], bids...), append(asks[:0:0], asks...), 0, time.Now(), time.Now(), true) - if err != nil { - t.Fatal(err) - } // append to slice err = holder.updateByIDAndAction(&orderbook.Update{ - Action: orderbook.UpdateInsert, - Bids: []orderbook.Tranche{ - { - Price: 0, - ID: 1337, - Amount: 1, - }, - }, - Asks: []orderbook.Tranche{ - { - Price: 100, - ID: 1337, - Amount: 1, - }, - }, + Action: orderbook.UpdateInsert, + Bids: []orderbook.Tranche{{Price: 0, ID: 1337, Amount: 1}}, + Asks: []orderbook.Tranche{{Price: 100, ID: 1337, Amount: 1}}, UpdateTime: time.Now(), }) - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) cpy, err := book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if cpy.Bids[len(cpy.Bids)-1].Price != 0 { - t.Fatal("did not append bid item") - } - if cpy.Asks[len(cpy.Asks)-1].Price != 100 { - t.Fatal("did not append ask item") - } + require.NoError(t, err) + require.Equal(t, 0., cpy.Bids[len(cpy.Bids)-1].Price) + require.Equal(t, 100., cpy.Asks[len(cpy.Asks)-1].Price) // Change amount err = holder.updateByIDAndAction(&orderbook.Update{ - Action: orderbook.UpdateInsert, - Bids: []orderbook.Tranche{ - { - Price: 0, - ID: 1337, - Amount: 100, - }, - }, - Asks: []orderbook.Tranche{ - { - Price: 100, - ID: 1337, - Amount: 100, - }, - }, + Action: orderbook.UpdateInsert, + Bids: []orderbook.Tranche{{Price: 0, ID: 1337, Amount: 100}}, + Asks: []orderbook.Tranche{{Price: 100, ID: 1337, Amount: 100}}, UpdateTime: time.Now(), }) - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) cpy, err = book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if cpy.Bids[len(cpy.Bids)-1].Amount != 100 { - t.Fatal("did not update bid amount", cpy.Bids[len(cpy.Bids)-1].Amount) - } - - if cpy.Asks[len(cpy.Asks)-1].Amount != 100 { - t.Fatal("did not update ask amount") - } + require.NoError(t, err) + require.Equal(t, 100., cpy.Bids[len(cpy.Bids)-1].Amount) + require.Equal(t, 100., cpy.Asks[len(cpy.Asks)-1].Amount) // Change price level err = holder.updateByIDAndAction(&orderbook.Update{ - Action: orderbook.UpdateInsert, - Bids: []orderbook.Tranche{ - { - Price: 100, - ID: 1337, - Amount: 99, - }, - }, - Asks: []orderbook.Tranche{ - { - Price: 0, - ID: 1337, - Amount: 99, - }, - }, + Action: orderbook.UpdateInsert, + Bids: []orderbook.Tranche{{Price: 100, ID: 1337, Amount: 99}}, + Asks: []orderbook.Tranche{{Price: 0, ID: 1337, Amount: 99}}, UpdateTime: time.Now(), }) - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) cpy, err = book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) - if cpy.Bids[0].Amount != 99 && cpy.Bids[0].Price != 100 { - t.Fatal("did not adjust bid item placement and details") - } + require.Equal(t, 99., cpy.Bids[0].Amount) + require.Equal(t, 100., cpy.Bids[0].Price) + require.Equal(t, 99., cpy.Asks[0].Amount) + require.Equal(t, 0., cpy.Asks[0].Price) - if cpy.Asks[0].Amount != 99 && cpy.Asks[0].Amount != 0 { - t.Fatal("did not adjust ask item placement and details") - } - - err = book.LoadSnapshot(append(bids[:0:0], bids...), append(asks[:0:0], asks...), 0, time.Now(), time.Now(), true) //nolint:gocritic - if err != nil { - t.Fatal(err) - } + err = book.LoadSnapshot(slices.Clone(bids), slices.Clone(asks), 0, time.Now(), time.Now(), true) + require.NoError(t, err) // Delete - not found err = holder.updateByIDAndAction(&orderbook.Update{ Action: orderbook.Delete, - Asks: []orderbook.Tranche{ - { - Price: 0, - ID: 1337, - Amount: 99, - }, - }, + Asks: []orderbook.Tranche{{Price: 0, ID: 1337, Amount: 99}}, }) - if !strings.Contains(err.Error(), errDeleteFailure.Error()) { - t.Fatalf("received: '%v' but expected: '%v'", err, errDeleteFailure) - } + require.ErrorIs(t, err, errDeleteFailure) + + err = book.LoadSnapshot(slices.Clone(bids), slices.Clone(asks), 0, time.Now(), time.Now(), true) + require.NoError(t, err) - err = book.LoadSnapshot(append(bids[:0:0], bids...), append(asks[:0:0], asks...), 0, time.Now(), time.Now(), true) //nolint:gocritic - if err != nil { - t.Fatal(err) - } // Delete - found err = holder.updateByIDAndAction(&orderbook.Update{ - Action: orderbook.Delete, - Asks: []orderbook.Tranche{ - asks[0], - }, + Action: orderbook.Delete, + Asks: []orderbook.Tranche{asks[0]}, UpdateTime: time.Now(), }) - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } + require.NoError(t, err) askLen, err := book.GetAskLength() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if askLen != 99 { - t.Fatal("element not deleted") - } + require.NoError(t, err) + require.Equal(t, 99, askLen) // Apply update err = holder.updateByIDAndAction(&orderbook.Update{ Action: orderbook.Amend, - Asks: []orderbook.Tranche{ - {ID: 123456}, - }, + Asks: []orderbook.Tranche{{ID: 123456}}, }) - if !strings.Contains(err.Error(), errAmendFailure.Error()) { - t.Fatalf("received: '%v' but expected: '%v'", err, errAmendFailure) - } + require.ErrorIs(t, err, errAmendFailure) - err = book.LoadSnapshot(bids, bids, 0, time.Now(), time.Now(), true) - if err != nil { - t.Fatal(err) - } + err = book.LoadSnapshot(slices.Clone(bids), slices.Clone(bids), 0, time.Now(), time.Now(), true) + require.NoError(t, err) ob, err = book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - if len(ob.Asks) == 0 || len(ob.Bids) == 0 { - t.Fatal("expected a valid orderbook") - } + require.NoError(t, err) + require.NotEmpty(t, ob.Asks) + require.NotEmpty(t, ob.Bids) update := ob.Asks[0] update.Amount = 1337 err = holder.updateByIDAndAction(&orderbook.Update{ - Action: orderbook.Amend, - Asks: []orderbook.Tranche{ - update, - }, + Action: orderbook.Amend, + Asks: []orderbook.Tranche{update}, UpdateTime: time.Now(), }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) ob, err = book.Retrieve() - if !errors.Is(err, nil) { - t.Fatalf("received: '%v' but expected: '%v'", err, nil) - } - - if ob.Asks[0].Amount != 1337 { - t.Fatal("element not updated") - } + require.NoError(t, err) + require.Equal(t, 1337., ob.Asks[0].Amount) } func TestFlushOrderbook(t *testing.T) { t.Parallel() + cp, err := getExclusivePair() + require.NoError(t, err) + w := &Orderbook{} - err := w.Setup(&config.Exchange{Name: "test"}, &Config{}, make(chan interface{}, 2)) - if err != nil { - t.Fatal(err) - } + err = w.Setup(&config.Exchange{Name: "test"}, &Config{}, make(chan interface{}, 2)) + require.NoError(t, err) var snapShot1 orderbook.Base snapShot1.Exchange = "Snapshooooot" - asks := []orderbook.Tranche{ - {Price: 4000, Amount: 1, ID: 8}, - } - bids := []orderbook.Tranche{ - {Price: 4000, Amount: 1, ID: 9}, - } + asks := []orderbook.Tranche{{Price: 4000, Amount: 1, ID: 8}} + bids := []orderbook.Tranche{{Price: 4000, Amount: 1, ID: 9}} snapShot1.Asks = asks snapShot1.Bids = bids snapShot1.Asset = asset.Spot @@ -1188,22 +987,11 @@ func TestFlushOrderbook(t *testing.T) { } _, err = w.GetOrderbook(cp, asset.Spot) - if !errors.Is(err, errDepthNotFound) { - t.Fatalf("expected: %v but received: %v", errDepthNotFound, err) - } + require.ErrorIs(t, err, errDepthNotFound) - err = w.LoadSnapshot(&snapShot1) - if err != nil { - t.Fatal(err) - } - - err = w.FlushOrderbook(cp, asset.Spot) - if err != nil { - t.Fatal(err) - } + require.NoError(t, w.LoadSnapshot(&snapShot1)) + require.NoError(t, w.FlushOrderbook(cp, asset.Spot)) _, err = w.GetOrderbook(cp, asset.Spot) - if !errors.Is(err, orderbook.ErrOrderbookInvalid) { - t.Fatalf("received: '%v' but expected: '%v'", err, orderbook.ErrOrderbookInvalid) - } + require.ErrorIs(t, err, orderbook.ErrOrderbookInvalid) }