github.com/decred/dcrlnd@v0.7.6/discovery/reliable_sender_test.go (about)

     1  package discovery
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/davecgh/go-spew/spew"
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    10  	"github.com/decred/dcrlnd/lnpeer"
    11  	"github.com/decred/dcrlnd/lntest/wait"
    12  	"github.com/decred/dcrlnd/lnwire"
    13  )
    14  
    15  // newTestReliableSender creates a new reliable sender instance used for
    16  // testing.
    17  func newTestReliableSender(t *testing.T) *reliableSender {
    18  	t.Helper()
    19  
    20  	cfg := &reliableSenderCfg{
    21  		NotifyWhenOnline: func(pubKey [33]byte,
    22  			peerChan chan<- lnpeer.Peer) {
    23  			pk, err := secp256k1.ParsePubKey(pubKey[:])
    24  			if err != nil {
    25  				t.Fatalf("unable to parse pubkey: %v", err)
    26  			}
    27  			peerChan <- &mockPeer{pk: pk}
    28  		},
    29  		NotifyWhenOffline: func(_ [33]byte) <-chan struct{} {
    30  			c := make(chan struct{}, 1)
    31  			return c
    32  		},
    33  		MessageStore: newMockMessageStore(),
    34  		IsMsgStale: func(lnwire.Message) bool {
    35  			return false
    36  		},
    37  	}
    38  
    39  	return newReliableSender(cfg)
    40  }
    41  
    42  // assertMsgsSent ensures that the given messages can be read from a mock peer's
    43  // msgChan.
    44  func assertMsgsSent(t *testing.T, msgChan chan lnwire.Message,
    45  	msgs ...lnwire.Message) {
    46  
    47  	t.Helper()
    48  
    49  	m := make(map[lnwire.Message]struct{}, len(msgs))
    50  	for _, msg := range msgs {
    51  		m[msg] = struct{}{}
    52  	}
    53  
    54  	for i := 0; i < len(msgs); i++ {
    55  		select {
    56  		case msg := <-msgChan:
    57  			if _, ok := m[msg]; !ok {
    58  				t.Fatalf("found unexpected message sent: %v",
    59  					spew.Sdump(msg))
    60  			}
    61  		case <-time.After(time.Second):
    62  			t.Fatal("reliable sender did not send message to peer")
    63  		}
    64  	}
    65  }
    66  
    67  // TestReliableSenderFlow ensures that the flow for sending messages reliably to
    68  // a peer while taking into account its connection lifecycle works as expected.
    69  func TestReliableSenderFlow(t *testing.T) {
    70  	t.Parallel()
    71  
    72  	reliableSender := newTestReliableSender(t)
    73  
    74  	// Create a mock peer to send the messages to.
    75  	pubKey := randPubKey(t)
    76  	msgsSent := make(chan lnwire.Message)
    77  	peer := &mockPeer{pubKey, msgsSent, reliableSender.quit}
    78  
    79  	// Override NotifyWhenOnline and NotifyWhenOffline to provide the
    80  	// notification channels so that we can control when notifications get
    81  	// dispatched.
    82  	notifyOnline := make(chan chan<- lnpeer.Peer, 2)
    83  	notifyOffline := make(chan chan struct{}, 1)
    84  
    85  	reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte,
    86  		peerChan chan<- lnpeer.Peer) {
    87  		notifyOnline <- peerChan
    88  	}
    89  	reliableSender.cfg.NotifyWhenOffline = func(_ [33]byte) <-chan struct{} {
    90  		c := make(chan struct{}, 1)
    91  		notifyOffline <- c
    92  		return c
    93  	}
    94  
    95  	// We'll start by creating our first message which we should reliably
    96  	// send to our peer.
    97  	msg1 := randChannelUpdate()
    98  	var peerPubKey [33]byte
    99  	copy(peerPubKey[:], pubKey.SerializeCompressed())
   100  	if err := reliableSender.sendMessage(msg1, peerPubKey); err != nil {
   101  		t.Fatalf("unable to reliably send message: %v", err)
   102  	}
   103  
   104  	// Since there isn't a peerHandler for this peer currently active due to
   105  	// this being the first message being sent reliably, we should expect to
   106  	// see a notification request for when the peer is online.
   107  	var peerChan chan<- lnpeer.Peer
   108  	select {
   109  	case peerChan = <-notifyOnline:
   110  	case <-time.After(time.Second):
   111  		t.Fatal("reliable sender did not request online notification")
   112  	}
   113  
   114  	// We'll then attempt to send another additional message reliably.
   115  	msg2 := randAnnounceSignatures()
   116  	if err := reliableSender.sendMessage(msg2, peerPubKey); err != nil {
   117  		t.Fatalf("unable to reliably send message: %v", err)
   118  	}
   119  
   120  	// This should not however request another peer online notification as
   121  	// the peerHandler has already been started and is waiting for the
   122  	// notification to be dispatched.
   123  	select {
   124  	case <-notifyOnline:
   125  		t.Fatal("reliable sender should not request online notification")
   126  	case <-time.After(time.Second):
   127  	}
   128  
   129  	// We'll go ahead and notify the peer.
   130  	peerChan <- peer
   131  
   132  	// By doing so, we should expect to see a notification request for when
   133  	// the peer is offline.
   134  	var offlineChan chan struct{}
   135  	select {
   136  	case offlineChan = <-notifyOffline:
   137  	case <-time.After(time.Second):
   138  		t.Fatal("reliable sender did not request offline notification")
   139  	}
   140  
   141  	// We should also see the messages arrive at the peer since they are now
   142  	// seen as online.
   143  	assertMsgsSent(t, peer.sentMsgs, msg1, msg2)
   144  
   145  	// Then, we'll send one more message reliably.
   146  	msg3 := randChannelUpdate()
   147  	if err := reliableSender.sendMessage(msg3, peerPubKey); err != nil {
   148  		t.Fatalf("unable to reliably send message: %v", err)
   149  	}
   150  
   151  	// Again, this should not request another peer online notification
   152  	// request since we are currently waiting for the peer to be offline.
   153  	select {
   154  	case <-notifyOnline:
   155  		t.Fatal("reliable sender should not request online notification")
   156  	case <-time.After(time.Second):
   157  	}
   158  
   159  	// The expected message should be sent to the peer.
   160  	assertMsgsSent(t, peer.sentMsgs, msg3)
   161  
   162  	// We'll then notify that the peer is offline.
   163  	close(offlineChan)
   164  
   165  	// This should cause an online notification to be requested.
   166  	select {
   167  	case peerChan = <-notifyOnline:
   168  	case <-time.After(time.Second):
   169  		t.Fatal("reliable sender did not request online notification")
   170  	}
   171  
   172  	// Once we dispatch it, we should expect to see the messages be resent
   173  	// to the peer as they are not stale.
   174  	peerChan <- peer
   175  
   176  	select {
   177  	case <-notifyOffline:
   178  	case <-time.After(5 * time.Second):
   179  		t.Fatal("reliable sender did not request offline notification")
   180  	}
   181  
   182  	assertMsgsSent(t, peer.sentMsgs, msg1, msg2, msg3)
   183  }
   184  
   185  // TestReliableSenderStaleMessages ensures that the reliable sender is no longer
   186  // active for a peer which has successfully sent all of its messages and deemed
   187  // them as stale.
   188  func TestReliableSenderStaleMessages(t *testing.T) {
   189  	t.Parallel()
   190  
   191  	reliableSender := newTestReliableSender(t)
   192  
   193  	// Create a mock peer to send the messages to.
   194  	pubKey := randPubKey(t)
   195  	msgsSent := make(chan lnwire.Message)
   196  	peer := &mockPeer{pubKey, msgsSent, reliableSender.quit}
   197  
   198  	// Override NotifyWhenOnline to provide the notification channel so that
   199  	// we can control when notifications get dispatched.
   200  	notifyOnline := make(chan chan<- lnpeer.Peer, 1)
   201  	reliableSender.cfg.NotifyWhenOnline = func(_ [33]byte,
   202  		peerChan chan<- lnpeer.Peer) {
   203  		notifyOnline <- peerChan
   204  	}
   205  
   206  	// We'll also override IsMsgStale to mark all messages as stale as we're
   207  	// interested in testing the stale message behavior.
   208  	reliableSender.cfg.IsMsgStale = func(_ lnwire.Message) bool {
   209  		return true
   210  	}
   211  
   212  	// We'll start by creating our first message which we should reliably
   213  	// send to our peer, but will be seen as stale.
   214  	msg1 := randAnnounceSignatures()
   215  	var peerPubKey [33]byte
   216  	copy(peerPubKey[:], pubKey.SerializeCompressed())
   217  	if err := reliableSender.sendMessage(msg1, peerPubKey); err != nil {
   218  		t.Fatalf("unable to reliably send message: %v", err)
   219  	}
   220  
   221  	// Since there isn't a peerHandler for this peer currently active due to
   222  	// this being the first message being sent reliably, we should expect to
   223  	// see a notification request for when the peer is online.
   224  	var peerChan chan<- lnpeer.Peer
   225  	select {
   226  	case peerChan = <-notifyOnline:
   227  	case <-time.After(time.Second):
   228  		t.Fatal("reliable sender did not request online notification")
   229  	}
   230  
   231  	// We'll go ahead and notify the peer.
   232  	peerChan <- peer
   233  
   234  	// This should cause the message to be sent to the peer since they are
   235  	// now seen as online. The message will be sent at least once to ensure
   236  	// they can propagate before deciding whether they are stale or not.
   237  	assertMsgsSent(t, peer.sentMsgs, msg1)
   238  
   239  	// We'll create another message which we'll send reliably. This one
   240  	// won't be seen as stale.
   241  	msg2 := randChannelUpdate()
   242  
   243  	// We'll then wait for the message to be removed from the backing
   244  	// message store since it is seen as stale and has been sent at least
   245  	// once. Once the message is removed, the peerHandler should be torn
   246  	// down as there are no longer any pending messages within the store.
   247  	err := wait.NoError(func() error {
   248  		msgs, err := reliableSender.cfg.MessageStore.MessagesForPeer(
   249  			peerPubKey,
   250  		)
   251  		if err != nil {
   252  			return fmt.Errorf("unable to retrieve messages for "+
   253  				"peer: %v", err)
   254  		}
   255  		if len(msgs) != 0 {
   256  			return fmt.Errorf("expected to not find any "+
   257  				"messages for peer, found %d", len(msgs))
   258  		}
   259  
   260  		return nil
   261  	}, time.Second)
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  
   266  	// Override IsMsgStale to no longer mark messages as stale.
   267  	reliableSender.cfg.IsMsgStale = func(_ lnwire.Message) bool {
   268  		return false
   269  	}
   270  
   271  	// We'll request the message to be sent reliably.
   272  	if err := reliableSender.sendMessage(msg2, peerPubKey); err != nil {
   273  		t.Fatalf("unable to reliably send message: %v", err)
   274  	}
   275  
   276  	// We should see an online notification request indicating that a new
   277  	// peerHandler has been spawned since it was previously torn down.
   278  	select {
   279  	case peerChan = <-notifyOnline:
   280  	case <-time.After(time.Second):
   281  		t.Fatal("reliable sender did not request online notification")
   282  	}
   283  
   284  	// Finally, notifying the peer is online should prompt the message to be
   285  	// sent. Only the ChannelUpdate will be sent in this case since the
   286  	// AnnounceSignatures message above was seen as stale.
   287  	peerChan <- peer
   288  
   289  	assertMsgsSent(t, peer.sentMsgs, msg2)
   290  }