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 }