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.

116 lines
3.1 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(logger.With("peerID", i), map[p2p.Protocol]p2p.Transport{
  36. p2p.MemoryProtocol: peerTransport,
  37. }, nil)
  38. peers = append(peers, peerTransport.Endpoints()[0].PeerAddress())
  39. channel, err := peerRouter.OpenChannel(chID, &TestMessage{})
  40. require.NoError(t, err)
  41. defer channel.Close()
  42. go echoReactor(channel)
  43. err = peerRouter.Start()
  44. require.NoError(t, err)
  45. defer func() { require.NoError(t, peerRouter.Stop()) }()
  46. }
  47. // Start the main router and connect it to the peers above.
  48. router := p2p.NewRouter(logger, map[p2p.Protocol]p2p.Transport{
  49. p2p.MemoryProtocol: transport,
  50. }, peers)
  51. channel, err := router.OpenChannel(chID, &TestMessage{})
  52. require.NoError(t, err)
  53. peerUpdates := router.SubscribePeerUpdates()
  54. err = router.Start()
  55. require.NoError(t, err)
  56. defer func() {
  57. channel.Close()
  58. peerUpdates.Close()
  59. require.NoError(t, router.Stop())
  60. }()
  61. // Wait for peers to come online, and ping them as they do.
  62. for i := 0; i < len(peers); i++ {
  63. peerUpdate := <-peerUpdates.Updates()
  64. peerID := peerUpdate.PeerID
  65. require.Equal(t, p2p.PeerUpdate{
  66. PeerID: peerID,
  67. Status: p2p.PeerStatusUp,
  68. }, peerUpdate)
  69. channel.Out() <- p2p.Envelope{To: peerID, Message: &TestMessage{Value: "hi!"}}
  70. assert.Equal(t, p2p.Envelope{
  71. From: peerID,
  72. Message: &TestMessage{Value: "hi!"},
  73. }, (<-channel.In()).Strip())
  74. }
  75. // We then submit an error for a peer, and watch it get disconnected.
  76. channel.Error() <- p2p.PeerError{
  77. PeerID: peers[0].NodeID(),
  78. Err: errors.New("test error"),
  79. Severity: p2p.PeerErrorSeverityCritical,
  80. }
  81. peerUpdate := <-peerUpdates.Updates()
  82. require.Equal(t, p2p.PeerUpdate{
  83. PeerID: peers[0].NodeID(),
  84. Status: p2p.PeerStatusDown,
  85. }, peerUpdate)
  86. // We now broadcast a message, which we should receive back from only two peers.
  87. channel.Out() <- p2p.Envelope{
  88. Broadcast: true,
  89. Message: &TestMessage{Value: "broadcast"},
  90. }
  91. for i := 0; i < len(peers)-1; i++ {
  92. envelope := <-channel.In()
  93. require.NotEqual(t, peers[0].NodeID(), envelope.From)
  94. require.Equal(t, &TestMessage{Value: "broadcast"}, envelope.Message)
  95. }
  96. select {
  97. case envelope := <-channel.In():
  98. t.Errorf("unexpected message: %v", envelope)
  99. default:
  100. }
  101. }