github.com/decred/dcrlnd@v0.7.6/chanbackup/recover_test.go (about) 1 package chanbackup 2 3 import ( 4 "bytes" 5 "fmt" 6 "net" 7 "testing" 8 9 "github.com/decred/dcrd/dcrec/secp256k1/v4" 10 ) 11 12 type mockChannelRestorer struct { 13 fail bool 14 15 callCount int 16 } 17 18 func (m *mockChannelRestorer) RestoreChansFromSingles(...Single) error { 19 if m.fail { 20 return fmt.Errorf("fail") 21 } 22 23 m.callCount++ 24 25 return nil 26 } 27 28 type mockPeerConnector struct { 29 fail bool 30 31 callCount int 32 } 33 34 func (m *mockPeerConnector) ConnectPeer(node *secp256k1.PublicKey, 35 addrs []net.Addr) error { 36 37 if m.fail { 38 return fmt.Errorf("fail") 39 } 40 41 m.callCount++ 42 43 return nil 44 } 45 46 // TestUnpackAndRecoverSingles tests that we're able to properly unpack and 47 // recover a set of packed singles. 48 func TestUnpackAndRecoverSingles(t *testing.T) { 49 t.Parallel() 50 51 keyRing := &mockKeyRing{} 52 53 // First, we'll create a number of single chan backups that we'll 54 // shortly back to so we can begin our recovery attempt. 55 numSingles := 10 56 backups := make([]Single, 0, numSingles) 57 var packedBackups PackedSingles 58 for i := 0; i < numSingles; i++ { 59 channel, err := genRandomOpenChannelShell() 60 if err != nil { 61 t.Fatalf("unable make channel: %v", err) 62 } 63 64 single := NewSingle(channel, nil) 65 66 var b bytes.Buffer 67 if err := single.PackToWriter(&b, keyRing); err != nil { 68 t.Fatalf("unable to pack single: %v", err) 69 } 70 71 backups = append(backups, single) 72 packedBackups = append(packedBackups, b.Bytes()) 73 } 74 75 chanRestorer := mockChannelRestorer{} 76 peerConnector := mockPeerConnector{} 77 78 // Now that we have our backups (packed and unpacked), we'll attempt to 79 // restore them all in a single batch. 80 81 // If we make the channel restore fail, then the entire method should 82 // as well 83 chanRestorer.fail = true 84 err := UnpackAndRecoverSingles( 85 packedBackups, keyRing, &chanRestorer, &peerConnector, 86 ) 87 if err == nil { 88 t.Fatalf("restoration should have failed") 89 } 90 91 chanRestorer.fail = false 92 93 // If we make the peer connector fail, then the entire method should as 94 // well 95 peerConnector.fail = true 96 err = UnpackAndRecoverSingles( 97 packedBackups, keyRing, &chanRestorer, &peerConnector, 98 ) 99 if err == nil { 100 t.Fatalf("restoration should have failed") 101 } 102 103 chanRestorer.callCount-- 104 peerConnector.fail = false 105 106 // Next, we'll ensure that if all the interfaces function as expected, 107 // then the channels will properly be unpacked and restored. 108 err = UnpackAndRecoverSingles( 109 packedBackups, keyRing, &chanRestorer, &peerConnector, 110 ) 111 if err != nil { 112 t.Fatalf("unable to recover chans: %v", err) 113 } 114 115 // Both the restorer, and connector should have been called 10 times, 116 // once for each backup. 117 if chanRestorer.callCount != numSingles { 118 t.Fatalf("expected %v calls, instead got %v", 119 numSingles, chanRestorer.callCount) 120 } 121 if peerConnector.callCount != numSingles { 122 t.Fatalf("expected %v calls, instead got %v", 123 numSingles, peerConnector.callCount) 124 } 125 126 // If we modify the keyRing, then unpacking should fail. 127 keyRing.fail = true 128 err = UnpackAndRecoverSingles( 129 packedBackups, keyRing, &chanRestorer, &peerConnector, 130 ) 131 if err == nil { 132 t.Fatalf("unpacking should have failed") 133 } 134 135 // TODO(roasbeef): verify proper call args 136 } 137 138 // TestUnpackAndRecoverMulti tests that we're able to properly unpack and 139 // recover a packed multi. 140 func TestUnpackAndRecoverMulti(t *testing.T) { 141 t.Parallel() 142 143 keyRing := &mockKeyRing{} 144 145 // First, we'll create a number of single chan backups that we'll 146 // shortly back to so we can begin our recovery attempt. 147 numSingles := 10 148 backups := make([]Single, 0, numSingles) 149 for i := 0; i < numSingles; i++ { 150 channel, err := genRandomOpenChannelShell() 151 if err != nil { 152 t.Fatalf("unable make channel: %v", err) 153 } 154 155 single := NewSingle(channel, nil) 156 157 backups = append(backups, single) 158 } 159 160 multi := Multi{ 161 StaticBackups: backups, 162 } 163 164 var b bytes.Buffer 165 if err := multi.PackToWriter(&b, keyRing); err != nil { 166 t.Fatalf("unable to pack multi: %v", err) 167 } 168 169 // Next, we'll pack the set of singles into a packed multi, and also 170 // create the set of interfaces we need to carry out the remainder of 171 // the test. 172 packedMulti := PackedMulti(b.Bytes()) 173 174 chanRestorer := mockChannelRestorer{} 175 peerConnector := mockPeerConnector{} 176 177 // If we make the channel restore fail, then the entire method should 178 // as well 179 chanRestorer.fail = true 180 err := UnpackAndRecoverMulti( 181 packedMulti, keyRing, &chanRestorer, &peerConnector, 182 ) 183 if err == nil { 184 t.Fatalf("restoration should have failed") 185 } 186 187 chanRestorer.fail = false 188 189 // If we make the peer connector fail, then the entire method should as 190 // well 191 peerConnector.fail = true 192 err = UnpackAndRecoverMulti( 193 packedMulti, keyRing, &chanRestorer, &peerConnector, 194 ) 195 if err == nil { 196 t.Fatalf("restoration should have failed") 197 } 198 199 chanRestorer.callCount-- 200 peerConnector.fail = false 201 202 // Next, we'll ensure that if all the interfaces function as expected, 203 // then the channels will properly be unpacked and restored. 204 err = UnpackAndRecoverMulti( 205 packedMulti, keyRing, &chanRestorer, &peerConnector, 206 ) 207 if err != nil { 208 t.Fatalf("unable to recover chans: %v", err) 209 } 210 211 // Both the restorer, and connector should have been called 10 times, 212 // once for each backup. 213 if chanRestorer.callCount != numSingles { 214 t.Fatalf("expected %v calls, instead got %v", 215 numSingles, chanRestorer.callCount) 216 } 217 if peerConnector.callCount != numSingles { 218 t.Fatalf("expected %v calls, instead got %v", 219 numSingles, peerConnector.callCount) 220 } 221 222 // If we modify the keyRing, then unpacking should fail. 223 keyRing.fail = true 224 err = UnpackAndRecoverMulti( 225 packedMulti, keyRing, &chanRestorer, &peerConnector, 226 ) 227 if err == nil { 228 t.Fatalf("unpacking should have failed") 229 } 230 231 // TODO(roasbeef): verify proper call args 232 }