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  }