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.

201 lines
5.2 KiB

  1. package behaviour_test
  2. import (
  3. "sync"
  4. "testing"
  5. bh "github.com/tendermint/tendermint/behaviour"
  6. "github.com/tendermint/tendermint/p2p"
  7. )
  8. // TestMockReporter tests the MockReporter's ability to store reported
  9. // peer behaviour in memory indexed by the peerID.
  10. func TestMockReporter(t *testing.T) {
  11. var peerID p2p.ID = "MockPeer"
  12. pr := bh.NewMockReporter()
  13. behaviours := pr.GetBehaviours(peerID)
  14. if len(behaviours) != 0 {
  15. t.Error("Expected to have no behaviours reported")
  16. }
  17. badMessage := bh.BadMessage(peerID, "bad message")
  18. pr.Report(badMessage)
  19. behaviours = pr.GetBehaviours(peerID)
  20. if len(behaviours) != 1 {
  21. t.Error("Expected the peer have one reported behaviour")
  22. }
  23. if behaviours[0] != badMessage {
  24. t.Error("Expected Bad Message to have been reported")
  25. }
  26. }
  27. type scriptItem struct {
  28. peerID p2p.ID
  29. behaviour bh.PeerBehaviour
  30. }
  31. // equalBehaviours returns true if a and b contain the same PeerBehaviours with
  32. // the same freequencies and otherwise false.
  33. func equalBehaviours(a []bh.PeerBehaviour, b []bh.PeerBehaviour) bool {
  34. aHistogram := map[bh.PeerBehaviour]int{}
  35. bHistogram := map[bh.PeerBehaviour]int{}
  36. for _, behaviour := range a {
  37. aHistogram[behaviour] += 1
  38. }
  39. for _, behaviour := range b {
  40. bHistogram[behaviour] += 1
  41. }
  42. if len(aHistogram) != len(bHistogram) {
  43. return false
  44. }
  45. for _, behaviour := range a {
  46. if aHistogram[behaviour] != bHistogram[behaviour] {
  47. return false
  48. }
  49. }
  50. for _, behaviour := range b {
  51. if bHistogram[behaviour] != aHistogram[behaviour] {
  52. return false
  53. }
  54. }
  55. return true
  56. }
  57. // TestEqualPeerBehaviours tests that equalBehaviours can tell that two slices
  58. // of peer behaviours can be compared for the behaviours they contain and the
  59. // freequencies that those behaviours occur.
  60. func TestEqualPeerBehaviours(t *testing.T) {
  61. var (
  62. peerID p2p.ID = "MockPeer"
  63. consensusVote = bh.ConsensusVote(peerID, "voted")
  64. blockPart = bh.BlockPart(peerID, "blocked")
  65. equals = []struct {
  66. left []bh.PeerBehaviour
  67. right []bh.PeerBehaviour
  68. }{
  69. // Empty sets
  70. {[]bh.PeerBehaviour{}, []bh.PeerBehaviour{}},
  71. // Single behaviours
  72. {[]bh.PeerBehaviour{consensusVote}, []bh.PeerBehaviour{consensusVote}},
  73. // Equal Frequencies
  74. {[]bh.PeerBehaviour{consensusVote, consensusVote},
  75. []bh.PeerBehaviour{consensusVote, consensusVote}},
  76. // Equal frequencies different orders
  77. {[]bh.PeerBehaviour{consensusVote, blockPart},
  78. []bh.PeerBehaviour{blockPart, consensusVote}},
  79. }
  80. unequals = []struct {
  81. left []bh.PeerBehaviour
  82. right []bh.PeerBehaviour
  83. }{
  84. // Comparing empty sets to non empty sets
  85. {[]bh.PeerBehaviour{}, []bh.PeerBehaviour{consensusVote}},
  86. // Different behaviours
  87. {[]bh.PeerBehaviour{consensusVote}, []bh.PeerBehaviour{blockPart}},
  88. // Same behaviour with different frequencies
  89. {[]bh.PeerBehaviour{consensusVote},
  90. []bh.PeerBehaviour{consensusVote, consensusVote}},
  91. }
  92. )
  93. for _, test := range equals {
  94. if !equalBehaviours(test.left, test.right) {
  95. t.Errorf("Expected %#v and %#v to be equal", test.left, test.right)
  96. }
  97. }
  98. for _, test := range unequals {
  99. if equalBehaviours(test.left, test.right) {
  100. t.Errorf("Expected %#v and %#v to be unequal", test.left, test.right)
  101. }
  102. }
  103. }
  104. // TestPeerBehaviourConcurrency constructs a scenario in which
  105. // multiple goroutines are using the same MockReporter instance.
  106. // This test reproduces the conditions in which MockReporter will
  107. // be used within a Reactor `Receive` method tests to ensure thread safety.
  108. func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
  109. var (
  110. behaviourScript = []struct {
  111. peerID p2p.ID
  112. behaviours []bh.PeerBehaviour
  113. }{
  114. {"1", []bh.PeerBehaviour{bh.ConsensusVote("1", "")}},
  115. {"2", []bh.PeerBehaviour{bh.ConsensusVote("2", ""), bh.ConsensusVote("2", ""), bh.ConsensusVote("2", "")}},
  116. {
  117. "3",
  118. []bh.PeerBehaviour{bh.BlockPart("3", ""),
  119. bh.ConsensusVote("3", ""),
  120. bh.BlockPart("3", ""),
  121. bh.ConsensusVote("3", "")}},
  122. {
  123. "4",
  124. []bh.PeerBehaviour{bh.ConsensusVote("4", ""),
  125. bh.ConsensusVote("4", ""),
  126. bh.ConsensusVote("4", ""),
  127. bh.ConsensusVote("4", "")}},
  128. {
  129. "5",
  130. []bh.PeerBehaviour{bh.BlockPart("5", ""),
  131. bh.ConsensusVote("5", ""),
  132. bh.BlockPart("5", ""),
  133. bh.ConsensusVote("5", "")}},
  134. }
  135. )
  136. var receiveWg sync.WaitGroup
  137. pr := bh.NewMockReporter()
  138. scriptItems := make(chan scriptItem)
  139. done := make(chan int)
  140. numConsumers := 3
  141. for i := 0; i < numConsumers; i++ {
  142. receiveWg.Add(1)
  143. go func() {
  144. defer receiveWg.Done()
  145. for {
  146. select {
  147. case pb := <-scriptItems:
  148. pr.Report(pb.behaviour)
  149. case <-done:
  150. return
  151. }
  152. }
  153. }()
  154. }
  155. var sendingWg sync.WaitGroup
  156. sendingWg.Add(1)
  157. go func() {
  158. defer sendingWg.Done()
  159. for _, item := range behaviourScript {
  160. for _, reason := range item.behaviours {
  161. scriptItems <- scriptItem{item.peerID, reason}
  162. }
  163. }
  164. }()
  165. sendingWg.Wait()
  166. for i := 0; i < numConsumers; i++ {
  167. done <- 1
  168. }
  169. receiveWg.Wait()
  170. for _, items := range behaviourScript {
  171. reported := pr.GetBehaviours(items.peerID)
  172. if !equalBehaviours(reported, items.behaviours) {
  173. t.Errorf("Expected peer %s to have behaved \nExpected: %#v \nGot %#v \n",
  174. items.peerID, items.behaviours, reported)
  175. }
  176. }
  177. }