github.com/decred/dcrlnd@v0.7.6/chanbackup/backup_test.go (about) 1 package chanbackup 2 3 import ( 4 "fmt" 5 "net" 6 "testing" 7 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 "github.com/decred/dcrd/wire" 10 "github.com/decred/dcrlnd/channeldb" 11 "github.com/decred/dcrlnd/kvdb" 12 ) 13 14 type mockChannelSource struct { 15 chans map[wire.OutPoint]*channeldb.OpenChannel 16 17 failQuery bool 18 19 addrs map[[33]byte][]net.Addr 20 } 21 22 func newMockChannelSource() *mockChannelSource { 23 return &mockChannelSource{ 24 chans: make(map[wire.OutPoint]*channeldb.OpenChannel), 25 addrs: make(map[[33]byte][]net.Addr), 26 } 27 } 28 29 func (m *mockChannelSource) FetchAllChannels() ([]*channeldb.OpenChannel, error) { 30 if m.failQuery { 31 return nil, fmt.Errorf("fail") 32 } 33 34 chans := make([]*channeldb.OpenChannel, 0, len(m.chans)) 35 for _, channel := range m.chans { 36 chans = append(chans, channel) 37 } 38 39 return chans, nil 40 } 41 42 func (m *mockChannelSource) FetchChannel(_ kvdb.RTx, chanPoint wire.OutPoint) ( 43 *channeldb.OpenChannel, error) { 44 45 if m.failQuery { 46 return nil, fmt.Errorf("fail") 47 } 48 49 channel, ok := m.chans[chanPoint] 50 if !ok { 51 return nil, fmt.Errorf("can't find chan") 52 } 53 54 return channel, nil 55 } 56 57 func (m *mockChannelSource) addAddrsForNode(nodePub *secp256k1.PublicKey, addrs []net.Addr) { 58 var nodeKey [33]byte 59 copy(nodeKey[:], nodePub.SerializeCompressed()) 60 61 m.addrs[nodeKey] = addrs 62 } 63 64 func (m *mockChannelSource) AddrsForNode(nodePub *secp256k1.PublicKey) ([]net.Addr, error) { 65 if m.failQuery { 66 return nil, fmt.Errorf("fail") 67 } 68 69 var nodeKey [33]byte 70 copy(nodeKey[:], nodePub.SerializeCompressed()) 71 72 addrs, ok := m.addrs[nodeKey] 73 if !ok { 74 return nil, fmt.Errorf("can't find addr") 75 } 76 77 return addrs, nil 78 } 79 80 // TestFetchBackupForChan tests that we're able to construct a single channel 81 // backup for channels that are known, unknown, and also channels in which we 82 // can find addresses for and otherwise. 83 func TestFetchBackupForChan(t *testing.T) { 84 t.Parallel() 85 86 // First, we'll make two channels, only one of them will have all the 87 // information we need to construct set of backups for them. 88 randomChan1, err := genRandomOpenChannelShell() 89 if err != nil { 90 t.Fatalf("unable to generate chan: %v", err) 91 } 92 randomChan2, err := genRandomOpenChannelShell() 93 if err != nil { 94 t.Fatalf("unable to generate chan: %v", err) 95 } 96 97 chanSource := newMockChannelSource() 98 chanSource.chans[randomChan1.FundingOutpoint] = randomChan1 99 chanSource.chans[randomChan2.FundingOutpoint] = randomChan2 100 101 chanSource.addAddrsForNode(randomChan1.IdentityPub, []net.Addr{addr1}) 102 103 testCases := []struct { 104 chanPoint wire.OutPoint 105 106 pass bool 107 }{ 108 // Able to find channel, and addresses, should pass. 109 { 110 chanPoint: randomChan1.FundingOutpoint, 111 pass: true, 112 }, 113 114 // Able to find channel, not able to find addrs, should fail. 115 { 116 chanPoint: randomChan2.FundingOutpoint, 117 pass: false, 118 }, 119 120 // Not able to find channel, should fail. 121 { 122 chanPoint: op, 123 pass: false, 124 }, 125 } 126 for i, testCase := range testCases { 127 _, err := FetchBackupForChan( 128 testCase.chanPoint, chanSource, chanSource, 129 ) 130 switch { 131 // If this is a valid test case, and we failed, then we'll 132 // return an error. 133 case err != nil && testCase.pass: 134 t.Fatalf("#%v, unable to make chan backup: %v", i, err) 135 136 // If this is an invalid test case, and we passed it, then 137 // we'll return an error. 138 case err == nil && !testCase.pass: 139 t.Fatalf("#%v got nil error for invalid req: %v", 140 i, err) 141 } 142 } 143 } 144 145 // TestFetchStaticChanBackups tests that we're able to properly query the 146 // channel source for all channels and construct a Single for each channel. 147 func TestFetchStaticChanBackups(t *testing.T) { 148 t.Parallel() 149 150 // First, we'll make the set of channels that we want to seed the 151 // channel source with. Both channels will be fully populated in the 152 // channel source. 153 const numChans = 2 154 randomChan1, err := genRandomOpenChannelShell() 155 if err != nil { 156 t.Fatalf("unable to generate chan: %v", err) 157 } 158 randomChan2, err := genRandomOpenChannelShell() 159 if err != nil { 160 t.Fatalf("unable to generate chan: %v", err) 161 } 162 163 chanSource := newMockChannelSource() 164 chanSource.chans[randomChan1.FundingOutpoint] = randomChan1 165 chanSource.chans[randomChan2.FundingOutpoint] = randomChan2 166 chanSource.addAddrsForNode(randomChan1.IdentityPub, []net.Addr{addr1}) 167 chanSource.addAddrsForNode(randomChan2.IdentityPub, []net.Addr{addr2}) 168 169 // With the channel source populated, we'll now attempt to create a set 170 // of backups for all the channels. This should succeed, as all items 171 // are populated within the channel source. 172 backups, err := FetchStaticChanBackups(chanSource, chanSource) 173 if err != nil { 174 t.Fatalf("unable to create chan back ups: %v", err) 175 } 176 177 if len(backups) != numChans { 178 t.Fatalf("expected %v chans, instead got %v", numChans, 179 len(backups)) 180 } 181 182 // We'll attempt to create a set up backups again, but this time the 183 // second channel will have missing information, which should cause the 184 // query to fail. 185 var n [33]byte 186 copy(n[:], randomChan2.IdentityPub.SerializeCompressed()) 187 delete(chanSource.addrs, n) 188 189 _, err = FetchStaticChanBackups(chanSource, chanSource) 190 if err == nil { 191 t.Fatalf("query with incomplete information should fail") 192 } 193 194 // To wrap up, we'll ensure that if we're unable to query the channel 195 // source at all, then we'll fail as well. 196 chanSource = newMockChannelSource() 197 chanSource.failQuery = true 198 _, err = FetchStaticChanBackups(chanSource, chanSource) 199 if err == nil { 200 t.Fatalf("query should fail") 201 } 202 }