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.

163 lines
4.6 KiB

  1. package p2ptest
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/gogo/protobuf/proto"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/tendermint/internal/p2p"
  9. "github.com/tendermint/tendermint/types"
  10. )
  11. // RequireEmpty requires that the given channel is empty.
  12. func RequireEmpty(t *testing.T, channels ...*p2p.Channel) {
  13. for _, channel := range channels {
  14. select {
  15. case e := <-channel.In:
  16. require.Fail(t, "unexpected message", "channel %v should be empty, got %v", channel.ID, e)
  17. case <-time.After(10 * time.Millisecond):
  18. }
  19. }
  20. }
  21. // RequireReceive requires that the given envelope is received on the channel.
  22. func RequireReceive(t *testing.T, channel *p2p.Channel, expect p2p.Envelope) {
  23. t.Helper()
  24. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  25. defer timer.Stop()
  26. select {
  27. case e, ok := <-channel.In:
  28. require.True(t, ok, "channel %v is closed", channel.ID)
  29. require.Equal(t, expect, e)
  30. case <-channel.Done():
  31. require.Fail(t, "channel %v is closed", channel.ID)
  32. case <-timer.C:
  33. require.Fail(t, "timed out waiting for message", "%v on channel %v", expect, channel.ID)
  34. }
  35. }
  36. // RequireReceiveUnordered requires that the given envelopes are all received on
  37. // the channel, ignoring order.
  38. func RequireReceiveUnordered(t *testing.T, channel *p2p.Channel, expect []p2p.Envelope) {
  39. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  40. defer timer.Stop()
  41. actual := []p2p.Envelope{}
  42. for {
  43. select {
  44. case e, ok := <-channel.In:
  45. require.True(t, ok, "channel %v is closed", channel.ID)
  46. actual = append(actual, e)
  47. if len(actual) == len(expect) {
  48. require.ElementsMatch(t, expect, actual)
  49. return
  50. }
  51. case <-channel.Done():
  52. require.Fail(t, "channel %v is closed", channel.ID)
  53. case <-timer.C:
  54. require.ElementsMatch(t, expect, actual)
  55. return
  56. }
  57. }
  58. }
  59. // RequireSend requires that the given envelope is sent on the channel.
  60. func RequireSend(t *testing.T, channel *p2p.Channel, envelope p2p.Envelope) {
  61. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  62. defer timer.Stop()
  63. select {
  64. case channel.Out <- envelope:
  65. case <-timer.C:
  66. require.Fail(t, "timed out sending message", "%v on channel %v", envelope, channel.ID)
  67. }
  68. }
  69. // RequireSendReceive requires that a given Protobuf message is sent to the
  70. // given peer, and then that the given response is received back.
  71. func RequireSendReceive(
  72. t *testing.T,
  73. channel *p2p.Channel,
  74. peerID types.NodeID,
  75. send proto.Message,
  76. receive proto.Message,
  77. ) {
  78. RequireSend(t, channel, p2p.Envelope{To: peerID, Message: send})
  79. RequireReceive(t, channel, p2p.Envelope{From: peerID, Message: send})
  80. }
  81. // RequireNoUpdates requires that a PeerUpdates subscription is empty.
  82. func RequireNoUpdates(ctx context.Context, t *testing.T, peerUpdates *p2p.PeerUpdates) {
  83. t.Helper()
  84. select {
  85. case update := <-peerUpdates.Updates():
  86. if ctx.Err() == nil {
  87. require.Fail(t, "unexpected peer updates", "got %v", update)
  88. }
  89. case <-ctx.Done():
  90. default:
  91. }
  92. }
  93. // RequireError requires that the given peer error is submitted for a peer.
  94. func RequireError(t *testing.T, channel *p2p.Channel, peerError p2p.PeerError) {
  95. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  96. defer timer.Stop()
  97. select {
  98. case channel.Error <- peerError:
  99. case <-timer.C:
  100. require.Fail(t, "timed out reporting error", "%v on %v", peerError, channel.ID)
  101. }
  102. }
  103. // RequireUpdate requires that a PeerUpdates subscription yields the given update.
  104. func RequireUpdate(t *testing.T, peerUpdates *p2p.PeerUpdates, expect p2p.PeerUpdate) {
  105. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  106. defer timer.Stop()
  107. select {
  108. case update := <-peerUpdates.Updates():
  109. require.Equal(t, expect, update, "peer update did not match")
  110. case <-peerUpdates.Done():
  111. require.Fail(t, "peer updates subscription is closed")
  112. case <-timer.C:
  113. require.Fail(t, "timed out waiting for peer update", "expected %v", expect)
  114. }
  115. }
  116. // RequireUpdates requires that a PeerUpdates subscription yields the given updates
  117. // in the given order.
  118. func RequireUpdates(t *testing.T, peerUpdates *p2p.PeerUpdates, expect []p2p.PeerUpdate) {
  119. timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks
  120. defer timer.Stop()
  121. actual := []p2p.PeerUpdate{}
  122. for {
  123. select {
  124. case update := <-peerUpdates.Updates():
  125. actual = append(actual, update)
  126. if len(actual) == len(expect) {
  127. require.Equal(t, expect, actual)
  128. return
  129. }
  130. case <-peerUpdates.Done():
  131. require.Fail(t, "peer updates subscription is closed")
  132. case <-timer.C:
  133. require.Equal(t, expect, actual, "did not receive expected peer updates")
  134. return
  135. }
  136. }
  137. }