mirror of https://github.com/lightninglabs/loop
reservation: add test for manager
parent
61a5f9da05
commit
d527b0b67c
@ -0,0 +1,160 @@
|
||||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightninglabs/loop/swapserverrpc"
|
||||
"github.com/lightninglabs/loop/test"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultReservationId = mustDecodeID("17cecc61ab4aafebdc0542dabdae0d0cb8907ec1c9c8ae387bc5a3309ca8b600")
|
||||
)
|
||||
|
||||
func TestManager(t *testing.T) {
|
||||
ctxb, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
testContext := newManagerTestContext(t)
|
||||
|
||||
// Start the manager.
|
||||
go func() {
|
||||
err := testContext.manager.Run(ctxb, testContext.mockLnd.Height)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
// Create a new reservation.
|
||||
fsm, err := testContext.manager.newReservation(
|
||||
ctxb, uint32(testContext.mockLnd.Height),
|
||||
&swapserverrpc.ServerReservationNotification{
|
||||
ReservationId: defaultReservationId[:],
|
||||
Value: uint64(defaultValue),
|
||||
ServerKey: defaultPubkeyBytes,
|
||||
Expiry: uint32(testContext.mockLnd.Height) + defaultExpiry,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll expect the spendConfirmation to be sent to the server.
|
||||
pkScript, err := fsm.reservation.GetPkScript()
|
||||
require.NoError(t, err)
|
||||
|
||||
conf := <-testContext.mockLnd.RegisterConfChannel
|
||||
require.Equal(t, conf.PkScript, pkScript)
|
||||
|
||||
confTx := &wire.MsgTx{
|
||||
TxOut: []*wire.TxOut{
|
||||
{
|
||||
PkScript: pkScript,
|
||||
},
|
||||
},
|
||||
}
|
||||
// We'll now confirm the spend.
|
||||
conf.ConfChan <- &chainntnfs.TxConfirmation{
|
||||
BlockHeight: uint32(testContext.mockLnd.Height),
|
||||
Tx: confTx,
|
||||
}
|
||||
|
||||
// We'll now expect the reservation to be confirmed.
|
||||
err = fsm.DefaultObserver.WaitForState(ctxb, 5*time.Second, Confirmed)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll now expire the reservation.
|
||||
err = testContext.mockLnd.NotifyHeight(
|
||||
testContext.mockLnd.Height + int32(defaultExpiry),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll now expect the reservation to be expired.
|
||||
err = fsm.DefaultObserver.WaitForState(ctxb, 5*time.Second, TimedOut)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// ManagerTestContext is a helper struct that contains all the necessary
|
||||
// components to test the reservation manager.
|
||||
type ManagerTestContext struct {
|
||||
manager *Manager
|
||||
context test.Context
|
||||
mockLnd *test.LndMockServices
|
||||
reservationNotificationChan chan *swapserverrpc.ServerReservationNotification
|
||||
mockReservationClient *mockReservationClient
|
||||
}
|
||||
|
||||
// newManagerTestContext creates a new test context for the reservation manager.
|
||||
func newManagerTestContext(t *testing.T) *ManagerTestContext {
|
||||
mockLnd := test.NewMockLnd()
|
||||
lndContext := test.NewContext(t, mockLnd)
|
||||
|
||||
dbFixture := loopdb.NewTestDB(t)
|
||||
|
||||
store := NewSQLStore(dbFixture)
|
||||
|
||||
mockReservationClient := new(mockReservationClient)
|
||||
|
||||
sendChan := make(chan *swapserverrpc.ServerReservationNotification)
|
||||
|
||||
mockReservationClient.On(
|
||||
"ReservationNotificationStream", mock.Anything, mock.Anything,
|
||||
mock.Anything,
|
||||
).Return(
|
||||
&dummyReservationNotificationServer{
|
||||
SendChan: sendChan,
|
||||
}, nil,
|
||||
)
|
||||
|
||||
mockReservationClient.On(
|
||||
"OpenReservation", mock.Anything, mock.Anything, mock.Anything,
|
||||
).Return(
|
||||
&swapserverrpc.ServerOpenReservationResponse{}, nil,
|
||||
)
|
||||
|
||||
cfg := &Config{
|
||||
Store: store,
|
||||
Wallet: mockLnd.WalletKit,
|
||||
ChainNotifier: mockLnd.ChainNotifier,
|
||||
FetchL402: func(context.Context) error { return nil },
|
||||
ReservationClient: mockReservationClient,
|
||||
}
|
||||
|
||||
manager := NewManager(cfg)
|
||||
|
||||
return &ManagerTestContext{
|
||||
manager: manager,
|
||||
context: lndContext,
|
||||
mockLnd: mockLnd,
|
||||
mockReservationClient: mockReservationClient,
|
||||
reservationNotificationChan: sendChan,
|
||||
}
|
||||
}
|
||||
|
||||
type dummyReservationNotificationServer struct {
|
||||
grpc.ClientStream
|
||||
|
||||
// SendChan is the channel that is used to send notifications.
|
||||
SendChan chan *swapserverrpc.ServerReservationNotification
|
||||
}
|
||||
|
||||
func (d *dummyReservationNotificationServer) Recv() (
|
||||
*swapserverrpc.ServerReservationNotification, error) {
|
||||
|
||||
return <-d.SendChan, nil
|
||||
}
|
||||
|
||||
func mustDecodeID(id string) ID {
|
||||
bytes, err := hex.DecodeString(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var decoded ID
|
||||
copy(decoded[:], bytes)
|
||||
return decoded
|
||||
}
|
Loading…
Reference in New Issue