pool/clientdb/event_test.go
Oliver Gugger f460060692
wasm
2021-05-25 14:21:39 +02:00

150 lines
4.2 KiB
Go

package clientdb
import (
"fmt"
"testing"
"time"
"github.com/btcsuite/btcwallet/walletdb"
"github.com/lightninglabs/pool/event"
"github.com/lightninglabs/pool/order"
"github.com/stretchr/testify/require"
)
// TestOrderEvents tests that storing and updating orders creates the correct
// events in the main event bucket but also the references in the order's
// bucket.
func TestOrderEvents(t *testing.T) {
t.Parallel()
store, cleanup := newTestDB(t)
defer cleanup()
// Store two dummy orders that we are going to update later.
o1 := &order.Bid{
Kit: *dummyOrder(500000, 1337),
}
err := store.SubmitOrder(o1)
require.NoError(t, err)
o2 := &order.Ask{
Kit: *dummyOrder(500000, 1337),
}
err = store.SubmitOrder(o2)
require.NoError(t, err)
assertOrderCreateEvent(t, store, o1.Nonce())
assertOrderCreateEvent(t, store, o2.Nonce())
assertOrderStateEvents(t, store, o1.Nonce(), []order.State{})
assertOrderStateEvents(t, store, o2.Nonce(), []order.State{})
// Update the state of the first order and check that it is persisted.
err = store.UpdateOrder(
o1.Nonce(), order.StateModifier(order.StatePartiallyFilled),
)
require.NoError(t, err)
storedOrder, err := store.GetOrder(o1.Nonce())
require.NoError(t, err)
require.Equal(
t, order.StatePartiallyFilled, storedOrder.Details().State,
)
assertOrderStateEvents(t, store, o1.Nonce(), []order.State{
order.StatePartiallyFilled,
})
// Bulk update the state of both orders and check that they are
// persisted correctly.
stateModifier := order.StateModifier(order.StateCleared)
err = store.UpdateOrders(
[]order.Nonce{o1.Nonce(), o2.Nonce()},
[][]order.Modifier{{stateModifier}, {stateModifier}},
)
require.NoError(t, err)
allOrders, err := store.GetOrders()
require.NoError(t, err)
require.Len(t, allOrders, 2)
for _, o := range allOrders {
require.Equal(t, order.StateCleared, o.Details().State)
}
assertOrderStateEvents(t, store, o1.Nonce(), []order.State{
order.StatePartiallyFilled, order.StateCleared,
})
assertOrderStateEvents(t, store, o2.Nonce(), []order.State{
order.StateCleared,
})
}
func assertOrderStateEvents(t *testing.T, store *DB, o order.Nonce,
expectedStates []order.State) {
t.Helper()
// Read all order events.
orderEventTimestamps, err := getOrderEventTimestamps(
store, o, event.TypeOrderStateChange,
)
require.NoError(t, err)
require.Equal(t, len(expectedStates), len(orderEventTimestamps))
// Now that we know the timestamps, we can go ahead and read the events
// themselves.
events, err := store.GetEvents(orderEventTimestamps)
require.NoError(t, err)
require.NoError(t, err)
require.Equal(t, len(expectedStates), len(events))
// Make sure we got the actual event changes in the correct order.
for idx, evt := range events {
orderStateEvent, ok := evt.(*UpdatedEvent)
require.True(t, ok)
require.Equal(t, expectedStates[idx], orderStateEvent.NewState)
}
}
func assertOrderCreateEvent(t *testing.T, store *DB, o order.Nonce) {
t.Helper()
// Read all order events.
orderEventTimestamps, err := getOrderEventTimestamps(
store, o, event.TypeOrderCreated,
)
require.NoError(t, err)
require.Equal(t, 1, len(orderEventTimestamps))
}
func getOrderEventTimestamps(store *DB, o order.Nonce, evtType event.Type) (
map[time.Time]struct{}, error) {
orderEventTimestamps := make(map[time.Time]struct{})
err := walletdb.View(store, func(tx walletdb.ReadTx) error {
ordersBucket := tx.ReadBucket(ordersBucketKey)
orderBucket := ordersBucket.NestedReadBucket(o[:])
eventBucket := orderBucket.NestedReadBucket(eventRefSubBucket)
return eventBucket.ForEach(func(k, v []byte) error {
// Only look at keys with correct length.
if len(k) != event.TimestampLength {
return nil
}
// Assert there are no corrupt values, in the reference
// key we only store the event's type, not the value
// itself.
if len(v) != 1 {
return fmt.Errorf("unexpected timestamp "+
"reference value length: %d", len(v))
}
// We filter by the requested order type.
if event.Type(v[0]) != evtType {
return nil
}
ts := time.Unix(0, int64(byteOrder.Uint64(k)))
orderEventTimestamps[ts] = struct{}{}
return nil
})
})
return orderEventTimestamps, err
}