github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/whisper/whisperv2/peer_test.go (about)

     1  // Copyright 2015 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package whisperv2
    18  
    19  import (
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    24  	"github.com/SmartMeshFoundation/Spectrum/p2p/discover"
    25  )
    26  
    27  type testPeer struct {
    28  	client *Whisper
    29  	stream *p2p.MsgPipeRW
    30  	termed chan struct{}
    31  }
    32  
    33  func startTestPeer() *testPeer {
    34  	// Create a simulated P2P remote peer and data streams to it
    35  	remote := p2p.NewPeer(discover.NodeID{}, "", nil)
    36  	tester, tested := p2p.MsgPipe()
    37  
    38  	// Create a whisper client and connect with it to the tester peer
    39  	client := New()
    40  	client.Start(nil)
    41  
    42  	termed := make(chan struct{})
    43  	go func() {
    44  		defer client.Stop()
    45  		defer close(termed)
    46  		defer tested.Close()
    47  
    48  		client.handlePeer(remote, tested)
    49  	}()
    50  
    51  	return &testPeer{
    52  		client: client,
    53  		stream: tester,
    54  		termed: termed,
    55  	}
    56  }
    57  
    58  func startTestPeerInited() (*testPeer, error) {
    59  	peer := startTestPeer()
    60  
    61  	if err := p2p.ExpectMsg(peer.stream, statusCode, []uint64{protocolVersion}); err != nil {
    62  		peer.stream.Close()
    63  		return nil, err
    64  	}
    65  	if err := p2p.SendItems(peer.stream, statusCode, protocolVersion); err != nil {
    66  		peer.stream.Close()
    67  		return nil, err
    68  	}
    69  	return peer, nil
    70  }
    71  
    72  func TestPeerStatusMessage(t *testing.T) {
    73  	tester := startTestPeer()
    74  
    75  	// Wait for the handshake status message and check it
    76  	if err := p2p.ExpectMsg(tester.stream, statusCode, []uint64{protocolVersion}); err != nil {
    77  		t.Fatalf("status message mismatch: %v", err)
    78  	}
    79  	// Terminate the node
    80  	tester.stream.Close()
    81  
    82  	select {
    83  	case <-tester.termed:
    84  	case <-time.After(time.Second):
    85  		t.Fatalf("local close timed out")
    86  	}
    87  }
    88  
    89  func TestPeerHandshakeFail(t *testing.T) {
    90  	tester := startTestPeer()
    91  
    92  	// Wait for and check the handshake
    93  	if err := p2p.ExpectMsg(tester.stream, statusCode, []uint64{protocolVersion}); err != nil {
    94  		t.Fatalf("status message mismatch: %v", err)
    95  	}
    96  	// Send an invalid handshake status and verify disconnect
    97  	if err := p2p.SendItems(tester.stream, messagesCode); err != nil {
    98  		t.Fatalf("failed to send malformed status: %v", err)
    99  	}
   100  	select {
   101  	case <-tester.termed:
   102  	case <-time.After(time.Second):
   103  		t.Fatalf("remote close timed out")
   104  	}
   105  }
   106  
   107  func TestPeerHandshakeSuccess(t *testing.T) {
   108  	tester := startTestPeer()
   109  
   110  	// Wait for and check the handshake
   111  	if err := p2p.ExpectMsg(tester.stream, statusCode, []uint64{protocolVersion}); err != nil {
   112  		t.Fatalf("status message mismatch: %v", err)
   113  	}
   114  	// Send a valid handshake status and make sure connection stays live
   115  	if err := p2p.SendItems(tester.stream, statusCode, protocolVersion); err != nil {
   116  		t.Fatalf("failed to send status: %v", err)
   117  	}
   118  	select {
   119  	case <-tester.termed:
   120  		t.Fatalf("valid handshake disconnected")
   121  
   122  	case <-time.After(100 * time.Millisecond):
   123  	}
   124  	// Clean up the test
   125  	tester.stream.Close()
   126  
   127  	select {
   128  	case <-tester.termed:
   129  	case <-time.After(time.Second):
   130  		t.Fatalf("local close timed out")
   131  	}
   132  }
   133  
   134  func TestPeerSend(t *testing.T) {
   135  	// Start a tester and execute the handshake
   136  	tester, err := startTestPeerInited()
   137  	if err != nil {
   138  		t.Fatalf("failed to start initialized peer: %v", err)
   139  	}
   140  	defer tester.stream.Close()
   141  
   142  	// Construct a message and inject into the tester
   143  	message := NewMessage([]byte("peer broadcast test message"))
   144  	envelope, err := message.Wrap(DefaultPoW, Options{
   145  		TTL: DefaultTTL,
   146  	})
   147  	if err != nil {
   148  		t.Fatalf("failed to wrap message: %v", err)
   149  	}
   150  	if err := tester.client.Send(envelope); err != nil {
   151  		t.Fatalf("failed to send message: %v", err)
   152  	}
   153  	// Check that the message is eventually forwarded
   154  	payload := []interface{}{envelope}
   155  	if err := p2p.ExpectMsg(tester.stream, messagesCode, payload); err != nil {
   156  		t.Fatalf("message mismatch: %v", err)
   157  	}
   158  	// Make sure that even with a re-insert, an empty batch is received
   159  	if err := tester.client.Send(envelope); err != nil {
   160  		t.Fatalf("failed to send message: %v", err)
   161  	}
   162  	if err := p2p.ExpectMsg(tester.stream, messagesCode, []interface{}{}); err != nil {
   163  		t.Fatalf("message mismatch: %v", err)
   164  	}
   165  }
   166  
   167  func TestPeerDeliver(t *testing.T) {
   168  	// Start a tester and execute the handshake
   169  	tester, err := startTestPeerInited()
   170  	if err != nil {
   171  		t.Fatalf("failed to start initialized peer: %v", err)
   172  	}
   173  	defer tester.stream.Close()
   174  
   175  	// Watch for all inbound messages
   176  	arrived := make(chan struct{}, 1)
   177  	tester.client.Watch(Filter{
   178  		Fn: func(message *Message) {
   179  			arrived <- struct{}{}
   180  		},
   181  	})
   182  	// Construct a message and deliver it to the tester peer
   183  	message := NewMessage([]byte("peer broadcast test message"))
   184  	envelope, err := message.Wrap(DefaultPoW, Options{
   185  		TTL: DefaultTTL,
   186  	})
   187  	if err != nil {
   188  		t.Fatalf("failed to wrap message: %v", err)
   189  	}
   190  	if err := p2p.Send(tester.stream, messagesCode, []*Envelope{envelope}); err != nil {
   191  		t.Fatalf("failed to transfer message: %v", err)
   192  	}
   193  	// Check that the message is delivered upstream
   194  	select {
   195  	case <-arrived:
   196  	case <-time.After(time.Second):
   197  		t.Fatalf("message delivery timeout")
   198  	}
   199  	// Check that a resend is not delivered
   200  	if err := p2p.Send(tester.stream, messagesCode, []*Envelope{envelope}); err != nil {
   201  		t.Fatalf("failed to transfer message: %v", err)
   202  	}
   203  	select {
   204  	case <-time.After(2 * transmissionCycle):
   205  	case <-arrived:
   206  		t.Fatalf("repeating message arrived")
   207  	}
   208  }
   209  
   210  func TestPeerMessageExpiration(t *testing.T) {
   211  	// Start a tester and execute the handshake
   212  	tester, err := startTestPeerInited()
   213  	if err != nil {
   214  		t.Fatalf("failed to start initialized peer: %v", err)
   215  	}
   216  	defer tester.stream.Close()
   217  
   218  	// Fetch the peer instance for later inspection
   219  	tester.client.peerMu.RLock()
   220  	if peers := len(tester.client.peers); peers != 1 {
   221  		t.Fatalf("peer pool size mismatch: have %v, want %v", peers, 1)
   222  	}
   223  	var peer *peer
   224  	for peer = range tester.client.peers {
   225  		break
   226  	}
   227  	tester.client.peerMu.RUnlock()
   228  
   229  	// Construct a message and pass it through the tester
   230  	message := NewMessage([]byte("peer test message"))
   231  	envelope, err := message.Wrap(DefaultPoW, Options{
   232  		TTL: time.Second,
   233  	})
   234  	if err != nil {
   235  		t.Fatalf("failed to wrap message: %v", err)
   236  	}
   237  	if err := tester.client.Send(envelope); err != nil {
   238  		t.Fatalf("failed to send message: %v", err)
   239  	}
   240  	payload := []interface{}{envelope}
   241  	if err := p2p.ExpectMsg(tester.stream, messagesCode, payload); err != nil {
   242  		// A premature empty message may have been broadcast, check the next too
   243  		if err := p2p.ExpectMsg(tester.stream, messagesCode, payload); err != nil {
   244  			t.Fatalf("message mismatch: %v", err)
   245  		}
   246  	}
   247  	// Check that the message is inside the cache
   248  	if !peer.known.Has(envelope.Hash()) {
   249  		t.Fatalf("message not found in cache")
   250  	}
   251  	// Discard messages until expiration and check cache again
   252  	exp := time.Now().Add(time.Second + 2*expirationCycle + 100*time.Millisecond)
   253  	for time.Now().Before(exp) {
   254  		if err := p2p.ExpectMsg(tester.stream, messagesCode, []interface{}{}); err != nil {
   255  			t.Fatalf("message mismatch: %v", err)
   256  		}
   257  	}
   258  	if peer.known.Has(envelope.Hash()) {
   259  		t.Fatalf("message not expired from cache")
   260  	}
   261  }