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.

380 lines
12 KiB

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