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 }