github.com/susy-go/susy-graviton@v0.0.0-20190614130430-36cddae42305/swarm/network/protocol_test.go (about)

     1  // Copyleft 2016 The susy-graviton Authors
     2  // This file is part of the susy-graviton library.
     3  //
     4  // The susy-graviton 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 susy-graviton library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MSRCHANTABILITY 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 susy-graviton library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package network
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"os"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/susy-go/susy-graviton/log"
    27  	"github.com/susy-go/susy-graviton/p2p"
    28  	"github.com/susy-go/susy-graviton/p2p/enode"
    29  	"github.com/susy-go/susy-graviton/p2p/protocols"
    30  	p2ptest "github.com/susy-go/susy-graviton/p2p/testing"
    31  )
    32  
    33  const (
    34  	TestProtocolVersion   = 8
    35  	TestProtocolNetworkID = 3
    36  )
    37  
    38  var (
    39  	loglevel = flag.Int("loglevel", 2, "verbosity of logs")
    40  )
    41  
    42  func init() {
    43  	flag.Parse()
    44  	log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
    45  }
    46  
    47  func HandshakeMsgExchange(lhs, rhs *HandshakeMsg, id enode.ID) []p2ptest.Exchange {
    48  	return []p2ptest.Exchange{
    49  		{
    50  			Expects: []p2ptest.Expect{
    51  				{
    52  					Code: 0,
    53  					Msg:  lhs,
    54  					Peer: id,
    55  				},
    56  			},
    57  		},
    58  		{
    59  			Triggers: []p2ptest.Trigger{
    60  				{
    61  					Code: 0,
    62  					Msg:  rhs,
    63  					Peer: id,
    64  				},
    65  			},
    66  		},
    67  	}
    68  }
    69  
    70  func newBzzBaseTester(t *testing.T, n int, addr *BzzAddr, spec *protocols.Spec, run func(*BzzPeer) error) *bzzTester {
    71  	cs := make(map[string]chan bool)
    72  
    73  	srv := func(p *BzzPeer) error {
    74  		defer func() {
    75  			if cs[p.ID().String()] != nil {
    76  				close(cs[p.ID().String()])
    77  			}
    78  		}()
    79  		return run(p)
    80  	}
    81  
    82  	protocol := func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
    83  		return srv(&BzzPeer{Peer: protocols.NewPeer(p, rw, spec), BzzAddr: NewAddr(p.Node())})
    84  	}
    85  
    86  	s := p2ptest.NewProtocolTester(addr.ID(), n, protocol)
    87  
    88  	for _, node := range s.Nodes {
    89  		cs[node.ID().String()] = make(chan bool)
    90  	}
    91  
    92  	return &bzzTester{
    93  		addr:           addr,
    94  		ProtocolTester: s,
    95  		cs:             cs,
    96  	}
    97  }
    98  
    99  type bzzTester struct {
   100  	*p2ptest.ProtocolTester
   101  	addr *BzzAddr
   102  	cs   map[string]chan bool
   103  	bzz  *Bzz
   104  }
   105  
   106  func newBzz(addr *BzzAddr, lightNode bool) *Bzz {
   107  	config := &BzzConfig{
   108  		OverlayAddr:  addr.Over(),
   109  		UnderlayAddr: addr.Under(),
   110  		HiveParams:   NewHiveParams(),
   111  		NetworkID:    DefaultNetworkID,
   112  		LightNode:    lightNode,
   113  	}
   114  	kad := NewKademlia(addr.OAddr, NewKadParams())
   115  	bzz := NewBzz(config, kad, nil, nil, nil)
   116  	return bzz
   117  }
   118  
   119  func newBzzHandshakeTester(n int, addr *BzzAddr, lightNode bool) *bzzTester {
   120  	bzz := newBzz(addr, lightNode)
   121  	pt := p2ptest.NewProtocolTester(addr.ID(), n, bzz.runBzz)
   122  
   123  	return &bzzTester{
   124  		addr:           addr,
   125  		ProtocolTester: pt,
   126  		bzz:            bzz,
   127  	}
   128  }
   129  
   130  // should test handshakes in one exchange? parallelisation
   131  func (s *bzzTester) testHandshake(lhs, rhs *HandshakeMsg, disconnects ...*p2ptest.Disconnect) error {
   132  	if err := s.TestExchanges(HandshakeMsgExchange(lhs, rhs, rhs.Addr.ID())...); err != nil {
   133  		return err
   134  	}
   135  
   136  	if len(disconnects) > 0 {
   137  		return s.TestDisconnected(disconnects...)
   138  	}
   139  
   140  	// If we don't expect disconnect, ensure peers remain connected
   141  	err := s.TestDisconnected(&p2ptest.Disconnect{
   142  		Peer:  s.Nodes[0].ID(),
   143  		Error: nil,
   144  	})
   145  
   146  	if err == nil {
   147  		return fmt.Errorf("Unexpected peer disconnect")
   148  	}
   149  
   150  	if err.Error() != "timed out waiting for peers to disconnect" {
   151  		return err
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  func correctBzzHandshake(addr *BzzAddr, lightNode bool) *HandshakeMsg {
   158  	return &HandshakeMsg{
   159  		Version:   TestProtocolVersion,
   160  		NetworkID: TestProtocolNetworkID,
   161  		Addr:      addr,
   162  		LightNode: lightNode,
   163  	}
   164  }
   165  
   166  func TestBzzHandshakeNetworkIDMismatch(t *testing.T) {
   167  	lightNode := false
   168  	addr := RandomAddr()
   169  	s := newBzzHandshakeTester(1, addr, lightNode)
   170  	node := s.Nodes[0]
   171  
   172  	err := s.testHandshake(
   173  		correctBzzHandshake(addr, lightNode),
   174  		&HandshakeMsg{Version: TestProtocolVersion, NetworkID: 321, Addr: NewAddr(node)},
   175  		&p2ptest.Disconnect{Peer: node.ID(), Error: fmt.Errorf("Handshake error: Message handler error: (msg code 0): network id mismatch 321 (!= 3)")},
   176  	)
   177  
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  }
   182  
   183  func TestBzzHandshakeVersionMismatch(t *testing.T) {
   184  	lightNode := false
   185  	addr := RandomAddr()
   186  	s := newBzzHandshakeTester(1, addr, lightNode)
   187  	node := s.Nodes[0]
   188  
   189  	err := s.testHandshake(
   190  		correctBzzHandshake(addr, lightNode),
   191  		&HandshakeMsg{Version: 0, NetworkID: TestProtocolNetworkID, Addr: NewAddr(node)},
   192  		&p2ptest.Disconnect{Peer: node.ID(), Error: fmt.Errorf("Handshake error: Message handler error: (msg code 0): version mismatch 0 (!= %d)", TestProtocolVersion)},
   193  	)
   194  
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  }
   199  
   200  func TestBzzHandshakeSuccess(t *testing.T) {
   201  	lightNode := false
   202  	addr := RandomAddr()
   203  	s := newBzzHandshakeTester(1, addr, lightNode)
   204  	node := s.Nodes[0]
   205  
   206  	err := s.testHandshake(
   207  		correctBzzHandshake(addr, lightNode),
   208  		&HandshakeMsg{Version: TestProtocolVersion, NetworkID: TestProtocolNetworkID, Addr: NewAddr(node)},
   209  	)
   210  
   211  	if err != nil {
   212  		t.Fatal(err)
   213  	}
   214  }
   215  
   216  func TestBzzHandshakeLightNode(t *testing.T) {
   217  	var lightNodeTests = []struct {
   218  		name      string
   219  		lightNode bool
   220  	}{
   221  		{"on", true},
   222  		{"off", false},
   223  	}
   224  
   225  	for _, test := range lightNodeTests {
   226  		t.Run(test.name, func(t *testing.T) {
   227  			randomAddr := RandomAddr()
   228  			pt := newBzzHandshakeTester(1, randomAddr, false)
   229  
   230  			node := pt.Nodes[0]
   231  			addr := NewAddr(node)
   232  
   233  			err := pt.testHandshake(
   234  				correctBzzHandshake(randomAddr, false),
   235  				&HandshakeMsg{Version: TestProtocolVersion, NetworkID: TestProtocolNetworkID, Addr: addr, LightNode: test.lightNode},
   236  			)
   237  
   238  			if err != nil {
   239  				t.Fatal(err)
   240  			}
   241  
   242  			select {
   243  
   244  			case <-pt.bzz.handshakes[node.ID()].done:
   245  				if pt.bzz.handshakes[node.ID()].LightNode != test.lightNode {
   246  					t.Fatalf("peer LightNode flag is %v, should be %v", pt.bzz.handshakes[node.ID()].LightNode, test.lightNode)
   247  				}
   248  			case <-time.After(10 * time.Second):
   249  				t.Fatal("test timeout")
   250  			}
   251  		})
   252  	}
   253  }