You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

259 lines
6.1 KiB

package loop
import (
"errors"
"testing"
"time"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/lntypes"
)
// storeMock implements a mock client swap store.
type storeMock struct {
loopOutSwaps map[lntypes.Hash]*loopdb.LoopOutContract
loopOutUpdates map[lntypes.Hash][]loopdb.SwapStateData
loopOutStoreChan chan loopdb.LoopOutContract
loopOutUpdateChan chan loopdb.SwapStateData
loopInSwaps map[lntypes.Hash]*loopdb.LoopInContract
loopInUpdates map[lntypes.Hash][]loopdb.SwapStateData
loopInStoreChan chan loopdb.LoopInContract
loopInUpdateChan chan loopdb.SwapStateData
t *testing.T
}
// NewStoreMock instantiates a new mock store.
func newStoreMock(t *testing.T) *storeMock {
return &storeMock{
loopOutStoreChan: make(chan loopdb.LoopOutContract, 1),
loopOutUpdateChan: make(chan loopdb.SwapStateData, 1),
loopOutSwaps: make(map[lntypes.Hash]*loopdb.LoopOutContract),
loopOutUpdates: make(map[lntypes.Hash][]loopdb.SwapStateData),
loopInStoreChan: make(chan loopdb.LoopInContract, 1),
loopInUpdateChan: make(chan loopdb.SwapStateData, 1),
loopInSwaps: make(map[lntypes.Hash]*loopdb.LoopInContract),
loopInUpdates: make(map[lntypes.Hash][]loopdb.SwapStateData),
t: t,
}
}
// FetchLoopOutSwaps returns all swaps currently in the store.
//
// NOTE: Part of the loopdb.SwapStore interface.
func (s *storeMock) FetchLoopOutSwaps() ([]*loopdb.LoopOut, error) {
result := []*loopdb.LoopOut{}
for hash, contract := range s.loopOutSwaps {
updates := s.loopOutUpdates[hash]
events := make([]*loopdb.LoopEvent, len(updates))
for i, u := range updates {
events[i] = &loopdb.LoopEvent{
SwapStateData: u,
}
}
swap := &loopdb.LoopOut{
Loop: loopdb.Loop{
Hash: hash,
Events: events,
},
Contract: contract,
}
result = append(result, swap)
}
return result, nil
}
// CreateLoopOut adds an initiated swap to the store.
//
// NOTE: Part of the loopdb.SwapStore interface.
func (s *storeMock) CreateLoopOut(hash lntypes.Hash,
swap *loopdb.LoopOutContract) error {
_, ok := s.loopOutSwaps[hash]
if ok {
return errors.New("swap already exists")
}
s.loopOutSwaps[hash] = swap
s.loopOutUpdates[hash] = []loopdb.SwapStateData{}
s.loopOutStoreChan <- *swap
return nil
}
// FetchLoopInSwaps returns all in swaps currently in the store.
func (s *storeMock) FetchLoopInSwaps() ([]*loopdb.LoopIn, error) {
result := []*loopdb.LoopIn{}
for hash, contract := range s.loopInSwaps {
updates := s.loopInUpdates[hash]
events := make([]*loopdb.LoopEvent, len(updates))
for i, u := range updates {
events[i] = &loopdb.LoopEvent{
SwapStateData: u,
}
}
swap := &loopdb.LoopIn{
Loop: loopdb.Loop{
Hash: hash,
Events: events,
},
Contract: contract,
}
result = append(result, swap)
}
return result, nil
}
// CreateLoopIn adds an initiated loop in swap to the store.
//
// NOTE: Part of the loopdb.SwapStore interface.
func (s *storeMock) CreateLoopIn(hash lntypes.Hash,
swap *loopdb.LoopInContract) error {
_, ok := s.loopInSwaps[hash]
if ok {
return errors.New("swap already exists")
}
s.loopInSwaps[hash] = swap
s.loopInUpdates[hash] = []loopdb.SwapStateData{}
s.loopInStoreChan <- *swap
return nil
}
// UpdateLoopOut stores a new event for a target loop out swap. This appends to
// the event log for a particular swap as it goes through the various stages in
// its lifetime.
//
// NOTE: Part of the loopdb.SwapStore interface.
func (s *storeMock) UpdateLoopOut(hash lntypes.Hash, time time.Time,
state loopdb.SwapStateData) error {
updates, ok := s.loopOutUpdates[hash]
if !ok {
return errors.New("swap does not exists")
}
updates = append(updates, state)
s.loopOutUpdates[hash] = updates
s.loopOutUpdateChan <- state
return nil
}
// UpdateLoopIn stores a new event for a target loop in swap. This appends to
// the event log for a particular swap as it goes through the various stages in
// its lifetime.
//
// NOTE: Part of the loopdb.SwapStore interface.
func (s *storeMock) UpdateLoopIn(hash lntypes.Hash, time time.Time,
state loopdb.SwapStateData) error {
updates, ok := s.loopInUpdates[hash]
if !ok {
return errors.New("swap does not exists")
}
updates = append(updates, state)
s.loopInUpdates[hash] = updates
s.loopInUpdateChan <- state
return nil
}
func (s *storeMock) Close() error {
return nil
}
func (s *storeMock) isDone() error {
select {
case <-s.loopOutStoreChan:
return errors.New("storeChan not empty")
default:
}
select {
case <-s.loopOutUpdateChan:
return errors.New("updateChan not empty")
default:
}
return nil
}
func (s *storeMock) assertLoopOutStored() {
s.t.Helper()
select {
case <-s.loopOutStoreChan:
case <-time.After(test.Timeout):
s.t.Fatalf("expected swap to be stored")
}
}
func (s *storeMock) assertLoopOutState(expectedState loopdb.SwapState) {
s.t.Helper()
state := <-s.loopOutUpdateChan
if state.State != expectedState {
s.t.Fatalf("expected state %v, got %v", expectedState, state)
}
}
func (s *storeMock) assertLoopInStored() {
s.t.Helper()
<-s.loopInStoreChan
}
// assertLoopInState asserts that a specified state transition is persisted to
// disk.
func (s *storeMock) assertLoopInState(
expectedState loopdb.SwapState) loopdb.SwapStateData {
s.t.Helper()
state := <-s.loopInUpdateChan
if state.State != expectedState {
s.t.Fatalf("expected state %v, got %v", expectedState, state)
}
return state
}
func (s *storeMock) assertStorePreimageReveal() {
s.t.Helper()
select {
case state := <-s.loopOutUpdateChan:
if state.State != loopdb.StatePreimageRevealed {
s.t.Fatalf("unexpected state")
}
case <-time.After(test.Timeout):
s.t.Fatalf("expected swap to be marked as preimage revealed")
}
}
func (s *storeMock) assertStoreFinished(expectedResult loopdb.SwapState) {
s.t.Helper()
select {
case state := <-s.loopOutUpdateChan:
if state.State != expectedResult {
s.t.Fatalf("expected result %v, but got %v",
expectedResult, state)
}
case <-time.After(test.Timeout):
s.t.Fatalf("expected swap to be finished")
}
}