mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
233 lines
5.6 KiB
Go
233 lines
5.6 KiB
Go
|
package chanbackup
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/btcsuite/btcd/btcec"
|
||
|
)
|
||
|
|
||
|
type mockChannelRestorer struct {
|
||
|
fail bool
|
||
|
|
||
|
callCount int
|
||
|
}
|
||
|
|
||
|
func (m *mockChannelRestorer) RestoreChansFromSingles(...Single) error {
|
||
|
if m.fail {
|
||
|
return fmt.Errorf("fail")
|
||
|
}
|
||
|
|
||
|
m.callCount++
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type mockPeerConnector struct {
|
||
|
fail bool
|
||
|
|
||
|
callCount int
|
||
|
}
|
||
|
|
||
|
func (m *mockPeerConnector) ConnectPeer(node *btcec.PublicKey,
|
||
|
addrs []net.Addr) error {
|
||
|
|
||
|
if m.fail {
|
||
|
return fmt.Errorf("fail")
|
||
|
}
|
||
|
|
||
|
m.callCount++
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// TestUnpackAndRecoverSingles tests that we're able to properly unpack and
|
||
|
// recover a set of packed singles.
|
||
|
func TestUnpackAndRecoverSingles(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
keyRing := &mockKeyRing{}
|
||
|
|
||
|
// First, we'll create a number of single chan backups that we'll
|
||
|
// shortly back to so we can begin our recovery attempt.
|
||
|
numSingles := 10
|
||
|
backups := make([]Single, 0, numSingles)
|
||
|
var packedBackups PackedSingles
|
||
|
for i := 0; i < numSingles; i++ {
|
||
|
channel, err := genRandomOpenChannelShell()
|
||
|
if err != nil {
|
||
|
t.Fatalf("unable make channel: %v", err)
|
||
|
}
|
||
|
|
||
|
single := NewSingle(channel, nil)
|
||
|
|
||
|
var b bytes.Buffer
|
||
|
if err := single.PackToWriter(&b, keyRing); err != nil {
|
||
|
t.Fatalf("unable to pack single: %v", err)
|
||
|
}
|
||
|
|
||
|
backups = append(backups, single)
|
||
|
packedBackups = append(packedBackups, b.Bytes())
|
||
|
}
|
||
|
|
||
|
chanRestorer := mockChannelRestorer{}
|
||
|
peerConnector := mockPeerConnector{}
|
||
|
|
||
|
// Now that we have our backups (packed and unpacked), we'll attempt to
|
||
|
// restore them all in a single batch.
|
||
|
|
||
|
// If we make the channel restore fail, then the entire method should
|
||
|
// as well
|
||
|
chanRestorer.fail = true
|
||
|
err := UnpackAndRecoverSingles(
|
||
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("restoration should have failed")
|
||
|
}
|
||
|
|
||
|
chanRestorer.fail = false
|
||
|
|
||
|
// If we make the peer connector fail, then the entire method should as
|
||
|
// well
|
||
|
peerConnector.fail = true
|
||
|
err = UnpackAndRecoverSingles(
|
||
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("restoration should have failed")
|
||
|
}
|
||
|
|
||
|
chanRestorer.callCount--
|
||
|
peerConnector.fail = false
|
||
|
|
||
|
// Next, we'll ensure that if all the interfaces function as expected,
|
||
|
// then the channels will properly be unpacked and restored.
|
||
|
err = UnpackAndRecoverSingles(
|
||
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("unable to recover chans: %v", err)
|
||
|
}
|
||
|
|
||
|
// Both the restorer, and connector should have been called 10 times,
|
||
|
// once for each backup.
|
||
|
if chanRestorer.callCount != numSingles {
|
||
|
t.Fatalf("expected %v calls, instead got %v",
|
||
|
numSingles, chanRestorer.callCount)
|
||
|
}
|
||
|
if peerConnector.callCount != numSingles {
|
||
|
t.Fatalf("expected %v calls, instead got %v",
|
||
|
numSingles, peerConnector.callCount)
|
||
|
}
|
||
|
|
||
|
// If we modify the keyRing, then unpacking should fail.
|
||
|
keyRing.fail = true
|
||
|
err = UnpackAndRecoverSingles(
|
||
|
packedBackups, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("unpacking should have failed")
|
||
|
}
|
||
|
|
||
|
// TODO(roasbeef): verify proper call args
|
||
|
}
|
||
|
|
||
|
// TestUnpackAndRecoverMulti tests that we're able to properly unpack and
|
||
|
// recover a packed multi.
|
||
|
func TestUnpackAndRecoverMulti(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
keyRing := &mockKeyRing{}
|
||
|
|
||
|
// First, we'll create a number of single chan backups that we'll
|
||
|
// shortly back to so we can begin our recovery attempt.
|
||
|
numSingles := 10
|
||
|
backups := make([]Single, 0, numSingles)
|
||
|
for i := 0; i < numSingles; i++ {
|
||
|
channel, err := genRandomOpenChannelShell()
|
||
|
if err != nil {
|
||
|
t.Fatalf("unable make channel: %v", err)
|
||
|
}
|
||
|
|
||
|
single := NewSingle(channel, nil)
|
||
|
|
||
|
backups = append(backups, single)
|
||
|
}
|
||
|
|
||
|
multi := Multi{
|
||
|
StaticBackups: backups,
|
||
|
}
|
||
|
|
||
|
var b bytes.Buffer
|
||
|
if err := multi.PackToWriter(&b, keyRing); err != nil {
|
||
|
t.Fatalf("unable to pack multi: %v", err)
|
||
|
}
|
||
|
|
||
|
// Next, we'll pack the set of singles into a packed multi, and also
|
||
|
// create the set of interfaces we need to carry out the remainder of
|
||
|
// the test.
|
||
|
packedMulti := PackedMulti(b.Bytes())
|
||
|
|
||
|
chanRestorer := mockChannelRestorer{}
|
||
|
peerConnector := mockPeerConnector{}
|
||
|
|
||
|
// If we make the channel restore fail, then the entire method should
|
||
|
// as well
|
||
|
chanRestorer.fail = true
|
||
|
err := UnpackAndRecoverMulti(
|
||
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("restoration should have failed")
|
||
|
}
|
||
|
|
||
|
chanRestorer.fail = false
|
||
|
|
||
|
// If we make the peer connector fail, then the entire method should as
|
||
|
// well
|
||
|
peerConnector.fail = true
|
||
|
err = UnpackAndRecoverMulti(
|
||
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("restoration should have failed")
|
||
|
}
|
||
|
|
||
|
chanRestorer.callCount--
|
||
|
peerConnector.fail = false
|
||
|
|
||
|
// Next, we'll ensure that if all the interfaces function as expected,
|
||
|
// then the channels will properly be unpacked and restored.
|
||
|
err = UnpackAndRecoverMulti(
|
||
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err != nil {
|
||
|
t.Fatalf("unable to recover chans: %v", err)
|
||
|
}
|
||
|
|
||
|
// Both the restorer, and connector should have been called 10 times,
|
||
|
// once for each backup.
|
||
|
if chanRestorer.callCount != numSingles {
|
||
|
t.Fatalf("expected %v calls, instead got %v",
|
||
|
numSingles, chanRestorer.callCount)
|
||
|
}
|
||
|
if peerConnector.callCount != numSingles {
|
||
|
t.Fatalf("expected %v calls, instead got %v",
|
||
|
numSingles, peerConnector.callCount)
|
||
|
}
|
||
|
|
||
|
// If we modify the keyRing, then unpacking should fail.
|
||
|
keyRing.fail = true
|
||
|
err = UnpackAndRecoverMulti(
|
||
|
packedMulti, keyRing, &chanRestorer, &peerConnector,
|
||
|
)
|
||
|
if err == nil {
|
||
|
t.Fatalf("unpacking should have failed")
|
||
|
}
|
||
|
|
||
|
// TODO(roasbeef): verify proper call args
|
||
|
}
|