bitbucket.org/number571/tendermint@v0.8.14/internal/p2p/test_util.go (about)

     1  package p2p
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	mrand "math/rand"
     7  	"net"
     8  
     9  	"bitbucket.org/number571/tendermint/libs/log"
    10  	tmnet "bitbucket.org/number571/tendermint/libs/net"
    11  	tmrand "bitbucket.org/number571/tendermint/libs/rand"
    12  	"bitbucket.org/number571/tendermint/types"
    13  
    14  	"bitbucket.org/number571/tendermint/config"
    15  	"bitbucket.org/number571/tendermint/internal/p2p/conn"
    16  )
    17  
    18  const testCh = 0x01
    19  
    20  //------------------------------------------------
    21  
    22  func AddPeerToSwitchPeerSet(sw *Switch, peer Peer) {
    23  	sw.peers.Add(peer) //nolint:errcheck // ignore error
    24  }
    25  
    26  func CreateRandomPeer(outbound bool) Peer {
    27  	addr, netAddr := CreateRoutableAddr()
    28  	p := &peer{
    29  		peerConn: peerConn{outbound: outbound},
    30  		nodeInfo: types.NodeInfo{
    31  			NodeID:     netAddr.ID,
    32  			ListenAddr: netAddr.DialString(),
    33  		},
    34  		metrics: NopMetrics(),
    35  	}
    36  	p.SetLogger(log.TestingLogger().With("peer", addr))
    37  	return p
    38  }
    39  
    40  // nolint:gosec // G404: Use of weak random number generator
    41  func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
    42  	for {
    43  		var err error
    44  		addr = fmt.Sprintf("%X@%v.%v.%v.%v:26656",
    45  			tmrand.Bytes(20),
    46  			mrand.Int()%256,
    47  			mrand.Int()%256,
    48  			mrand.Int()%256,
    49  			mrand.Int()%256)
    50  		netAddr, err = types.NewNetAddressString(addr)
    51  		if err != nil {
    52  			panic(err)
    53  		}
    54  		if netAddr.Routable() {
    55  			break
    56  		}
    57  	}
    58  	return
    59  }
    60  
    61  //------------------------------------------------------------------
    62  // Connects switches via arbitrary net.Conn. Used for testing.
    63  
    64  const TestHost = "localhost"
    65  
    66  // MakeConnectedSwitches returns n switches, connected according to the connect func.
    67  // If connect==Connect2Switches, the switches will be fully connected.
    68  // initSwitch defines how the i'th switch should be initialized (ie. with what reactors).
    69  // NOTE: panics if any switch fails to start.
    70  func MakeConnectedSwitches(cfg *config.P2PConfig,
    71  	n int,
    72  	initSwitch func(int, *Switch) *Switch,
    73  	connect func([]*Switch, int, int),
    74  ) []*Switch {
    75  	switches := make([]*Switch, n)
    76  	for i := 0; i < n; i++ {
    77  		switches[i] = MakeSwitch(cfg, i, TestHost, "123.123.123", initSwitch, log.TestingLogger())
    78  	}
    79  
    80  	if err := StartSwitches(switches); err != nil {
    81  		panic(err)
    82  	}
    83  
    84  	for i := 0; i < n; i++ {
    85  		for j := i + 1; j < n; j++ {
    86  			connect(switches, i, j)
    87  		}
    88  	}
    89  
    90  	return switches
    91  }
    92  
    93  // Connect2Switches will connect switches i and j via net.Pipe().
    94  // Blocks until a connection is established.
    95  // NOTE: caller ensures i and j are within bounds.
    96  func Connect2Switches(switches []*Switch, i, j int) {
    97  	switchI := switches[i]
    98  	switchJ := switches[j]
    99  
   100  	c1, c2 := conn.NetPipe()
   101  
   102  	doneCh := make(chan struct{})
   103  	go func() {
   104  		err := switchI.addPeerWithConnection(c1)
   105  		if err != nil {
   106  			panic(err)
   107  		}
   108  		doneCh <- struct{}{}
   109  	}()
   110  	go func() {
   111  		err := switchJ.addPeerWithConnection(c2)
   112  		if err != nil {
   113  			panic(err)
   114  		}
   115  		doneCh <- struct{}{}
   116  	}()
   117  	<-doneCh
   118  	<-doneCh
   119  }
   120  
   121  func (sw *Switch) addPeerWithConnection(conn net.Conn) error {
   122  	pc, err := testInboundPeerConn(sw.transport.(*MConnTransport), conn)
   123  	if err != nil {
   124  		if err := conn.Close(); err != nil {
   125  			sw.Logger.Error("Error closing connection", "err", err)
   126  		}
   127  		return err
   128  	}
   129  	peerNodeInfo, _, err := pc.conn.Handshake(context.Background(), sw.nodeInfo, sw.nodeKey.PrivKey)
   130  	if err != nil {
   131  		if err := conn.Close(); err != nil {
   132  			sw.Logger.Error("Error closing connection", "err", err)
   133  		}
   134  		return err
   135  	}
   136  
   137  	p := newPeer(
   138  		peerNodeInfo,
   139  		pc,
   140  		sw.reactorsByCh,
   141  		sw.StopPeerForError,
   142  	)
   143  
   144  	if err = sw.addPeer(p); err != nil {
   145  		pc.CloseConn()
   146  		return err
   147  	}
   148  
   149  	return nil
   150  }
   151  
   152  // StartSwitches calls sw.Start() for each given switch.
   153  // It returns the first encountered error.
   154  func StartSwitches(switches []*Switch) error {
   155  	for _, s := range switches {
   156  		err := s.Start() // start switch and reactors
   157  		if err != nil {
   158  			return err
   159  		}
   160  	}
   161  	return nil
   162  }
   163  
   164  func MakeSwitch(
   165  	cfg *config.P2PConfig,
   166  	i int,
   167  	network, version string,
   168  	initSwitch func(int, *Switch) *Switch,
   169  	logger log.Logger,
   170  	opts ...SwitchOption,
   171  ) *Switch {
   172  
   173  	nodeKey := types.GenNodeKey()
   174  	nodeInfo := testNodeInfo(nodeKey.ID, fmt.Sprintf("node%d", i))
   175  	addr, err := types.NewNetAddressString(
   176  		nodeKey.ID.AddressString(nodeInfo.ListenAddr),
   177  	)
   178  	if err != nil {
   179  		panic(err)
   180  	}
   181  
   182  	swLogger := logger.With("switch", i)
   183  	t := NewMConnTransport(swLogger, MConnConfig(cfg),
   184  		[]*ChannelDescriptor{}, MConnTransportOptions{})
   185  
   186  	// TODO: let the config be passed in?
   187  	sw := initSwitch(i, NewSwitch(cfg, t, opts...))
   188  	sw.SetLogger(swLogger)
   189  	sw.SetNodeKey(nodeKey)
   190  
   191  	if err := t.Listen(NewEndpoint(addr)); err != nil {
   192  		panic(err)
   193  	}
   194  
   195  	ni := nodeInfo
   196  	ni.Channels = []byte{}
   197  	for ch := range sw.reactorsByCh {
   198  		ni.Channels = append(ni.Channels, ch)
   199  	}
   200  	nodeInfo = ni
   201  
   202  	// TODO: We need to setup reactors ahead of time so the NodeInfo is properly
   203  	// populated and we don't have to do those awkward overrides and setters.
   204  	sw.SetNodeInfo(nodeInfo)
   205  
   206  	return sw
   207  }
   208  
   209  func testInboundPeerConn(
   210  	transport *MConnTransport,
   211  	conn net.Conn,
   212  ) (peerConn, error) {
   213  	return testPeerConn(transport, conn, false, false)
   214  }
   215  
   216  func testPeerConn(
   217  	transport *MConnTransport,
   218  	rawConn net.Conn,
   219  	outbound, persistent bool,
   220  ) (pc peerConn, err error) {
   221  
   222  	conn := newMConnConnection(transport.logger, rawConn, transport.mConnConfig, transport.channelDescs)
   223  
   224  	return newPeerConn(outbound, persistent, conn), nil
   225  }
   226  
   227  //----------------------------------------------------------------
   228  // rand node info
   229  
   230  func testNodeInfo(id types.NodeID, name string) types.NodeInfo {
   231  	return testNodeInfoWithNetwork(id, name, "testing")
   232  }
   233  
   234  func testNodeInfoWithNetwork(id types.NodeID, name, network string) types.NodeInfo {
   235  	return types.NodeInfo{
   236  		ProtocolVersion: defaultProtocolVersion,
   237  		NodeID:          id,
   238  		ListenAddr:      fmt.Sprintf("127.0.0.1:%d", getFreePort()),
   239  		Network:         network,
   240  		Version:         "1.2.3-rc0-deadbeef",
   241  		Channels:        []byte{testCh},
   242  		Moniker:         name,
   243  		Other: types.NodeInfoOther{
   244  			TxIndex:    "on",
   245  			RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
   246  		},
   247  	}
   248  }
   249  
   250  func getFreePort() int {
   251  	port, err := tmnet.GetFreePort()
   252  	if err != nil {
   253  		panic(err)
   254  	}
   255  	return port
   256  }
   257  
   258  type AddrBookMock struct {
   259  	Addrs        map[string]struct{}
   260  	OurAddrs     map[string]struct{}
   261  	PrivateAddrs map[string]struct{}
   262  }
   263  
   264  var _ AddrBook = (*AddrBookMock)(nil)
   265  
   266  func (book *AddrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error {
   267  	book.Addrs[addr.String()] = struct{}{}
   268  	return nil
   269  }
   270  func (book *AddrBookMock) AddOurAddress(addr *NetAddress) { book.OurAddrs[addr.String()] = struct{}{} }
   271  func (book *AddrBookMock) OurAddress(addr *NetAddress) bool {
   272  	_, ok := book.OurAddrs[addr.String()]
   273  	return ok
   274  }
   275  func (book *AddrBookMock) MarkGood(types.NodeID) {}
   276  func (book *AddrBookMock) HasAddress(addr *NetAddress) bool {
   277  	_, ok := book.Addrs[addr.String()]
   278  	return ok
   279  }
   280  func (book *AddrBookMock) RemoveAddress(addr *NetAddress) {
   281  	delete(book.Addrs, addr.String())
   282  }
   283  func (book *AddrBookMock) Save() {}
   284  func (book *AddrBookMock) AddPrivateIDs(addrs []string) {
   285  	for _, addr := range addrs {
   286  		book.PrivateAddrs[addr] = struct{}{}
   287  	}
   288  }