@@ -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 ).UnixNano (),
815+ EndTimestamp : unixTime .Add (15 * time .Minute ).UnixNano (),
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 ).UnixNano (),
830+ EndTimestamp : unixTime .Add (25 * time .Minute ).UnixNano (),
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 ).UnixNano (),
847+ EndTimestamp : unixTime .Add (25 * time .Minute ).UnixNano (),
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