mirror of
https://github.com/lightninglabs/pool.git
synced 2026-08-13 12:33:04 +02:00
151 lines
4.1 KiB
Go
151 lines
4.1 KiB
Go
package clientdb
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/lightninglabs/pool/event"
|
|
"github.com/lightninglabs/pool/order"
|
|
"github.com/stretchr/testify/require"
|
|
"go.etcd.io/bbolt"
|
|
)
|
|
|
|
// 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 := store.DB.View(func(tx *bbolt.Tx) error {
|
|
ordersBucket := tx.Bucket(ordersBucketKey)
|
|
orderBucket := ordersBucket.Bucket(o[:])
|
|
eventBucket := orderBucket.Bucket(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
|
|
}
|