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  }