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  }