github.com/pure-x-eth/consensus_tm@v0.0.0-20230502163723-e3c2ff987250/p2p/switch_test.go (about) 1 package p2p 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io" 8 "net" 9 "net/http" 10 "net/http/httptest" 11 "regexp" 12 "strconv" 13 "sync/atomic" 14 "testing" 15 "time" 16 17 "github.com/gogo/protobuf/proto" 18 "github.com/prometheus/client_golang/prometheus/promhttp" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/require" 21 22 "github.com/pure-x-eth/consensus_tm/config" 23 "github.com/pure-x-eth/consensus_tm/crypto/ed25519" 24 "github.com/pure-x-eth/consensus_tm/libs/log" 25 tmsync "github.com/pure-x-eth/consensus_tm/libs/sync" 26 "github.com/pure-x-eth/consensus_tm/p2p/conn" 27 p2pproto "github.com/pure-x-eth/consensus_tm/proto/tendermint/p2p" 28 ) 29 30 var cfg *config.P2PConfig 31 32 func init() { 33 cfg = config.DefaultP2PConfig() 34 cfg.PexReactor = true 35 cfg.AllowDuplicateIP = true 36 } 37 38 type PeerMessage struct { 39 Contents proto.Message 40 Counter int 41 } 42 43 type TestReactor struct { 44 BaseReactor 45 46 mtx tmsync.Mutex 47 channels []*conn.ChannelDescriptor 48 logMessages bool 49 msgsCounter int 50 msgsReceived map[byte][]PeerMessage 51 } 52 53 func NewTestReactor(channels []*conn.ChannelDescriptor, logMessages bool) *TestReactor { 54 tr := &TestReactor{ 55 channels: channels, 56 logMessages: logMessages, 57 msgsReceived: make(map[byte][]PeerMessage), 58 } 59 tr.BaseReactor = *NewBaseReactor("TestReactor", tr) 60 tr.SetLogger(log.TestingLogger()) 61 return tr 62 } 63 64 func (tr *TestReactor) GetChannels() []*conn.ChannelDescriptor { 65 return tr.channels 66 } 67 68 func (tr *TestReactor) AddPeer(peer Peer) {} 69 70 func (tr *TestReactor) RemovePeer(peer Peer, reason interface{}) {} 71 72 func (tr *TestReactor) ReceiveEnvelope(e Envelope) { 73 if tr.logMessages { 74 tr.mtx.Lock() 75 defer tr.mtx.Unlock() 76 // fmt.Printf("Received: %X, %X\n", e.ChannelID, e.Message) 77 tr.msgsReceived[e.ChannelID] = append(tr.msgsReceived[e.ChannelID], PeerMessage{Contents: e.Message, Counter: tr.msgsCounter}) 78 tr.msgsCounter++ 79 } 80 } 81 82 func (tr *TestReactor) Receive(chID byte, peer Peer, msgBytes []byte) { 83 msg := &p2pproto.Message{} 84 err := proto.Unmarshal(msgBytes, msg) 85 if err != nil { 86 panic(err) 87 } 88 um, err := msg.Unwrap() 89 if err != nil { 90 panic(err) 91 } 92 93 tr.ReceiveEnvelope(Envelope{ 94 ChannelID: chID, 95 Src: peer, 96 Message: um, 97 }) 98 } 99 100 func (tr *TestReactor) getMsgs(chID byte) []PeerMessage { 101 tr.mtx.Lock() 102 defer tr.mtx.Unlock() 103 return tr.msgsReceived[chID] 104 } 105 106 //----------------------------------------------------------------------------- 107 108 // convenience method for creating two switches connected to each other. 109 // XXX: note this uses net.Pipe and not a proper TCP conn 110 func MakeSwitchPair(t testing.TB, initSwitch func(int, *Switch) *Switch) (*Switch, *Switch) { 111 // Create two switches that will be interconnected. 112 switches := MakeConnectedSwitches(cfg, 2, initSwitch, Connect2Switches) 113 return switches[0], switches[1] 114 } 115 116 func initSwitchFunc(i int, sw *Switch) *Switch { 117 sw.SetAddrBook(&AddrBookMock{ 118 Addrs: make(map[string]struct{}), 119 OurAddrs: make(map[string]struct{}), 120 }) 121 122 // Make two reactors of two channels each 123 sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ 124 {ID: byte(0x00), Priority: 10, MessageType: &p2pproto.Message{}}, 125 {ID: byte(0x01), Priority: 10, MessageType: &p2pproto.Message{}}, 126 }, true)) 127 sw.AddReactor("bar", NewTestReactor([]*conn.ChannelDescriptor{ 128 {ID: byte(0x02), Priority: 10, MessageType: &p2pproto.Message{}}, 129 {ID: byte(0x03), Priority: 10, MessageType: &p2pproto.Message{}}, 130 }, true)) 131 132 return sw 133 } 134 135 func TestSwitches(t *testing.T) { 136 s1, s2 := MakeSwitchPair(t, initSwitchFunc) 137 t.Cleanup(func() { 138 if err := s1.Stop(); err != nil { 139 t.Error(err) 140 } 141 }) 142 t.Cleanup(func() { 143 if err := s2.Stop(); err != nil { 144 t.Error(err) 145 } 146 }) 147 148 if s1.Peers().Size() != 1 { 149 t.Errorf("expected exactly 1 peer in s1, got %v", s1.Peers().Size()) 150 } 151 if s2.Peers().Size() != 1 { 152 t.Errorf("expected exactly 1 peer in s2, got %v", s2.Peers().Size()) 153 } 154 155 // Lets send some messages 156 ch0Msg := &p2pproto.PexAddrs{ 157 Addrs: []p2pproto.NetAddress{ 158 { 159 ID: "1", 160 }, 161 }, 162 } 163 ch1Msg := &p2pproto.PexAddrs{ 164 Addrs: []p2pproto.NetAddress{ 165 { 166 ID: "1", 167 }, 168 }, 169 } 170 ch2Msg := &p2pproto.PexAddrs{ 171 Addrs: []p2pproto.NetAddress{ 172 { 173 ID: "2", 174 }, 175 }, 176 } 177 s1.BroadcastEnvelope(Envelope{ChannelID: byte(0x00), Message: ch0Msg}) 178 s1.BroadcastEnvelope(Envelope{ChannelID: byte(0x01), Message: ch1Msg}) 179 s1.BroadcastEnvelope(Envelope{ChannelID: byte(0x02), Message: ch2Msg}) 180 assertMsgReceivedWithTimeout(t, 181 ch0Msg, 182 byte(0x00), 183 s2.Reactor("foo").(*TestReactor), 200*time.Millisecond, 5*time.Second) 184 assertMsgReceivedWithTimeout(t, 185 ch1Msg, 186 byte(0x01), 187 s2.Reactor("foo").(*TestReactor), 200*time.Millisecond, 5*time.Second) 188 assertMsgReceivedWithTimeout(t, 189 ch2Msg, 190 byte(0x02), 191 s2.Reactor("bar").(*TestReactor), 200*time.Millisecond, 5*time.Second) 192 } 193 194 func assertMsgReceivedWithTimeout( 195 t *testing.T, 196 msg proto.Message, 197 channel byte, 198 reactor *TestReactor, 199 checkPeriod, 200 timeout time.Duration, 201 ) { 202 ticker := time.NewTicker(checkPeriod) 203 for { 204 select { 205 case <-ticker.C: 206 msgs := reactor.getMsgs(channel) 207 expectedBytes, err := proto.Marshal(msgs[0].Contents) 208 require.NoError(t, err) 209 gotBytes, err := proto.Marshal(msg) 210 require.NoError(t, err) 211 if len(msgs) > 0 { 212 if !bytes.Equal(expectedBytes, gotBytes) { 213 t.Fatalf("Unexpected message bytes. Wanted: %X, Got: %X", msg, msgs[0].Counter) 214 } 215 return 216 } 217 218 case <-time.After(timeout): 219 t.Fatalf("Expected to have received 1 message in channel #%v, got zero", channel) 220 } 221 } 222 } 223 224 func TestSwitchFiltersOutItself(t *testing.T) { 225 s1 := MakeSwitch(cfg, 1, "127.0.0.1", "123.123.123", initSwitchFunc) 226 227 // simulate s1 having a public IP by creating a remote peer with the same ID 228 rp := &remotePeer{PrivKey: s1.nodeKey.PrivKey, Config: cfg} 229 rp.Start() 230 231 // addr should be rejected in addPeer based on the same ID 232 err := s1.DialPeerWithAddress(rp.Addr()) 233 if assert.Error(t, err) { 234 if err, ok := err.(ErrRejected); ok { 235 if !err.IsSelf() { 236 t.Errorf("expected self to be rejected") 237 } 238 } else { 239 t.Errorf("expected ErrRejected") 240 } 241 } 242 243 assert.True(t, s1.addrBook.OurAddress(rp.Addr())) 244 assert.False(t, s1.addrBook.HasAddress(rp.Addr())) 245 246 rp.Stop() 247 248 assertNoPeersAfterTimeout(t, s1, 100*time.Millisecond) 249 } 250 251 func TestSwitchPeerFilter(t *testing.T) { 252 var ( 253 filters = []PeerFilterFunc{ 254 func(_ IPeerSet, _ Peer) error { return nil }, 255 func(_ IPeerSet, _ Peer) error { return fmt.Errorf("denied") }, 256 func(_ IPeerSet, _ Peer) error { return nil }, 257 } 258 sw = MakeSwitch( 259 cfg, 260 1, 261 "testing", 262 "123.123.123", 263 initSwitchFunc, 264 SwitchPeerFilters(filters...), 265 ) 266 ) 267 err := sw.Start() 268 require.NoError(t, err) 269 t.Cleanup(func() { 270 if err := sw.Stop(); err != nil { 271 t.Error(err) 272 } 273 }) 274 275 // simulate remote peer 276 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 277 rp.Start() 278 t.Cleanup(rp.Stop) 279 280 p, err := sw.transport.Dial(*rp.Addr(), peerConfig{ 281 chDescs: sw.chDescs, 282 onPeerError: sw.StopPeerForError, 283 isPersistent: sw.IsPeerPersistent, 284 reactorsByCh: sw.reactorsByCh, 285 }) 286 if err != nil { 287 t.Fatal(err) 288 } 289 290 err = sw.addPeer(p) 291 if err, ok := err.(ErrRejected); ok { 292 if !err.IsFiltered() { 293 t.Errorf("expected peer to be filtered") 294 } 295 } else { 296 t.Errorf("expected ErrRejected") 297 } 298 } 299 300 func TestSwitchPeerFilterTimeout(t *testing.T) { 301 var ( 302 filters = []PeerFilterFunc{ 303 func(_ IPeerSet, _ Peer) error { 304 time.Sleep(10 * time.Millisecond) 305 return nil 306 }, 307 } 308 sw = MakeSwitch( 309 cfg, 310 1, 311 "testing", 312 "123.123.123", 313 initSwitchFunc, 314 SwitchFilterTimeout(5*time.Millisecond), 315 SwitchPeerFilters(filters...), 316 ) 317 ) 318 err := sw.Start() 319 require.NoError(t, err) 320 t.Cleanup(func() { 321 if err := sw.Stop(); err != nil { 322 t.Log(err) 323 } 324 }) 325 326 // simulate remote peer 327 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 328 rp.Start() 329 defer rp.Stop() 330 331 p, err := sw.transport.Dial(*rp.Addr(), peerConfig{ 332 chDescs: sw.chDescs, 333 onPeerError: sw.StopPeerForError, 334 isPersistent: sw.IsPeerPersistent, 335 reactorsByCh: sw.reactorsByCh, 336 }) 337 if err != nil { 338 t.Fatal(err) 339 } 340 341 err = sw.addPeer(p) 342 if _, ok := err.(ErrFilterTimeout); !ok { 343 t.Errorf("expected ErrFilterTimeout") 344 } 345 } 346 347 func TestSwitchPeerFilterDuplicate(t *testing.T) { 348 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 349 err := sw.Start() 350 require.NoError(t, err) 351 t.Cleanup(func() { 352 if err := sw.Stop(); err != nil { 353 t.Error(err) 354 } 355 }) 356 357 // simulate remote peer 358 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 359 rp.Start() 360 defer rp.Stop() 361 362 p, err := sw.transport.Dial(*rp.Addr(), peerConfig{ 363 chDescs: sw.chDescs, 364 onPeerError: sw.StopPeerForError, 365 isPersistent: sw.IsPeerPersistent, 366 reactorsByCh: sw.reactorsByCh, 367 }) 368 if err != nil { 369 t.Fatal(err) 370 } 371 372 if err := sw.addPeer(p); err != nil { 373 t.Fatal(err) 374 } 375 376 err = sw.addPeer(p) 377 if errRej, ok := err.(ErrRejected); ok { 378 if !errRej.IsDuplicate() { 379 t.Errorf("expected peer to be duplicate. got %v", errRej) 380 } 381 } else { 382 t.Errorf("expected ErrRejected, got %v", err) 383 } 384 } 385 386 func assertNoPeersAfterTimeout(t *testing.T, sw *Switch, timeout time.Duration) { 387 time.Sleep(timeout) 388 if sw.Peers().Size() != 0 { 389 t.Fatalf("Expected %v to not connect to some peers, got %d", sw, sw.Peers().Size()) 390 } 391 } 392 393 func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { 394 assert, require := assert.New(t), require.New(t) 395 396 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 397 err := sw.Start() 398 if err != nil { 399 t.Error(err) 400 } 401 t.Cleanup(func() { 402 if err := sw.Stop(); err != nil { 403 t.Error(err) 404 } 405 }) 406 407 // simulate remote peer 408 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 409 rp.Start() 410 defer rp.Stop() 411 412 p, err := sw.transport.Dial(*rp.Addr(), peerConfig{ 413 chDescs: sw.chDescs, 414 onPeerError: sw.StopPeerForError, 415 isPersistent: sw.IsPeerPersistent, 416 reactorsByCh: sw.reactorsByCh, 417 }) 418 require.Nil(err) 419 420 err = sw.addPeer(p) 421 require.Nil(err) 422 423 require.NotNil(sw.Peers().Get(rp.ID())) 424 425 // simulate failure by closing connection 426 err = p.(*peer).CloseConn() 427 require.NoError(err) 428 429 assertNoPeersAfterTimeout(t, sw, 100*time.Millisecond) 430 assert.False(p.IsRunning()) 431 } 432 433 func TestSwitchStopPeerForError(t *testing.T) { 434 s := httptest.NewServer(promhttp.Handler()) 435 defer s.Close() 436 437 scrapeMetrics := func() string { 438 resp, err := http.Get(s.URL) 439 require.NoError(t, err) 440 defer resp.Body.Close() 441 buf, _ := io.ReadAll(resp.Body) 442 return string(buf) 443 } 444 445 namespace, subsystem, name := config.TestInstrumentationConfig().Namespace, MetricsSubsystem, "peers" 446 re := regexp.MustCompile(namespace + `_` + subsystem + `_` + name + ` ([0-9\.]+)`) 447 peersMetricValue := func() float64 { 448 matches := re.FindStringSubmatch(scrapeMetrics()) 449 f, _ := strconv.ParseFloat(matches[1], 64) 450 return f 451 } 452 453 p2pMetrics := PrometheusMetrics(namespace) 454 455 // make two connected switches 456 sw1, sw2 := MakeSwitchPair(t, func(i int, sw *Switch) *Switch { 457 // set metrics on sw1 458 if i == 0 { 459 opt := WithMetrics(p2pMetrics) 460 opt(sw) 461 } 462 return initSwitchFunc(i, sw) 463 }) 464 465 assert.Equal(t, len(sw1.Peers().List()), 1) 466 assert.EqualValues(t, 1, peersMetricValue()) 467 468 // send messages to the peer from sw1 469 p := sw1.Peers().List()[0] 470 SendEnvelopeShim(p, Envelope{ 471 ChannelID: 0x1, 472 Message: &p2pproto.Message{}, 473 }, sw1.Logger) 474 475 // stop sw2. this should cause the p to fail, 476 // which results in calling StopPeerForError internally 477 t.Cleanup(func() { 478 if err := sw2.Stop(); err != nil { 479 t.Error(err) 480 } 481 }) 482 483 // now call StopPeerForError explicitly, eg. from a reactor 484 sw1.StopPeerForError(p, fmt.Errorf("some err")) 485 486 assert.Equal(t, len(sw1.Peers().List()), 0) 487 assert.EqualValues(t, 0, peersMetricValue()) 488 } 489 490 func TestSwitchReconnectsToOutboundPersistentPeer(t *testing.T) { 491 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 492 err := sw.Start() 493 require.NoError(t, err) 494 t.Cleanup(func() { 495 if err := sw.Stop(); err != nil { 496 t.Error(err) 497 } 498 }) 499 500 // 1. simulate failure by closing connection 501 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 502 rp.Start() 503 defer rp.Stop() 504 505 err = sw.AddPersistentPeers([]string{rp.Addr().String()}) 506 require.NoError(t, err) 507 508 err = sw.DialPeerWithAddress(rp.Addr()) 509 require.Nil(t, err) 510 require.NotNil(t, sw.Peers().Get(rp.ID())) 511 512 p := sw.Peers().List()[0] 513 err = p.(*peer).CloseConn() 514 require.NoError(t, err) 515 516 waitUntilSwitchHasAtLeastNPeers(sw, 1) 517 assert.False(t, p.IsRunning()) // old peer instance 518 assert.Equal(t, 1, sw.Peers().Size()) // new peer instance 519 520 // 2. simulate first time dial failure 521 rp = &remotePeer{ 522 PrivKey: ed25519.GenPrivKey(), 523 Config: cfg, 524 // Use different interface to prevent duplicate IP filter, this will break 525 // beyond two peers. 526 listenAddr: "127.0.0.1:0", 527 } 528 rp.Start() 529 defer rp.Stop() 530 531 conf := config.DefaultP2PConfig() 532 conf.TestDialFail = true // will trigger a reconnect 533 err = sw.addOutboundPeerWithConfig(rp.Addr(), conf) 534 require.NotNil(t, err) 535 // DialPeerWithAddres - sw.peerConfig resets the dialer 536 waitUntilSwitchHasAtLeastNPeers(sw, 2) 537 assert.Equal(t, 2, sw.Peers().Size()) 538 } 539 540 func TestSwitchReconnectsToInboundPersistentPeer(t *testing.T) { 541 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 542 err := sw.Start() 543 require.NoError(t, err) 544 t.Cleanup(func() { 545 if err := sw.Stop(); err != nil { 546 t.Error(err) 547 } 548 }) 549 550 // 1. simulate failure by closing the connection 551 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 552 rp.Start() 553 defer rp.Stop() 554 555 err = sw.AddPersistentPeers([]string{rp.Addr().String()}) 556 require.NoError(t, err) 557 558 conn, err := rp.Dial(sw.NetAddress()) 559 require.NoError(t, err) 560 time.Sleep(50 * time.Millisecond) 561 require.NotNil(t, sw.Peers().Get(rp.ID())) 562 563 conn.Close() 564 565 waitUntilSwitchHasAtLeastNPeers(sw, 1) 566 assert.Equal(t, 1, sw.Peers().Size()) 567 } 568 569 func TestSwitchDialPeersAsync(t *testing.T) { 570 if testing.Short() { 571 return 572 } 573 574 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 575 err := sw.Start() 576 require.NoError(t, err) 577 t.Cleanup(func() { 578 if err := sw.Stop(); err != nil { 579 t.Error(err) 580 } 581 }) 582 583 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 584 rp.Start() 585 defer rp.Stop() 586 587 err = sw.DialPeersAsync([]string{rp.Addr().String()}) 588 require.NoError(t, err) 589 time.Sleep(dialRandomizerIntervalMilliseconds * time.Millisecond) 590 require.NotNil(t, sw.Peers().Get(rp.ID())) 591 } 592 593 func waitUntilSwitchHasAtLeastNPeers(sw *Switch, n int) { 594 for i := 0; i < 20; i++ { 595 time.Sleep(250 * time.Millisecond) 596 has := sw.Peers().Size() 597 if has >= n { 598 break 599 } 600 } 601 } 602 603 func TestSwitchFullConnectivity(t *testing.T) { 604 switches := MakeConnectedSwitches(cfg, 3, initSwitchFunc, Connect2Switches) 605 defer func() { 606 for _, sw := range switches { 607 sw := sw 608 t.Cleanup(func() { 609 if err := sw.Stop(); err != nil { 610 t.Error(err) 611 } 612 }) 613 } 614 }() 615 616 for i, sw := range switches { 617 if sw.Peers().Size() != 2 { 618 t.Fatalf("Expected each switch to be connected to 2 other, but %d switch only connected to %d", sw.Peers().Size(), i) 619 } 620 } 621 } 622 623 func TestSwitchAcceptRoutine(t *testing.T) { 624 cfg.MaxNumInboundPeers = 5 625 626 // Create some unconditional peers. 627 const unconditionalPeersNum = 2 628 var ( 629 unconditionalPeers = make([]*remotePeer, unconditionalPeersNum) 630 unconditionalPeerIDs = make([]string, unconditionalPeersNum) 631 ) 632 for i := 0; i < unconditionalPeersNum; i++ { 633 peer := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 634 peer.Start() 635 unconditionalPeers[i] = peer 636 unconditionalPeerIDs[i] = string(peer.ID()) 637 } 638 639 // make switch 640 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", initSwitchFunc) 641 err := sw.AddUnconditionalPeerIDs(unconditionalPeerIDs) 642 require.NoError(t, err) 643 err = sw.Start() 644 require.NoError(t, err) 645 t.Cleanup(func() { 646 err := sw.Stop() 647 require.NoError(t, err) 648 }) 649 650 // 0. check there are no peers 651 assert.Equal(t, 0, sw.Peers().Size()) 652 653 // 1. check we connect up to MaxNumInboundPeers 654 peers := make([]*remotePeer, 0) 655 for i := 0; i < cfg.MaxNumInboundPeers; i++ { 656 peer := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 657 peers = append(peers, peer) 658 peer.Start() 659 c, err := peer.Dial(sw.NetAddress()) 660 require.NoError(t, err) 661 // spawn a reading routine to prevent connection from closing 662 go func(c net.Conn) { 663 for { 664 one := make([]byte, 1) 665 _, err := c.Read(one) 666 if err != nil { 667 return 668 } 669 } 670 }(c) 671 } 672 time.Sleep(100 * time.Millisecond) 673 assert.Equal(t, cfg.MaxNumInboundPeers, sw.Peers().Size()) 674 675 // 2. check we close new connections if we already have MaxNumInboundPeers peers 676 peer := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 677 peer.Start() 678 conn, err := peer.Dial(sw.NetAddress()) 679 require.NoError(t, err) 680 // check conn is closed 681 one := make([]byte, 1) 682 _ = conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond)) 683 _, err = conn.Read(one) 684 assert.Error(t, err) 685 assert.Equal(t, cfg.MaxNumInboundPeers, sw.Peers().Size()) 686 peer.Stop() 687 688 // 3. check we connect to unconditional peers despite the limit. 689 for _, peer := range unconditionalPeers { 690 c, err := peer.Dial(sw.NetAddress()) 691 require.NoError(t, err) 692 // spawn a reading routine to prevent connection from closing 693 go func(c net.Conn) { 694 for { 695 one := make([]byte, 1) 696 _, err := c.Read(one) 697 if err != nil { 698 return 699 } 700 } 701 }(c) 702 } 703 time.Sleep(10 * time.Millisecond) 704 assert.Equal(t, cfg.MaxNumInboundPeers+unconditionalPeersNum, sw.Peers().Size()) 705 706 for _, peer := range peers { 707 peer.Stop() 708 } 709 for _, peer := range unconditionalPeers { 710 peer.Stop() 711 } 712 } 713 714 type errorTransport struct { 715 acceptErr error 716 } 717 718 func (et errorTransport) NetAddress() NetAddress { 719 panic("not implemented") 720 } 721 722 func (et errorTransport) Accept(c peerConfig) (Peer, error) { 723 return nil, et.acceptErr 724 } 725 726 func (errorTransport) Dial(NetAddress, peerConfig) (Peer, error) { 727 panic("not implemented") 728 } 729 730 func (errorTransport) Cleanup(Peer) { 731 panic("not implemented") 732 } 733 734 func TestSwitchAcceptRoutineErrorCases(t *testing.T) { 735 sw := NewSwitch(cfg, errorTransport{ErrFilterTimeout{}}) 736 assert.NotPanics(t, func() { 737 err := sw.Start() 738 require.NoError(t, err) 739 err = sw.Stop() 740 require.NoError(t, err) 741 }) 742 743 sw = NewSwitch(cfg, errorTransport{ErrRejected{conn: nil, err: errors.New("filtered"), isFiltered: true}}) 744 assert.NotPanics(t, func() { 745 err := sw.Start() 746 require.NoError(t, err) 747 err = sw.Stop() 748 require.NoError(t, err) 749 }) 750 // TODO(melekes) check we remove our address from addrBook 751 752 sw = NewSwitch(cfg, errorTransport{ErrTransportClosed{}}) 753 assert.NotPanics(t, func() { 754 err := sw.Start() 755 require.NoError(t, err) 756 err = sw.Stop() 757 require.NoError(t, err) 758 }) 759 } 760 761 // mockReactor checks that InitPeer never called before RemovePeer. If that's 762 // not true, InitCalledBeforeRemoveFinished will return true. 763 type mockReactor struct { 764 *BaseReactor 765 766 // atomic 767 removePeerInProgress uint32 768 initCalledBeforeRemoveFinished uint32 769 } 770 771 func (r *mockReactor) RemovePeer(peer Peer, reason interface{}) { 772 atomic.StoreUint32(&r.removePeerInProgress, 1) 773 defer atomic.StoreUint32(&r.removePeerInProgress, 0) 774 time.Sleep(100 * time.Millisecond) 775 } 776 777 func (r *mockReactor) InitPeer(peer Peer) Peer { 778 if atomic.LoadUint32(&r.removePeerInProgress) == 1 { 779 atomic.StoreUint32(&r.initCalledBeforeRemoveFinished, 1) 780 } 781 782 return peer 783 } 784 785 func (r *mockReactor) InitCalledBeforeRemoveFinished() bool { 786 return atomic.LoadUint32(&r.initCalledBeforeRemoveFinished) == 1 787 } 788 789 // see stopAndRemovePeer 790 func TestSwitchInitPeerIsNotCalledBeforeRemovePeer(t *testing.T) { 791 // make reactor 792 reactor := &mockReactor{} 793 reactor.BaseReactor = NewBaseReactor("mockReactor", reactor) 794 795 // make switch 796 sw := MakeSwitch(cfg, 1, "testing", "123.123.123", func(i int, sw *Switch) *Switch { 797 sw.AddReactor("mock", reactor) 798 return sw 799 }) 800 err := sw.Start() 801 require.NoError(t, err) 802 t.Cleanup(func() { 803 if err := sw.Stop(); err != nil { 804 t.Error(err) 805 } 806 }) 807 808 // add peer 809 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 810 rp.Start() 811 defer rp.Stop() 812 _, err = rp.Dial(sw.NetAddress()) 813 require.NoError(t, err) 814 815 // wait till the switch adds rp to the peer set, then stop the peer asynchronously 816 for { 817 time.Sleep(20 * time.Millisecond) 818 if peer := sw.Peers().Get(rp.ID()); peer != nil { 819 go sw.StopPeerForError(peer, "test") 820 break 821 } 822 } 823 824 // simulate peer reconnecting to us 825 _, err = rp.Dial(sw.NetAddress()) 826 require.NoError(t, err) 827 // wait till the switch adds rp to the peer set 828 time.Sleep(50 * time.Millisecond) 829 830 // make sure reactor.RemovePeer is finished before InitPeer is called 831 assert.False(t, reactor.InitCalledBeforeRemoveFinished()) 832 } 833 834 func BenchmarkSwitchBroadcast(b *testing.B) { 835 s1, s2 := MakeSwitchPair(b, func(i int, sw *Switch) *Switch { 836 // Make bar reactors of bar channels each 837 sw.AddReactor("foo", NewTestReactor([]*conn.ChannelDescriptor{ 838 {ID: byte(0x00), Priority: 10}, 839 {ID: byte(0x01), Priority: 10}, 840 }, false)) 841 sw.AddReactor("bar", NewTestReactor([]*conn.ChannelDescriptor{ 842 {ID: byte(0x02), Priority: 10}, 843 {ID: byte(0x03), Priority: 10}, 844 }, false)) 845 return sw 846 }) 847 848 b.Cleanup(func() { 849 if err := s1.Stop(); err != nil { 850 b.Error(err) 851 } 852 }) 853 854 b.Cleanup(func() { 855 if err := s2.Stop(); err != nil { 856 b.Error(err) 857 } 858 }) 859 860 // Allow time for goroutines to boot up 861 time.Sleep(1 * time.Second) 862 863 b.ResetTimer() 864 865 numSuccess, numFailure := 0, 0 866 867 // Send random message from foo channel to another 868 for i := 0; i < b.N; i++ { 869 chID := byte(i % 4) 870 successChan := s1.BroadcastEnvelope(Envelope{ChannelID: chID}) 871 for s := range successChan { 872 if s { 873 numSuccess++ 874 } else { 875 numFailure++ 876 } 877 } 878 } 879 880 b.Logf("success: %v, failure: %v", numSuccess, numFailure) 881 } 882 883 func TestSwitchRemovalErr(t *testing.T) { 884 sw1, sw2 := MakeSwitchPair(t, func(i int, sw *Switch) *Switch { 885 return initSwitchFunc(i, sw) 886 }) 887 assert.Equal(t, len(sw1.Peers().List()), 1) 888 p := sw1.Peers().List()[0] 889 890 sw2.StopPeerForError(p, fmt.Errorf("peer should error")) 891 892 assert.Equal(t, sw2.peers.Add(p).Error(), ErrPeerRemoval{}.Error()) 893 }