Skip to content

Commit 6385390

Browse files
committed
looprpc: add test for ListSwaps pagination and filtering
1 parent ca69184 commit 6385390

File tree

1 file changed

+327
-0
lines changed

1 file changed

+327
-0
lines changed

loopd/swapclient_server_test.go

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ import (
44
"context"
55
"os"
66
"testing"
7+
"time"
78

89
"github.com/btcsuite/btcd/btcutil"
910
"github.com/btcsuite/btcd/chaincfg"
1011
"github.com/btcsuite/btclog/v2"
1112
"github.com/lightninglabs/lndclient"
1213
"github.com/lightninglabs/loop"
1314
"github.com/lightninglabs/loop/labels"
15+
"github.com/lightninglabs/loop/loopdb"
1416
"github.com/lightninglabs/loop/looprpc"
17+
"github.com/lightninglabs/loop/swap"
1518
mock_lnd "github.com/lightninglabs/loop/test"
19+
"github.com/lightningnetwork/lnd/lntypes"
1620
"github.com/lightningnetwork/lnd/lnwire"
1721
"github.com/lightningnetwork/lnd/routing/route"
1822
"github.com/stretchr/testify/require"
@@ -595,3 +599,326 @@ func TestHasBandwidth(t *testing.T) {
595599
})
596600
}
597601
}
602+
603+
// TestListSwapsFilterAndPagination tests the filtering and
604+
// paging of the ListSwaps command.
605+
func TestListSwapsFilterAndPagination(t *testing.T) {
606+
unixTime := time.Unix(0, 0)
607+
firstSwapStartTime := unixTime.Add(10 * time.Minute)
608+
secondSwapStartTime := unixTime.Add(20 * time.Minute)
609+
thirdSwapStartTime := unixTime.Add(30 * time.Minute)
610+
611+
// Create a set of test swaps of various types which contain the minimal
612+
// viable amount of info to successfully be run through marshallSwap.
613+
swapInOrder0 := loop.SwapInfo{
614+
SwapStateData: loopdb.SwapStateData{
615+
State: loopdb.StateInitiated,
616+
Cost: loopdb.SwapCost{},
617+
},
618+
SwapContract: loopdb.SwapContract{
619+
InitiationTime: firstSwapStartTime,
620+
},
621+
LastUpdate: time.Now(),
622+
SwapHash: lntypes.Hash{1},
623+
SwapType: swap.Type(swap.TypeIn),
624+
HtlcAddressP2WSH: testnetAddr,
625+
HtlcAddressP2TR: testnetAddr,
626+
}
627+
628+
swapOutOrder1 := loop.SwapInfo{
629+
SwapStateData: loopdb.SwapStateData{
630+
State: loopdb.StateInitiated,
631+
Cost: loopdb.SwapCost{},
632+
},
633+
SwapContract: loopdb.SwapContract{
634+
InitiationTime: secondSwapStartTime,
635+
},
636+
LastUpdate: time.Now(),
637+
SwapHash: lntypes.Hash{2},
638+
SwapType: swap.Type(swap.TypeOut),
639+
HtlcAddressP2WSH: testnetAddr,
640+
HtlcAddressP2TR: testnetAddr,
641+
}
642+
643+
swapOutOrder2 := loop.SwapInfo{
644+
SwapStateData: loopdb.SwapStateData{
645+
State: loopdb.StateInitiated,
646+
Cost: loopdb.SwapCost{},
647+
},
648+
SwapContract: loopdb.SwapContract{
649+
InitiationTime: thirdSwapStartTime,
650+
},
651+
LastUpdate: time.Now(),
652+
SwapHash: lntypes.Hash{3},
653+
SwapType: swap.Type(swap.TypeOut),
654+
HtlcAddressP2WSH: testnetAddr,
655+
HtlcAddressP2TR: testnetAddr,
656+
}
657+
658+
mockSwaps := []loop.SwapInfo{swapInOrder0, swapOutOrder1, swapOutOrder2}
659+
660+
tests := []struct {
661+
name string
662+
// Define the mock swaps that will be stored in the mock client.
663+
mockSwaps []loop.SwapInfo
664+
req *looprpc.ListSwapsRequest
665+
// These hashes must be in the correct return order as the response.
666+
expectedReturnedSwaps []lntypes.Hash
667+
expectedFirstIdx uint64
668+
expectedLastIdx uint64
669+
expectedFilteredTotalCount uint64
670+
}{
671+
{
672+
name: "fetch all swaps no pagination",
673+
mockSwaps: mockSwaps,
674+
req: &looprpc.ListSwapsRequest{},
675+
expectedReturnedSwaps: []lntypes.Hash{
676+
swapOutOrder2.SwapHash,
677+
swapOutOrder1.SwapHash,
678+
swapInOrder0.SwapHash,
679+
},
680+
expectedFirstIdx: 0,
681+
expectedLastIdx: 2,
682+
expectedFilteredTotalCount: 3,
683+
},
684+
{
685+
name: "fetch all swaps no pagination alt-order1",
686+
mockSwaps: []loop.SwapInfo{swapOutOrder1, swapInOrder0, swapOutOrder2},
687+
req: &looprpc.ListSwapsRequest{},
688+
expectedReturnedSwaps: []lntypes.Hash{
689+
swapOutOrder2.SwapHash,
690+
swapOutOrder1.SwapHash,
691+
swapInOrder0.SwapHash,
692+
},
693+
expectedFirstIdx: 0,
694+
expectedLastIdx: 2,
695+
expectedFilteredTotalCount: 3,
696+
},
697+
{
698+
name: "fetch all swaps no pagination alt-order2",
699+
mockSwaps: []loop.SwapInfo{swapOutOrder2, swapOutOrder1, swapInOrder0},
700+
req: &looprpc.ListSwapsRequest{},
701+
expectedReturnedSwaps: []lntypes.Hash{
702+
swapOutOrder2.SwapHash,
703+
swapOutOrder1.SwapHash,
704+
swapInOrder0.SwapHash,
705+
},
706+
expectedFirstIdx: 0,
707+
expectedLastIdx: 2,
708+
expectedFilteredTotalCount: 3,
709+
},
710+
{
711+
name: "fetch swaps-ins no pagination",
712+
mockSwaps: mockSwaps,
713+
req: &looprpc.ListSwapsRequest{
714+
ListSwapFilter: &looprpc.ListSwapsFilter{
715+
SwapType: looprpc.ListSwapsFilter_LOOP_IN},
716+
},
717+
expectedReturnedSwaps: []lntypes.Hash{
718+
swapInOrder0.SwapHash,
719+
},
720+
expectedFirstIdx: 0,
721+
expectedLastIdx: 0,
722+
expectedFilteredTotalCount: 1,
723+
},
724+
{
725+
name: "fetch swaps-outs no pagination",
726+
mockSwaps: mockSwaps,
727+
req: &looprpc.ListSwapsRequest{
728+
ListSwapFilter: &looprpc.ListSwapsFilter{
729+
SwapType: looprpc.ListSwapsFilter_LOOP_OUT,
730+
},
731+
},
732+
expectedReturnedSwaps: []lntypes.Hash{
733+
swapOutOrder2.SwapHash,
734+
swapOutOrder1.SwapHash,
735+
},
736+
expectedFirstIdx: 0,
737+
expectedLastIdx: 1,
738+
expectedFilteredTotalCount: 2,
739+
},
740+
{
741+
name: "fetch swaps-outs increment start_index",
742+
mockSwaps: mockSwaps,
743+
req: &looprpc.ListSwapsRequest{
744+
ListSwapFilter: &looprpc.ListSwapsFilter{
745+
SwapType: looprpc.ListSwapsFilter_LOOP_OUT,
746+
},
747+
IndexOffset: 1,
748+
},
749+
expectedReturnedSwaps: []lntypes.Hash{
750+
swapOutOrder1.SwapHash,
751+
},
752+
expectedFirstIdx: 1,
753+
expectedLastIdx: 1,
754+
expectedFilteredTotalCount: 2,
755+
},
756+
{
757+
name: "fetch all swaps set swap limit",
758+
mockSwaps: mockSwaps,
759+
req: &looprpc.ListSwapsRequest{
760+
MaxSwaps: 2,
761+
},
762+
expectedReturnedSwaps: []lntypes.Hash{
763+
swapOutOrder2.SwapHash,
764+
swapOutOrder1.SwapHash,
765+
},
766+
expectedFirstIdx: 0,
767+
expectedLastIdx: 1,
768+
expectedFilteredTotalCount: 3,
769+
},
770+
{
771+
name: "fetch all swaps set swap limit set start index",
772+
mockSwaps: mockSwaps,
773+
req: &looprpc.ListSwapsRequest{
774+
IndexOffset: 1,
775+
MaxSwaps: 1,
776+
},
777+
expectedReturnedSwaps: []lntypes.Hash{
778+
swapOutOrder1.SwapHash,
779+
},
780+
expectedFirstIdx: 1,
781+
expectedLastIdx: 1,
782+
expectedFilteredTotalCount: 3,
783+
},
784+
{
785+
name: "fetch all swaps set start index out of bounds",
786+
mockSwaps: mockSwaps,
787+
req: &looprpc.ListSwapsRequest{
788+
IndexOffset: 5,
789+
},
790+
expectedReturnedSwaps: []lntypes.Hash{},
791+
expectedFirstIdx: 5,
792+
expectedLastIdx: 0,
793+
expectedFilteredTotalCount: 3,
794+
},
795+
{
796+
name: "fetch all swaps set limit to 0",
797+
mockSwaps: mockSwaps,
798+
req: &looprpc.ListSwapsRequest{
799+
MaxSwaps: 0,
800+
},
801+
expectedReturnedSwaps: []lntypes.Hash{
802+
swapOutOrder2.SwapHash,
803+
swapOutOrder1.SwapHash,
804+
swapInOrder0.SwapHash,
805+
},
806+
expectedLastIdx: 2,
807+
expectedFilteredTotalCount: 3,
808+
},
809+
{
810+
name: "fetch all swaps with time filter #1",
811+
mockSwaps: mockSwaps,
812+
req: &looprpc.ListSwapsRequest{
813+
ListSwapFilter: &looprpc.ListSwapsFilter{
814+
StartTimestamp: unixTime.Add(5 * time.Minute).Unix(),
815+
EndTimestamp: unixTime.Add(15 * time.Minute).Unix(),
816+
},
817+
},
818+
expectedReturnedSwaps: []lntypes.Hash{
819+
swapInOrder0.SwapHash,
820+
},
821+
expectedLastIdx: 0,
822+
expectedFilteredTotalCount: 1,
823+
},
824+
{
825+
name: "fetch all swaps with time filter #2",
826+
mockSwaps: mockSwaps,
827+
req: &looprpc.ListSwapsRequest{
828+
ListSwapFilter: &looprpc.ListSwapsFilter{
829+
StartTimestamp: unixTime.Add(5 * time.Minute).Unix(),
830+
EndTimestamp: unixTime.Add(25 * time.Minute).Unix(),
831+
},
832+
},
833+
expectedReturnedSwaps: []lntypes.Hash{
834+
swapOutOrder1.SwapHash,
835+
swapInOrder0.SwapHash,
836+
},
837+
expectedLastIdx: 1,
838+
expectedFilteredTotalCount: 2,
839+
},
840+
{
841+
name: "fetch loop out swaps with time filter #1",
842+
mockSwaps: mockSwaps,
843+
req: &looprpc.ListSwapsRequest{
844+
ListSwapFilter: &looprpc.ListSwapsFilter{
845+
SwapType: looprpc.ListSwapsFilter_LOOP_OUT,
846+
StartTimestamp: unixTime.Add(15 * time.Minute).Unix(),
847+
EndTimestamp: unixTime.Add(25 * time.Minute).Unix(),
848+
},
849+
},
850+
expectedReturnedSwaps: []lntypes.Hash{
851+
swapOutOrder1.SwapHash,
852+
},
853+
expectedLastIdx: 0,
854+
expectedFilteredTotalCount: 1,
855+
},
856+
}
857+
858+
for _, test := range tests {
859+
t.Run(test.name, func(t *testing.T) {
860+
t.Parallel()
861+
862+
// Create the swap client server with our mock client.
863+
server := &swapClientServer{
864+
swaps: make(map[lntypes.Hash]loop.SwapInfo),
865+
}
866+
867+
// Populate the server's swap cache with our mock swaps.
868+
for _, swap := range test.mockSwaps {
869+
server.swaps[swap.SwapHash] = swap
870+
}
871+
872+
// Call the ListSwaps method.
873+
resp, err := server.ListSwaps(context.Background(), test.req)
874+
require.NoError(t, err)
875+
876+
require.Len(
877+
t,
878+
resp.Swaps,
879+
len(test.expectedReturnedSwaps),
880+
"incorrect returned count",
881+
)
882+
883+
require.Equal(
884+
t,
885+
test.expectedFirstIdx,
886+
resp.FirstIndexOffset,
887+
"incorrect first index",
888+
)
889+
890+
require.Equal(
891+
t,
892+
test.expectedLastIdx,
893+
resp.LastIndexOffset,
894+
"incorrect last index",
895+
)
896+
897+
require.Equal(
898+
t,
899+
test.expectedFilteredTotalCount,
900+
resp.TotalFilteredSwaps,
901+
"incorrect total",
902+
)
903+
904+
// Subtest function to check consistent iteration order.
905+
swapOrderCheck := func(
906+
hashes []lntypes.Hash,
907+
swaps *looprpc.ListSwapsResponse) {
908+
for idx, aswap := range swaps.Swaps {
909+
newhash, err := lntypes.MakeHash(aswap.GetIdBytes())
910+
require.NoError(t, err)
911+
require.Equal(
912+
t,
913+
hashes[idx],
914+
newhash,
915+
"iteration order mismatch",
916+
)
917+
918+
}
919+
920+
}
921+
swapOrderCheck(test.expectedReturnedSwaps, resp)
922+
})
923+
}
924+
}

0 commit comments

Comments
 (0)