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.

147 lines
4.0 KiB

  1. package v1
  2. import (
  3. "os"
  4. "strings"
  5. "sync"
  6. "testing"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/tendermint/abci/example/kvstore"
  9. "github.com/tendermint/tendermint/config"
  10. tmsync "github.com/tendermint/tendermint/internal/libs/sync"
  11. "github.com/tendermint/tendermint/internal/mempool"
  12. "github.com/tendermint/tendermint/internal/p2p"
  13. "github.com/tendermint/tendermint/internal/p2p/p2ptest"
  14. "github.com/tendermint/tendermint/libs/log"
  15. protomem "github.com/tendermint/tendermint/proto/tendermint/mempool"
  16. "github.com/tendermint/tendermint/types"
  17. )
  18. type reactorTestSuite struct {
  19. network *p2ptest.Network
  20. logger log.Logger
  21. reactors map[types.NodeID]*Reactor
  22. mempoolChannels map[types.NodeID]*p2p.Channel
  23. mempools map[types.NodeID]*TxMempool
  24. kvstores map[types.NodeID]*kvstore.Application
  25. peerChans map[types.NodeID]chan p2p.PeerUpdate
  26. peerUpdates map[types.NodeID]*p2p.PeerUpdates
  27. nodes []types.NodeID
  28. }
  29. func setupReactors(t *testing.T, numNodes int, chBuf uint) *reactorTestSuite {
  30. t.Helper()
  31. cfg := config.ResetTestRoot(strings.ReplaceAll(t.Name(), "/", "|"))
  32. t.Cleanup(func() {
  33. os.RemoveAll(cfg.RootDir)
  34. })
  35. rts := &reactorTestSuite{
  36. logger: log.TestingLogger().With("testCase", t.Name()),
  37. network: p2ptest.MakeNetwork(t, p2ptest.NetworkOptions{NumNodes: numNodes}),
  38. reactors: make(map[types.NodeID]*Reactor, numNodes),
  39. mempoolChannels: make(map[types.NodeID]*p2p.Channel, numNodes),
  40. mempools: make(map[types.NodeID]*TxMempool, numNodes),
  41. kvstores: make(map[types.NodeID]*kvstore.Application, numNodes),
  42. peerChans: make(map[types.NodeID]chan p2p.PeerUpdate, numNodes),
  43. peerUpdates: make(map[types.NodeID]*p2p.PeerUpdates, numNodes),
  44. }
  45. chDesc := p2p.ChannelDescriptor{ID: byte(mempool.MempoolChannel)}
  46. rts.mempoolChannels = rts.network.MakeChannelsNoCleanup(t, chDesc, new(protomem.Message), int(chBuf))
  47. for nodeID := range rts.network.Nodes {
  48. rts.kvstores[nodeID] = kvstore.NewApplication()
  49. mempool := setup(t, 0)
  50. rts.mempools[nodeID] = mempool
  51. rts.peerChans[nodeID] = make(chan p2p.PeerUpdate)
  52. rts.peerUpdates[nodeID] = p2p.NewPeerUpdates(rts.peerChans[nodeID], 1)
  53. rts.network.Nodes[nodeID].PeerManager.Register(rts.peerUpdates[nodeID])
  54. rts.reactors[nodeID] = NewReactor(
  55. rts.logger.With("nodeID", nodeID),
  56. cfg.Mempool,
  57. rts.network.Nodes[nodeID].PeerManager,
  58. mempool,
  59. rts.mempoolChannels[nodeID],
  60. rts.peerUpdates[nodeID],
  61. )
  62. rts.nodes = append(rts.nodes, nodeID)
  63. require.NoError(t, rts.reactors[nodeID].Start())
  64. require.True(t, rts.reactors[nodeID].IsRunning())
  65. }
  66. require.Len(t, rts.reactors, numNodes)
  67. t.Cleanup(func() {
  68. for nodeID := range rts.reactors {
  69. if rts.reactors[nodeID].IsRunning() {
  70. require.NoError(t, rts.reactors[nodeID].Stop())
  71. require.False(t, rts.reactors[nodeID].IsRunning())
  72. }
  73. }
  74. })
  75. return rts
  76. }
  77. func (rts *reactorTestSuite) start(t *testing.T) {
  78. t.Helper()
  79. rts.network.Start(t)
  80. require.Len(t,
  81. rts.network.RandomNode().PeerManager.Peers(),
  82. len(rts.nodes)-1,
  83. "network does not have expected number of nodes")
  84. }
  85. func TestReactorBroadcastDoesNotPanic(t *testing.T) {
  86. numNodes := 2
  87. rts := setupReactors(t, numNodes, 0)
  88. observePanic := func(r interface{}) {
  89. t.Fatal("panic detected in reactor")
  90. }
  91. primary := rts.nodes[0]
  92. secondary := rts.nodes[1]
  93. primaryReactor := rts.reactors[primary]
  94. primaryMempool := primaryReactor.mempool
  95. secondaryReactor := rts.reactors[secondary]
  96. primaryReactor.observePanic = observePanic
  97. secondaryReactor.observePanic = observePanic
  98. firstTx := &WrappedTx{}
  99. primaryMempool.insertTx(firstTx)
  100. // run the router
  101. rts.start(t)
  102. closer := tmsync.NewCloser()
  103. primaryReactor.peerWG.Add(1)
  104. go primaryReactor.broadcastTxRoutine(secondary, closer)
  105. wg := &sync.WaitGroup{}
  106. for i := 0; i < 50; i++ {
  107. next := &WrappedTx{}
  108. wg.Add(1)
  109. go func() {
  110. defer wg.Done()
  111. primaryMempool.insertTx(next)
  112. }()
  113. }
  114. err := primaryReactor.Stop()
  115. require.NoError(t, err)
  116. primaryReactor.peerWG.Wait()
  117. wg.Wait()
  118. }