github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/internal/p2p/p2ptest/require.go (about) 1 package p2ptest 2 3 import ( 4 "context" 5 "errors" 6 "testing" 7 "time" 8 9 "github.com/gogo/protobuf/proto" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/ari-anchor/sei-tendermint/internal/p2p" 14 "github.com/ari-anchor/sei-tendermint/types" 15 ) 16 17 // RequireEmpty requires that the given channel is empty. 18 func RequireEmpty(ctx context.Context, t *testing.T, channels ...*p2p.Channel) { 19 t.Helper() 20 21 ctx, cancel := context.WithTimeout(ctx, 10*time.Millisecond) 22 defer cancel() 23 24 iter := p2p.MergedChannelIterator(ctx, channels...) 25 count := 0 26 for iter.Next(ctx) { 27 count++ 28 require.Nil(t, iter.Envelope()) 29 } 30 require.Zero(t, count) 31 require.Error(t, ctx.Err()) 32 } 33 34 // RequireReceive requires that the given envelope is received on the channel. 35 func RequireReceive(ctx context.Context, t *testing.T, channel *p2p.Channel, expect p2p.Envelope) { 36 t.Helper() 37 38 ctx, cancel := context.WithTimeout(ctx, time.Second) 39 defer cancel() 40 41 iter := channel.Receive(ctx) 42 count := 0 43 for iter.Next(ctx) { 44 count++ 45 envelope := iter.Envelope() 46 require.Equal(t, expect.From, envelope.From) 47 require.Equal(t, expect.Message, envelope.Message) 48 } 49 50 if !assert.True(t, count >= 1) { 51 require.NoError(t, ctx.Err(), "timed out waiting for message %v", expect) 52 } 53 } 54 55 // RequireReceiveUnordered requires that the given envelopes are all received on 56 // the channel, ignoring order. 57 func RequireReceiveUnordered(ctx context.Context, t *testing.T, channel *p2p.Channel, expect []*p2p.Envelope) { 58 ctx, cancel := context.WithTimeout(ctx, time.Second) 59 defer cancel() 60 61 actual := []*p2p.Envelope{} 62 63 iter := channel.Receive(ctx) 64 for iter.Next(ctx) { 65 actual = append(actual, iter.Envelope()) 66 if len(actual) == len(expect) { 67 require.ElementsMatch(t, expect, actual, "len=%d", len(actual)) 68 return 69 } 70 } 71 72 if errors.Is(ctx.Err(), context.DeadlineExceeded) { 73 require.ElementsMatch(t, expect, actual) 74 } 75 } 76 77 // RequireSend requires that the given envelope is sent on the channel. 78 func RequireSend(ctx context.Context, t *testing.T, channel *p2p.Channel, envelope p2p.Envelope) { 79 tctx, cancel := context.WithTimeout(ctx, time.Second) 80 defer cancel() 81 82 err := channel.Send(tctx, envelope) 83 switch { 84 case errors.Is(err, context.DeadlineExceeded): 85 require.Fail(t, "timed out sending message to %q", envelope.To) 86 default: 87 require.NoError(t, err, "unexpected error") 88 } 89 } 90 91 // RequireSendReceive requires that a given Protobuf message is sent to the 92 // given peer, and then that the given response is received back. 93 func RequireSendReceive( 94 ctx context.Context, 95 t *testing.T, 96 channel *p2p.Channel, 97 peerID types.NodeID, 98 send proto.Message, 99 receive proto.Message, 100 ) { 101 RequireSend(ctx, t, channel, p2p.Envelope{To: peerID, Message: send}) 102 RequireReceive(ctx, t, channel, p2p.Envelope{From: peerID, Message: send}) 103 } 104 105 // RequireNoUpdates requires that a PeerUpdates subscription is empty. 106 func RequireNoUpdates(ctx context.Context, t *testing.T, peerUpdates *p2p.PeerUpdates) { 107 t.Helper() 108 select { 109 case update := <-peerUpdates.Updates(): 110 if ctx.Err() == nil { 111 require.Fail(t, "unexpected peer updates", "got %v", update) 112 } 113 case <-ctx.Done(): 114 default: 115 } 116 } 117 118 // RequireError requires that the given peer error is submitted for a peer. 119 func RequireError(ctx context.Context, t *testing.T, channel *p2p.Channel, peerError p2p.PeerError) { 120 tctx, tcancel := context.WithTimeout(ctx, time.Second) 121 defer tcancel() 122 123 err := channel.SendError(tctx, peerError) 124 switch { 125 case errors.Is(err, context.DeadlineExceeded): 126 require.Fail(t, "timed out reporting error", "%v for %q", peerError, channel.String()) 127 default: 128 require.NoError(t, err, "unexpected error") 129 } 130 } 131 132 // RequireUpdate requires that a PeerUpdates subscription yields the given update. 133 func RequireUpdate(t *testing.T, peerUpdates *p2p.PeerUpdates, expect p2p.PeerUpdate) { 134 timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks 135 defer timer.Stop() 136 137 select { 138 case update := <-peerUpdates.Updates(): 139 require.Equal(t, expect.NodeID, update.NodeID, "node id did not match") 140 require.Equal(t, expect.Status, update.Status, "statuses did not match") 141 case <-timer.C: 142 require.Fail(t, "timed out waiting for peer update", "expected %v", expect) 143 } 144 } 145 146 // RequireUpdates requires that a PeerUpdates subscription yields the given updates 147 // in the given order. 148 func RequireUpdates(t *testing.T, peerUpdates *p2p.PeerUpdates, expect []p2p.PeerUpdate) { 149 timer := time.NewTimer(time.Second) // not time.After due to goroutine leaks 150 defer timer.Stop() 151 152 actual := []p2p.PeerUpdate{} 153 for { 154 select { 155 case update := <-peerUpdates.Updates(): 156 actual = append(actual, update) 157 if len(actual) == len(expect) { 158 for idx := range expect { 159 require.Equal(t, expect[idx].NodeID, actual[idx].NodeID) 160 require.Equal(t, expect[idx].Status, actual[idx].Status) 161 } 162 163 return 164 } 165 166 case <-timer.C: 167 require.Equal(t, expect, actual, "did not receive expected peer updates") 168 return 169 } 170 } 171 }