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.

566 lines
16 KiB

lint: Enable Golint (#4212) * Fix many golint errors * Fix golint errors in the 'lite' package * Don't export Pool.store * Fix typo * Revert unwanted changes * Fix errors in counter package * Fix linter errors in kvstore package * Fix linter error in example package * Fix error in tests package * Fix linter errors in v2 package * Fix linter errors in consensus package * Fix linter errors in evidence package * Fix linter error in fail package * Fix linter errors in query package * Fix linter errors in core package * Fix linter errors in node package * Fix linter errors in mempool package * Fix linter error in conn package * Fix linter errors in pex package * Rename PEXReactor export to Reactor * Fix linter errors in trust package * Fix linter errors in upnp package * Fix linter errors in p2p package * Fix linter errors in proxy package * Fix linter errors in mock_test package * Fix linter error in client_test package * Fix linter errors in coretypes package * Fix linter errors in coregrpc package * Fix linter errors in rpcserver package * Fix linter errors in rpctypes package * Fix linter errors in rpctest package * Fix linter error in json2wal script * Fix linter error in wal2json script * Fix linter errors in kv package * Fix linter error in state package * Fix linter error in grpc_client * Fix linter errors in types package * Fix linter error in version package * Fix remaining errors * Address review comments * Fix broken tests * Reconcile package coregrpc * Fix golangci bot error * Fix new golint errors * Fix broken reference * Enable golint linter * minor changes to bring golint into line * fix failing test * fix pex reactor naming * address PR comments
5 years ago
  1. package events
  2. import (
  3. "context"
  4. "fmt"
  5. "math/rand"
  6. "testing"
  7. "time"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. "github.com/tendermint/tendermint/libs/log"
  11. )
  12. // TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single
  13. // listener to an event, and sends a string "data".
  14. func TestAddListenerForEventFireOnce(t *testing.T) {
  15. ctx, cancel := context.WithCancel(context.Background())
  16. defer cancel()
  17. logger := log.NewTestingLogger(t)
  18. evsw := NewEventSwitch(logger)
  19. require.NoError(t, evsw.Start(ctx))
  20. t.Cleanup(evsw.Wait)
  21. messages := make(chan EventData)
  22. require.NoError(t, evsw.AddListenerForEvent("listener", "event",
  23. func(ctx context.Context, data EventData) error {
  24. // test there's no deadlock if we remove the listener inside a callback
  25. evsw.RemoveListener("listener")
  26. select {
  27. case messages <- data:
  28. return nil
  29. case <-ctx.Done():
  30. return ctx.Err()
  31. }
  32. }))
  33. go evsw.FireEvent(ctx, "event", "data")
  34. received := <-messages
  35. if received != "data" {
  36. t.Errorf("message received does not match: %v", received)
  37. }
  38. }
  39. // TestAddListenerForEventFireMany sets up an EventSwitch, subscribes a single
  40. // listener to an event, and sends a thousand integers.
  41. func TestAddListenerForEventFireMany(t *testing.T) {
  42. ctx, cancel := context.WithCancel(context.Background())
  43. defer cancel()
  44. logger := log.NewTestingLogger(t)
  45. evsw := NewEventSwitch(logger)
  46. require.NoError(t, evsw.Start(ctx))
  47. t.Cleanup(evsw.Wait)
  48. doneSum := make(chan uint64)
  49. doneSending := make(chan uint64)
  50. numbers := make(chan uint64, 4)
  51. // subscribe one listener for one event
  52. require.NoError(t, evsw.AddListenerForEvent("listener", "event",
  53. func(ctx context.Context, data EventData) error {
  54. select {
  55. case numbers <- data.(uint64):
  56. return nil
  57. case <-ctx.Done():
  58. return ctx.Err()
  59. }
  60. }))
  61. // collect received events
  62. go sumReceivedNumbers(numbers, doneSum)
  63. // go fire events
  64. go fireEvents(ctx, evsw, "event", doneSending, uint64(1))
  65. checkSum := <-doneSending
  66. close(numbers)
  67. eventSum := <-doneSum
  68. if checkSum != eventSum {
  69. t.Errorf("not all messages sent were received.\n")
  70. }
  71. }
  72. // TestAddListenerForDifferentEvents sets up an EventSwitch, subscribes a single
  73. // listener to three different events and sends a thousand integers for each
  74. // of the three events.
  75. func TestAddListenerForDifferentEvents(t *testing.T) {
  76. ctx, cancel := context.WithCancel(context.Background())
  77. defer cancel()
  78. logger := log.NewTestingLogger(t)
  79. evsw := NewEventSwitch(logger)
  80. require.NoError(t, evsw.Start(ctx))
  81. t.Cleanup(evsw.Wait)
  82. doneSum := make(chan uint64)
  83. doneSending1 := make(chan uint64)
  84. doneSending2 := make(chan uint64)
  85. doneSending3 := make(chan uint64)
  86. numbers := make(chan uint64, 4)
  87. // subscribe one listener to three events
  88. require.NoError(t, evsw.AddListenerForEvent("listener", "event1",
  89. func(ctx context.Context, data EventData) error {
  90. select {
  91. case numbers <- data.(uint64):
  92. return nil
  93. case <-ctx.Done():
  94. return ctx.Err()
  95. }
  96. }))
  97. require.NoError(t, evsw.AddListenerForEvent("listener", "event2",
  98. func(ctx context.Context, data EventData) error {
  99. select {
  100. case numbers <- data.(uint64):
  101. return nil
  102. case <-ctx.Done():
  103. return ctx.Err()
  104. }
  105. }))
  106. require.NoError(t, evsw.AddListenerForEvent("listener", "event3",
  107. func(ctx context.Context, data EventData) error {
  108. select {
  109. case numbers <- data.(uint64):
  110. return nil
  111. case <-ctx.Done():
  112. return ctx.Err()
  113. }
  114. }))
  115. // collect received events
  116. go sumReceivedNumbers(numbers, doneSum)
  117. // go fire events
  118. go fireEvents(ctx, evsw, "event1", doneSending1, uint64(1))
  119. go fireEvents(ctx, evsw, "event2", doneSending2, uint64(1))
  120. go fireEvents(ctx, evsw, "event3", doneSending3, uint64(1))
  121. var checkSum uint64
  122. checkSum += <-doneSending1
  123. checkSum += <-doneSending2
  124. checkSum += <-doneSending3
  125. close(numbers)
  126. eventSum := <-doneSum
  127. if checkSum != eventSum {
  128. t.Errorf("not all messages sent were received.\n")
  129. }
  130. }
  131. // TestAddDifferentListenerForDifferentEvents sets up an EventSwitch,
  132. // subscribes a first listener to three events, and subscribes a second
  133. // listener to two of those three events, and then sends a thousand integers
  134. // for each of the three events.
  135. func TestAddDifferentListenerForDifferentEvents(t *testing.T) {
  136. ctx, cancel := context.WithCancel(context.Background())
  137. defer cancel()
  138. logger := log.NewTestingLogger(t)
  139. evsw := NewEventSwitch(logger)
  140. require.NoError(t, evsw.Start(ctx))
  141. t.Cleanup(evsw.Wait)
  142. doneSum1 := make(chan uint64)
  143. doneSum2 := make(chan uint64)
  144. doneSending1 := make(chan uint64)
  145. doneSending2 := make(chan uint64)
  146. doneSending3 := make(chan uint64)
  147. numbers1 := make(chan uint64, 4)
  148. numbers2 := make(chan uint64, 4)
  149. // subscribe two listener to three events
  150. require.NoError(t, evsw.AddListenerForEvent("listener1", "event1",
  151. func(ctx context.Context, data EventData) error {
  152. select {
  153. case numbers1 <- data.(uint64):
  154. return nil
  155. case <-ctx.Done():
  156. return ctx.Err()
  157. }
  158. }))
  159. require.NoError(t, evsw.AddListenerForEvent("listener1", "event2",
  160. func(ctx context.Context, data EventData) error {
  161. select {
  162. case numbers1 <- data.(uint64):
  163. return nil
  164. case <-ctx.Done():
  165. return ctx.Err()
  166. }
  167. }))
  168. require.NoError(t, evsw.AddListenerForEvent("listener1", "event3",
  169. func(ctx context.Context, data EventData) error {
  170. select {
  171. case numbers1 <- data.(uint64):
  172. return nil
  173. case <-ctx.Done():
  174. return ctx.Err()
  175. }
  176. }))
  177. require.NoError(t, evsw.AddListenerForEvent("listener2", "event2",
  178. func(ctx context.Context, data EventData) error {
  179. select {
  180. case numbers2 <- data.(uint64):
  181. return nil
  182. case <-ctx.Done():
  183. return ctx.Err()
  184. }
  185. }))
  186. require.NoError(t, evsw.AddListenerForEvent("listener2", "event3",
  187. func(ctx context.Context, data EventData) error {
  188. select {
  189. case numbers2 <- data.(uint64):
  190. return nil
  191. case <-ctx.Done():
  192. return ctx.Err()
  193. }
  194. }))
  195. // collect received events for listener1
  196. go sumReceivedNumbers(numbers1, doneSum1)
  197. // collect received events for listener2
  198. go sumReceivedNumbers(numbers2, doneSum2)
  199. // go fire events
  200. go fireEvents(ctx, evsw, "event1", doneSending1, uint64(1))
  201. go fireEvents(ctx, evsw, "event2", doneSending2, uint64(1001))
  202. go fireEvents(ctx, evsw, "event3", doneSending3, uint64(2001))
  203. checkSumEvent1 := <-doneSending1
  204. checkSumEvent2 := <-doneSending2
  205. checkSumEvent3 := <-doneSending3
  206. checkSum1 := checkSumEvent1 + checkSumEvent2 + checkSumEvent3
  207. checkSum2 := checkSumEvent2 + checkSumEvent3
  208. close(numbers1)
  209. close(numbers2)
  210. eventSum1 := <-doneSum1
  211. eventSum2 := <-doneSum2
  212. if checkSum1 != eventSum1 ||
  213. checkSum2 != eventSum2 {
  214. t.Errorf("not all messages sent were received for different listeners to different events.\n")
  215. }
  216. }
  217. func TestAddAndRemoveListenerConcurrency(t *testing.T) {
  218. var (
  219. stopInputEvent = false
  220. roundCount = 2000
  221. )
  222. ctx, cancel := context.WithCancel(context.Background())
  223. defer cancel()
  224. logger := log.NewTestingLogger(t)
  225. evsw := NewEventSwitch(logger)
  226. require.NoError(t, evsw.Start(ctx))
  227. t.Cleanup(evsw.Wait)
  228. done1 := make(chan struct{})
  229. done2 := make(chan struct{})
  230. // Must be executed concurrently to uncover the data race.
  231. // 1. RemoveListener
  232. go func() {
  233. defer close(done1)
  234. for i := 0; i < roundCount; i++ {
  235. evsw.RemoveListener("listener")
  236. }
  237. }()
  238. // 2. AddListenerForEvent
  239. go func() {
  240. defer close(done2)
  241. for i := 0; i < roundCount; i++ {
  242. index := i
  243. // we explicitly ignore errors here, since the listener will sometimes be removed
  244. // (that's what we're testing)
  245. _ = evsw.AddListenerForEvent("listener", fmt.Sprintf("event%d", index),
  246. func(ctx context.Context, data EventData) error {
  247. t.Errorf("should not run callback for %d.\n", index)
  248. stopInputEvent = true
  249. return nil
  250. })
  251. }
  252. }()
  253. <-done1
  254. <-done2
  255. evsw.RemoveListener("listener") // remove the last listener
  256. for i := 0; i < roundCount && !stopInputEvent; i++ {
  257. evsw.FireEvent(ctx, fmt.Sprintf("event%d", i), uint64(1001))
  258. }
  259. }
  260. // TestAddAndRemoveListener sets up an EventSwitch, subscribes a listener to
  261. // two events, fires a thousand integers for the first event, then unsubscribes
  262. // the listener and fires a thousand integers for the second event.
  263. func TestAddAndRemoveListener(t *testing.T) {
  264. ctx, cancel := context.WithCancel(context.Background())
  265. defer cancel()
  266. logger := log.NewTestingLogger(t)
  267. evsw := NewEventSwitch(logger)
  268. require.NoError(t, evsw.Start(ctx))
  269. t.Cleanup(evsw.Wait)
  270. doneSum1 := make(chan uint64)
  271. doneSum2 := make(chan uint64)
  272. doneSending1 := make(chan uint64)
  273. doneSending2 := make(chan uint64)
  274. numbers1 := make(chan uint64, 4)
  275. numbers2 := make(chan uint64, 4)
  276. // subscribe two listener to three events
  277. require.NoError(t, evsw.AddListenerForEvent("listener", "event1",
  278. func(ctx context.Context, data EventData) error {
  279. select {
  280. case numbers1 <- data.(uint64):
  281. return nil
  282. case <-ctx.Done():
  283. return ctx.Err()
  284. }
  285. }))
  286. require.NoError(t, evsw.AddListenerForEvent("listener", "event2",
  287. func(ctx context.Context, data EventData) error {
  288. select {
  289. case numbers2 <- data.(uint64):
  290. return nil
  291. case <-ctx.Done():
  292. return ctx.Err()
  293. }
  294. }))
  295. // collect received events for event1
  296. go sumReceivedNumbers(numbers1, doneSum1)
  297. // collect received events for event2
  298. go sumReceivedNumbers(numbers2, doneSum2)
  299. // go fire events
  300. go fireEvents(ctx, evsw, "event1", doneSending1, uint64(1))
  301. checkSumEvent1 := <-doneSending1
  302. // after sending all event1, unsubscribe for all events
  303. evsw.RemoveListener("listener")
  304. go fireEvents(ctx, evsw, "event2", doneSending2, uint64(1001))
  305. checkSumEvent2 := <-doneSending2
  306. close(numbers1)
  307. close(numbers2)
  308. eventSum1 := <-doneSum1
  309. eventSum2 := <-doneSum2
  310. if checkSumEvent1 != eventSum1 ||
  311. // correct value asserted by preceding tests, suffices to be non-zero
  312. checkSumEvent2 == uint64(0) ||
  313. eventSum2 != uint64(0) {
  314. t.Errorf("not all messages sent were received or unsubscription did not register.\n")
  315. }
  316. }
  317. // TestRemoveListener does basic tests on adding and removing
  318. func TestRemoveListener(t *testing.T) {
  319. ctx, cancel := context.WithCancel(context.Background())
  320. defer cancel()
  321. logger := log.NewTestingLogger(t)
  322. evsw := NewEventSwitch(logger)
  323. require.NoError(t, evsw.Start(ctx))
  324. t.Cleanup(evsw.Wait)
  325. count := 10
  326. sum1, sum2 := 0, 0
  327. // add some listeners and make sure they work
  328. require.NoError(t, evsw.AddListenerForEvent("listener", "event1",
  329. func(ctx context.Context, data EventData) error {
  330. sum1++
  331. return nil
  332. }))
  333. require.NoError(t, evsw.AddListenerForEvent("listener", "event2",
  334. func(ctx context.Context, data EventData) error {
  335. sum2++
  336. return nil
  337. }))
  338. for i := 0; i < count; i++ {
  339. evsw.FireEvent(ctx, "event1", true)
  340. evsw.FireEvent(ctx, "event2", true)
  341. }
  342. assert.Equal(t, count, sum1)
  343. assert.Equal(t, count, sum2)
  344. // remove one by event and make sure it is gone
  345. evsw.RemoveListenerForEvent("event2", "listener")
  346. for i := 0; i < count; i++ {
  347. evsw.FireEvent(ctx, "event1", true)
  348. evsw.FireEvent(ctx, "event2", true)
  349. }
  350. assert.Equal(t, count*2, sum1)
  351. assert.Equal(t, count, sum2)
  352. // remove the listener entirely and make sure both gone
  353. evsw.RemoveListener("listener")
  354. for i := 0; i < count; i++ {
  355. evsw.FireEvent(ctx, "event1", true)
  356. evsw.FireEvent(ctx, "event2", true)
  357. }
  358. assert.Equal(t, count*2, sum1)
  359. assert.Equal(t, count, sum2)
  360. }
  361. // TestAddAndRemoveListenersAsync sets up an EventSwitch, subscribes two
  362. // listeners to three events, and fires a thousand integers for each event.
  363. // These two listeners serve as the baseline validation while other listeners
  364. // are randomly subscribed and unsubscribed.
  365. // More precisely it randomly subscribes new listeners (different from the first
  366. // two listeners) to one of these three events. At the same time it starts
  367. // randomly unsubscribing these additional listeners from all events they are
  368. // at that point subscribed to.
  369. // NOTE: it is important to run this test with race conditions tracking on,
  370. // `go test -race`, to examine for possible race conditions.
  371. func TestRemoveListenersAsync(t *testing.T) {
  372. ctx, cancel := context.WithCancel(context.Background())
  373. defer cancel()
  374. logger := log.NewTestingLogger(t)
  375. evsw := NewEventSwitch(logger)
  376. require.NoError(t, evsw.Start(ctx))
  377. t.Cleanup(evsw.Wait)
  378. doneSum1 := make(chan uint64)
  379. doneSum2 := make(chan uint64)
  380. doneSending1 := make(chan uint64)
  381. doneSending2 := make(chan uint64)
  382. doneSending3 := make(chan uint64)
  383. numbers1 := make(chan uint64, 4)
  384. numbers2 := make(chan uint64, 4)
  385. // subscribe two listener to three events
  386. require.NoError(t, evsw.AddListenerForEvent("listener1", "event1",
  387. func(ctx context.Context, data EventData) error {
  388. select {
  389. case numbers1 <- data.(uint64):
  390. return nil
  391. case <-ctx.Done():
  392. return ctx.Err()
  393. }
  394. }))
  395. require.NoError(t, evsw.AddListenerForEvent("listener1", "event2",
  396. func(ctx context.Context, data EventData) error {
  397. select {
  398. case numbers1 <- data.(uint64):
  399. return nil
  400. case <-ctx.Done():
  401. return ctx.Err()
  402. }
  403. }))
  404. require.NoError(t, evsw.AddListenerForEvent("listener1", "event3",
  405. func(ctx context.Context, data EventData) error {
  406. select {
  407. case numbers1 <- data.(uint64):
  408. return nil
  409. case <-ctx.Done():
  410. return ctx.Err()
  411. }
  412. }))
  413. require.NoError(t, evsw.AddListenerForEvent("listener2", "event1",
  414. func(ctx context.Context, data EventData) error {
  415. select {
  416. case numbers2 <- data.(uint64):
  417. return nil
  418. case <-ctx.Done():
  419. return ctx.Err()
  420. }
  421. }))
  422. require.NoError(t, evsw.AddListenerForEvent("listener2", "event2",
  423. func(ctx context.Context, data EventData) error {
  424. select {
  425. case numbers2 <- data.(uint64):
  426. return nil
  427. case <-ctx.Done():
  428. return ctx.Err()
  429. }
  430. }))
  431. require.NoError(t, evsw.AddListenerForEvent("listener2", "event3",
  432. func(ctx context.Context, data EventData) error {
  433. select {
  434. case numbers2 <- data.(uint64):
  435. return nil
  436. case <-ctx.Done():
  437. return ctx.Err()
  438. }
  439. }))
  440. // collect received events for event1
  441. go sumReceivedNumbers(numbers1, doneSum1)
  442. // collect received events for event2
  443. go sumReceivedNumbers(numbers2, doneSum2)
  444. addListenersStress := func() {
  445. r1 := rand.New(rand.NewSource(time.Now().Unix()))
  446. r1.Seed(time.Now().UnixNano())
  447. for k := uint16(0); k < 400; k++ {
  448. listenerNumber := r1.Intn(100) + 3
  449. eventNumber := r1.Intn(3) + 1
  450. go evsw.AddListenerForEvent(fmt.Sprintf("listener%v", listenerNumber), //nolint:errcheck // ignore for tests
  451. fmt.Sprintf("event%v", eventNumber),
  452. func(context.Context, EventData) error { return nil })
  453. }
  454. }
  455. removeListenersStress := func() {
  456. r2 := rand.New(rand.NewSource(time.Now().Unix()))
  457. r2.Seed(time.Now().UnixNano())
  458. for k := uint16(0); k < 80; k++ {
  459. listenerNumber := r2.Intn(100) + 3
  460. go evsw.RemoveListener(fmt.Sprintf("listener%v", listenerNumber))
  461. }
  462. }
  463. addListenersStress()
  464. // go fire events
  465. go fireEvents(ctx, evsw, "event1", doneSending1, uint64(1))
  466. removeListenersStress()
  467. go fireEvents(ctx, evsw, "event2", doneSending2, uint64(1001))
  468. go fireEvents(ctx, evsw, "event3", doneSending3, uint64(2001))
  469. checkSumEvent1 := <-doneSending1
  470. checkSumEvent2 := <-doneSending2
  471. checkSumEvent3 := <-doneSending3
  472. checkSum := checkSumEvent1 + checkSumEvent2 + checkSumEvent3
  473. close(numbers1)
  474. close(numbers2)
  475. eventSum1 := <-doneSum1
  476. eventSum2 := <-doneSum2
  477. if checkSum != eventSum1 ||
  478. checkSum != eventSum2 {
  479. t.Errorf("not all messages sent were received.\n")
  480. }
  481. }
  482. //------------------------------------------------------------------------------
  483. // Helper functions
  484. // sumReceivedNumbers takes two channels and adds all numbers received
  485. // until the receiving channel `numbers` is closed; it then sends the sum
  486. // on `doneSum` and closes that channel. Expected to be run in a go-routine.
  487. func sumReceivedNumbers(numbers, doneSum chan uint64) {
  488. var sum uint64
  489. for {
  490. j, more := <-numbers
  491. sum += j
  492. if !more {
  493. doneSum <- sum
  494. close(doneSum)
  495. return
  496. }
  497. }
  498. }
  499. // fireEvents takes an EventSwitch and fires a thousand integers under
  500. // a given `event` with the integers mootonically increasing from `offset`
  501. // to `offset` + 999. It additionally returns the addition of all integers
  502. // sent on `doneChan` for assertion that all events have been sent, and enabling
  503. // the test to assert all events have also been received.
  504. func fireEvents(ctx context.Context, evsw Fireable, event string, doneChan chan uint64, offset uint64) {
  505. defer close(doneChan)
  506. var sentSum uint64
  507. for i := offset; i <= offset+uint64(999); i++ {
  508. if ctx.Err() != nil {
  509. break
  510. }
  511. evsw.FireEvent(ctx, event, i)
  512. sentSum += i
  513. }
  514. select {
  515. case <-ctx.Done():
  516. case doneChan <- sentSum:
  517. }
  518. }