You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
3.4 KiB

  1. package p2p_test
  2. import (
  3. "errors"
  4. "testing"
  5. gogotypes "github.com/gogo/protobuf/types"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/tendermint/libs/log"
  9. "github.com/tendermint/tendermint/p2p"
  10. )
  11. type TestMessage = gogotypes.StringValue
  12. func echoReactor(channel *p2p.Channel) {
  13. for {
  14. select {
  15. case envelope := <-channel.In():
  16. channel.Out() <- p2p.Envelope{
  17. To: envelope.From,
  18. Message: &TestMessage{Value: envelope.Message.(*TestMessage).Value},
  19. }
  20. case <-channel.Done():
  21. return
  22. }
  23. }
  24. }
  25. func TestRouter(t *testing.T) {
  26. logger := log.TestingLogger()
  27. network := p2p.NewMemoryNetwork(logger)
  28. transport := network.GenerateTransport()
  29. chID := p2p.ChannelID(1)
  30. // Start some other in-memory network nodes to communicate with, running
  31. // a simple echo reactor that returns received messages.
  32. peers := []p2p.PeerAddress{}
  33. for i := 0; i < 3; i++ {
  34. peerTransport := network.GenerateTransport()
  35. peerRouter := p2p.NewRouter(
  36. logger.With("peerID", i),
  37. p2p.NewPeerManager(p2p.PeerManagerOptions{}),
  38. map[p2p.Protocol]p2p.Transport{
  39. p2p.MemoryProtocol: peerTransport,
  40. },
  41. )
  42. peers = append(peers, peerTransport.Endpoints()[0].PeerAddress())
  43. channel, err := peerRouter.OpenChannel(chID, &TestMessage{})
  44. require.NoError(t, err)
  45. defer channel.Close()
  46. go echoReactor(channel)
  47. err = peerRouter.Start()
  48. require.NoError(t, err)
  49. defer func() { require.NoError(t, peerRouter.Stop()) }()
  50. }
  51. // Start the main router and connect it to the peers above.
  52. peerManager := p2p.NewPeerManager(p2p.PeerManagerOptions{})
  53. for _, address := range peers {
  54. err := peerManager.Add(address)
  55. require.NoError(t, err)
  56. }
  57. peerUpdates := peerManager.Subscribe()
  58. defer peerUpdates.Close()
  59. router := p2p.NewRouter(logger, peerManager, map[p2p.Protocol]p2p.Transport{
  60. p2p.MemoryProtocol: transport,
  61. })
  62. channel, err := router.OpenChannel(chID, &TestMessage{})
  63. require.NoError(t, err)
  64. err = router.Start()
  65. require.NoError(t, err)
  66. defer func() {
  67. channel.Close()
  68. require.NoError(t, router.Stop())
  69. }()
  70. // Wait for peers to come online, and ping them as they do.
  71. for i := 0; i < len(peers); i++ {
  72. peerUpdate := <-peerUpdates.Updates()
  73. peerID := peerUpdate.PeerID
  74. require.Equal(t, p2p.PeerUpdate{
  75. PeerID: peerID,
  76. Status: p2p.PeerStatusUp,
  77. }, peerUpdate)
  78. channel.Out() <- p2p.Envelope{To: peerID, Message: &TestMessage{Value: "hi!"}}
  79. assert.Equal(t, p2p.Envelope{
  80. From: peerID,
  81. Message: &TestMessage{Value: "hi!"},
  82. }, (<-channel.In()).Strip())
  83. }
  84. // We then submit an error for a peer, and watch it get disconnected.
  85. channel.Error() <- p2p.PeerError{
  86. PeerID: peers[0].NodeID(),
  87. Err: errors.New("test error"),
  88. Severity: p2p.PeerErrorSeverityCritical,
  89. }
  90. peerUpdate := <-peerUpdates.Updates()
  91. require.Equal(t, p2p.PeerUpdate{
  92. PeerID: peers[0].NodeID(),
  93. Status: p2p.PeerStatusDown,
  94. }, peerUpdate)
  95. // We now broadcast a message, which we should receive back from only two peers.
  96. channel.Out() <- p2p.Envelope{
  97. Broadcast: true,
  98. Message: &TestMessage{Value: "broadcast"},
  99. }
  100. for i := 0; i < len(peers)-1; i++ {
  101. envelope := <-channel.In()
  102. require.NotEqual(t, peers[0].NodeID(), envelope.From)
  103. require.Equal(t, &TestMessage{Value: "broadcast"}, envelope.Message)
  104. }
  105. select {
  106. case envelope := <-channel.In():
  107. t.Errorf("unexpected message: %v", envelope)
  108. default:
  109. }
  110. }