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.

430 lines
13 KiB

  1. package events
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. cmn "github.com/tendermint/tendermint/libs/common"
  9. )
  10. // TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single
  11. // listener to an event, and sends a string "data".
  12. func TestAddListenerForEventFireOnce(t *testing.T) {
  13. evsw := NewEventSwitch()
  14. err := evsw.Start()
  15. require.NoError(t, err)
  16. defer evsw.Stop()
  17. messages := make(chan EventData)
  18. evsw.AddListenerForEvent("listener", "event",
  19. func(data EventData) {
  20. // test there's no deadlock if we remove the listener inside a callback
  21. evsw.RemoveListener("listener")
  22. messages <- data
  23. })
  24. go evsw.FireEvent("event", "data")
  25. received := <-messages
  26. if received != "data" {
  27. t.Errorf("Message received does not match: %v", received)
  28. }
  29. }
  30. // TestAddListenerForEventFireMany sets up an EventSwitch, subscribes a single
  31. // listener to an event, and sends a thousand integers.
  32. func TestAddListenerForEventFireMany(t *testing.T) {
  33. evsw := NewEventSwitch()
  34. err := evsw.Start()
  35. require.NoError(t, err)
  36. defer evsw.Stop()
  37. doneSum := make(chan uint64)
  38. doneSending := make(chan uint64)
  39. numbers := make(chan uint64, 4)
  40. // subscribe one listener for one event
  41. evsw.AddListenerForEvent("listener", "event",
  42. func(data EventData) {
  43. numbers <- data.(uint64)
  44. })
  45. // collect received events
  46. go sumReceivedNumbers(numbers, doneSum)
  47. // go fire events
  48. go fireEvents(evsw, "event", doneSending, uint64(1))
  49. checkSum := <-doneSending
  50. close(numbers)
  51. eventSum := <-doneSum
  52. if checkSum != eventSum {
  53. t.Errorf("Not all messages sent were received.\n")
  54. }
  55. }
  56. // TestAddListenerForDifferentEvents sets up an EventSwitch, subscribes a single
  57. // listener to three different events and sends a thousand integers for each
  58. // of the three events.
  59. func TestAddListenerForDifferentEvents(t *testing.T) {
  60. evsw := NewEventSwitch()
  61. err := evsw.Start()
  62. require.NoError(t, err)
  63. defer evsw.Stop()
  64. doneSum := make(chan uint64)
  65. doneSending1 := make(chan uint64)
  66. doneSending2 := make(chan uint64)
  67. doneSending3 := make(chan uint64)
  68. numbers := make(chan uint64, 4)
  69. // subscribe one listener to three events
  70. evsw.AddListenerForEvent("listener", "event1",
  71. func(data EventData) {
  72. numbers <- data.(uint64)
  73. })
  74. evsw.AddListenerForEvent("listener", "event2",
  75. func(data EventData) {
  76. numbers <- data.(uint64)
  77. })
  78. evsw.AddListenerForEvent("listener", "event3",
  79. func(data EventData) {
  80. numbers <- data.(uint64)
  81. })
  82. // collect received events
  83. go sumReceivedNumbers(numbers, doneSum)
  84. // go fire events
  85. go fireEvents(evsw, "event1", doneSending1, uint64(1))
  86. go fireEvents(evsw, "event2", doneSending2, uint64(1))
  87. go fireEvents(evsw, "event3", doneSending3, uint64(1))
  88. var checkSum uint64 = 0
  89. checkSum += <-doneSending1
  90. checkSum += <-doneSending2
  91. checkSum += <-doneSending3
  92. close(numbers)
  93. eventSum := <-doneSum
  94. if checkSum != eventSum {
  95. t.Errorf("Not all messages sent were received.\n")
  96. }
  97. }
  98. // TestAddDifferentListenerForDifferentEvents sets up an EventSwitch,
  99. // subscribes a first listener to three events, and subscribes a second
  100. // listener to two of those three events, and then sends a thousand integers
  101. // for each of the three events.
  102. func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
  103. evsw := NewEventSwitch()
  104. err := evsw.Start()
  105. require.NoError(t, err)
  106. defer evsw.Stop()
  107. doneSum1 := make(chan uint64)
  108. doneSum2 := make(chan uint64)
  109. doneSending1 := make(chan uint64)
  110. doneSending2 := make(chan uint64)
  111. doneSending3 := make(chan uint64)
  112. numbers1 := make(chan uint64, 4)
  113. numbers2 := make(chan uint64, 4)
  114. // subscribe two listener to three events
  115. evsw.AddListenerForEvent("listener1", "event1",
  116. func(data EventData) {
  117. numbers1 <- data.(uint64)
  118. })
  119. evsw.AddListenerForEvent("listener1", "event2",
  120. func(data EventData) {
  121. numbers1 <- data.(uint64)
  122. })
  123. evsw.AddListenerForEvent("listener1", "event3",
  124. func(data EventData) {
  125. numbers1 <- data.(uint64)
  126. })
  127. evsw.AddListenerForEvent("listener2", "event2",
  128. func(data EventData) {
  129. numbers2 <- data.(uint64)
  130. })
  131. evsw.AddListenerForEvent("listener2", "event3",
  132. func(data EventData) {
  133. numbers2 <- data.(uint64)
  134. })
  135. // collect received events for listener1
  136. go sumReceivedNumbers(numbers1, doneSum1)
  137. // collect received events for listener2
  138. go sumReceivedNumbers(numbers2, doneSum2)
  139. // go fire events
  140. go fireEvents(evsw, "event1", doneSending1, uint64(1))
  141. go fireEvents(evsw, "event2", doneSending2, uint64(1001))
  142. go fireEvents(evsw, "event3", doneSending3, uint64(2001))
  143. checkSumEvent1 := <-doneSending1
  144. checkSumEvent2 := <-doneSending2
  145. checkSumEvent3 := <-doneSending3
  146. checkSum1 := checkSumEvent1 + checkSumEvent2 + checkSumEvent3
  147. checkSum2 := checkSumEvent2 + checkSumEvent3
  148. close(numbers1)
  149. close(numbers2)
  150. eventSum1 := <-doneSum1
  151. eventSum2 := <-doneSum2
  152. if checkSum1 != eventSum1 ||
  153. checkSum2 != eventSum2 {
  154. t.Errorf("Not all messages sent were received for different listeners to different events.\n")
  155. }
  156. }
  157. func TestAddAndRemoveListenerConcurrency(t *testing.T) {
  158. var (
  159. stopInputEvent = false
  160. roundCount = 2000
  161. )
  162. evsw := NewEventSwitch()
  163. err := evsw.Start()
  164. require.NoError(t, err)
  165. defer evsw.Stop()
  166. done1 := make(chan struct{})
  167. done2 := make(chan struct{})
  168. // Must be executed concurrently to uncover the data race.
  169. // 1. RemoveListener
  170. go func() {
  171. for i := 0; i < roundCount; i++ {
  172. evsw.RemoveListener("listener")
  173. }
  174. close(done1)
  175. }()
  176. // 2. AddListenerForEvent
  177. go func() {
  178. for i := 0; i < roundCount; i++ {
  179. index := i
  180. evsw.AddListenerForEvent("listener", fmt.Sprintf("event%d", index),
  181. func(data EventData) {
  182. t.Errorf("should not run callback for %d.\n", index)
  183. stopInputEvent = true
  184. })
  185. }
  186. close(done2)
  187. }()
  188. <-done1
  189. <-done2
  190. evsw.RemoveListener("listener") // remove the last listener
  191. for i := 0; i < roundCount && !stopInputEvent; i++ {
  192. evsw.FireEvent(fmt.Sprintf("event%d", i), uint64(1001))
  193. }
  194. }
  195. // TestAddAndRemoveListener sets up an EventSwitch, subscribes a listener to
  196. // two events, fires a thousand integers for the first event, then unsubscribes
  197. // the listener and fires a thousand integers for the second event.
  198. func TestAddAndRemoveListener(t *testing.T) {
  199. evsw := NewEventSwitch()
  200. err := evsw.Start()
  201. require.NoError(t, err)
  202. defer evsw.Stop()
  203. doneSum1 := make(chan uint64)
  204. doneSum2 := make(chan uint64)
  205. doneSending1 := make(chan uint64)
  206. doneSending2 := make(chan uint64)
  207. numbers1 := make(chan uint64, 4)
  208. numbers2 := make(chan uint64, 4)
  209. // subscribe two listener to three events
  210. evsw.AddListenerForEvent("listener", "event1",
  211. func(data EventData) {
  212. numbers1 <- data.(uint64)
  213. })
  214. evsw.AddListenerForEvent("listener", "event2",
  215. func(data EventData) {
  216. numbers2 <- data.(uint64)
  217. })
  218. // collect received events for event1
  219. go sumReceivedNumbers(numbers1, doneSum1)
  220. // collect received events for event2
  221. go sumReceivedNumbers(numbers2, doneSum2)
  222. // go fire events
  223. go fireEvents(evsw, "event1", doneSending1, uint64(1))
  224. checkSumEvent1 := <-doneSending1
  225. // after sending all event1, unsubscribe for all events
  226. evsw.RemoveListener("listener")
  227. go fireEvents(evsw, "event2", doneSending2, uint64(1001))
  228. checkSumEvent2 := <-doneSending2
  229. close(numbers1)
  230. close(numbers2)
  231. eventSum1 := <-doneSum1
  232. eventSum2 := <-doneSum2
  233. if checkSumEvent1 != eventSum1 ||
  234. // correct value asserted by preceding tests, suffices to be non-zero
  235. checkSumEvent2 == uint64(0) ||
  236. eventSum2 != uint64(0) {
  237. t.Errorf("Not all messages sent were received or unsubscription did not register.\n")
  238. }
  239. }
  240. // TestRemoveListener does basic tests on adding and removing
  241. func TestRemoveListener(t *testing.T) {
  242. evsw := NewEventSwitch()
  243. err := evsw.Start()
  244. require.NoError(t, err)
  245. defer evsw.Stop()
  246. count := 10
  247. sum1, sum2 := 0, 0
  248. // add some listeners and make sure they work
  249. evsw.AddListenerForEvent("listener", "event1",
  250. func(data EventData) {
  251. sum1++
  252. })
  253. evsw.AddListenerForEvent("listener", "event2",
  254. func(data EventData) {
  255. sum2++
  256. })
  257. for i := 0; i < count; i++ {
  258. evsw.FireEvent("event1", true)
  259. evsw.FireEvent("event2", true)
  260. }
  261. assert.Equal(t, count, sum1)
  262. assert.Equal(t, count, sum2)
  263. // remove one by event and make sure it is gone
  264. evsw.RemoveListenerForEvent("event2", "listener")
  265. for i := 0; i < count; i++ {
  266. evsw.FireEvent("event1", true)
  267. evsw.FireEvent("event2", true)
  268. }
  269. assert.Equal(t, count*2, sum1)
  270. assert.Equal(t, count, sum2)
  271. // remove the listener entirely and make sure both gone
  272. evsw.RemoveListener("listener")
  273. for i := 0; i < count; i++ {
  274. evsw.FireEvent("event1", true)
  275. evsw.FireEvent("event2", true)
  276. }
  277. assert.Equal(t, count*2, sum1)
  278. assert.Equal(t, count, sum2)
  279. }
  280. // TestAddAndRemoveListenersAsync sets up an EventSwitch, subscribes two
  281. // listeners to three events, and fires a thousand integers for each event.
  282. // These two listeners serve as the baseline validation while other listeners
  283. // are randomly subscribed and unsubscribed.
  284. // More precisely it randomly subscribes new listeners (different from the first
  285. // two listeners) to one of these three events. At the same time it starts
  286. // randomly unsubscribing these additional listeners from all events they are
  287. // at that point subscribed to.
  288. // NOTE: it is important to run this test with race conditions tracking on,
  289. // `go test -race`, to examine for possible race conditions.
  290. func TestRemoveListenersAsync(t *testing.T) {
  291. evsw := NewEventSwitch()
  292. err := evsw.Start()
  293. require.NoError(t, err)
  294. defer evsw.Stop()
  295. doneSum1 := make(chan uint64)
  296. doneSum2 := make(chan uint64)
  297. doneSending1 := make(chan uint64)
  298. doneSending2 := make(chan uint64)
  299. doneSending3 := make(chan uint64)
  300. numbers1 := make(chan uint64, 4)
  301. numbers2 := make(chan uint64, 4)
  302. // subscribe two listener to three events
  303. evsw.AddListenerForEvent("listener1", "event1",
  304. func(data EventData) {
  305. numbers1 <- data.(uint64)
  306. })
  307. evsw.AddListenerForEvent("listener1", "event2",
  308. func(data EventData) {
  309. numbers1 <- data.(uint64)
  310. })
  311. evsw.AddListenerForEvent("listener1", "event3",
  312. func(data EventData) {
  313. numbers1 <- data.(uint64)
  314. })
  315. evsw.AddListenerForEvent("listener2", "event1",
  316. func(data EventData) {
  317. numbers2 <- data.(uint64)
  318. })
  319. evsw.AddListenerForEvent("listener2", "event2",
  320. func(data EventData) {
  321. numbers2 <- data.(uint64)
  322. })
  323. evsw.AddListenerForEvent("listener2", "event3",
  324. func(data EventData) {
  325. numbers2 <- data.(uint64)
  326. })
  327. // collect received events for event1
  328. go sumReceivedNumbers(numbers1, doneSum1)
  329. // collect received events for event2
  330. go sumReceivedNumbers(numbers2, doneSum2)
  331. addListenersStress := func() {
  332. r1 := cmn.NewRand()
  333. r1.Seed(time.Now().UnixNano())
  334. for k := uint16(0); k < 400; k++ {
  335. listenerNumber := r1.Intn(100) + 3
  336. eventNumber := r1.Intn(3) + 1
  337. go evsw.AddListenerForEvent(fmt.Sprintf("listener%v", listenerNumber),
  338. fmt.Sprintf("event%v", eventNumber),
  339. func(_ EventData) {})
  340. }
  341. }
  342. removeListenersStress := func() {
  343. r2 := cmn.NewRand()
  344. r2.Seed(time.Now().UnixNano())
  345. for k := uint16(0); k < 80; k++ {
  346. listenerNumber := r2.Intn(100) + 3
  347. go evsw.RemoveListener(fmt.Sprintf("listener%v", listenerNumber))
  348. }
  349. }
  350. addListenersStress()
  351. // go fire events
  352. go fireEvents(evsw, "event1", doneSending1, uint64(1))
  353. removeListenersStress()
  354. go fireEvents(evsw, "event2", doneSending2, uint64(1001))
  355. go fireEvents(evsw, "event3", doneSending3, uint64(2001))
  356. checkSumEvent1 := <-doneSending1
  357. checkSumEvent2 := <-doneSending2
  358. checkSumEvent3 := <-doneSending3
  359. checkSum := checkSumEvent1 + checkSumEvent2 + checkSumEvent3
  360. close(numbers1)
  361. close(numbers2)
  362. eventSum1 := <-doneSum1
  363. eventSum2 := <-doneSum2
  364. if checkSum != eventSum1 ||
  365. checkSum != eventSum2 {
  366. t.Errorf("Not all messages sent were received.\n")
  367. }
  368. }
  369. //------------------------------------------------------------------------------
  370. // Helper functions
  371. // sumReceivedNumbers takes two channels and adds all numbers received
  372. // until the receiving channel `numbers` is closed; it then sends the sum
  373. // on `doneSum` and closes that channel. Expected to be run in a go-routine.
  374. func sumReceivedNumbers(numbers, doneSum chan uint64) {
  375. var sum uint64
  376. for {
  377. j, more := <-numbers
  378. sum += j
  379. if !more {
  380. doneSum <- sum
  381. close(doneSum)
  382. return
  383. }
  384. }
  385. }
  386. // fireEvents takes an EventSwitch and fires a thousand integers under
  387. // a given `event` with the integers mootonically increasing from `offset`
  388. // to `offset` + 999. It additionally returns the addition of all integers
  389. // sent on `doneChan` for assertion that all events have been sent, and enabling
  390. // the test to assert all events have also been received.
  391. func fireEvents(evsw Fireable, event string, doneChan chan uint64,
  392. offset uint64) {
  393. var sentSum uint64
  394. for i := offset; i <= offset+uint64(999); i++ {
  395. sentSum += i
  396. evsw.FireEvent(event, i)
  397. }
  398. doneChan <- sentSum
  399. close(doneChan)
  400. }