|
|
- package p2p
-
- import (
- "context"
- "errors"
- "testing"
- "time"
-
- "github.com/fortytw2/leaktest"
- "github.com/stretchr/testify/require"
- )
-
- type channelInternal struct {
- In chan Envelope
- Out chan Envelope
- Error chan PeerError
- }
-
- func testChannel(size int) (*channelInternal, *Channel) {
- in := &channelInternal{
- In: make(chan Envelope, size),
- Out: make(chan Envelope, size),
- Error: make(chan PeerError, size),
- }
- ch := &Channel{
- inCh: in.In,
- outCh: in.Out,
- errCh: in.Error,
- }
- return in, ch
- }
-
- func TestChannel(t *testing.T) {
- t.Cleanup(leaktest.Check(t))
-
- bctx, bcancel := context.WithCancel(context.Background())
- defer bcancel()
-
- testCases := []struct {
- Name string
- Case func(context.Context, *testing.T)
- }{
- {
- Name: "Send",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
- require.NoError(t, ch.Send(ctx, Envelope{From: "kip", To: "merlin"}))
-
- res, ok := <-ins.Out
- require.True(t, ok)
- require.EqualValues(t, "kip", res.From)
- require.EqualValues(t, "merlin", res.To)
- },
- },
- {
- Name: "SendError",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
- require.NoError(t, ch.SendError(ctx, PeerError{NodeID: "kip", Err: errors.New("merlin")}))
-
- res, ok := <-ins.Error
- require.True(t, ok)
- require.EqualValues(t, "kip", res.NodeID)
- require.EqualValues(t, "merlin", res.Err.Error())
- },
- },
- {
- Name: "SendWithCanceledContext",
- Case: func(ctx context.Context, t *testing.T) {
- _, ch := testChannel(0)
- cctx, ccancel := context.WithCancel(ctx)
- ccancel()
- require.Error(t, ch.Send(cctx, Envelope{From: "kip", To: "merlin"}))
- },
- },
- {
- Name: "SendErrorWithCanceledContext",
- Case: func(ctx context.Context, t *testing.T) {
- _, ch := testChannel(0)
- cctx, ccancel := context.WithCancel(ctx)
- ccancel()
-
- require.Error(t, ch.SendError(cctx, PeerError{NodeID: "kip", Err: errors.New("merlin")}))
- },
- },
- {
- Name: "ReceiveEmptyIteratorBlocks",
- Case: func(ctx context.Context, t *testing.T) {
- _, ch := testChannel(1)
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
- out := make(chan bool)
- go func() {
- defer close(out)
- select {
- case <-ctx.Done():
- case out <- iter.Next(ctx):
- }
- }()
- select {
- case <-time.After(10 * time.Millisecond):
- case <-out:
- require.Fail(t, "iterator should not advance")
- }
- require.Nil(t, iter.Envelope())
- },
- },
- {
- Name: "ReceiveWithData",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
- ins.In <- Envelope{From: "kip", To: "merlin"}
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
- require.True(t, iter.Next(ctx))
-
- res := iter.Envelope()
- require.EqualValues(t, "kip", res.From)
- require.EqualValues(t, "merlin", res.To)
- },
- },
- {
- Name: "ReceiveWithCanceledContext",
- Case: func(ctx context.Context, t *testing.T) {
- _, ch := testChannel(0)
- cctx, ccancel := context.WithCancel(ctx)
- ccancel()
-
- iter := ch.Receive(cctx)
- require.NotNil(t, iter)
- require.False(t, iter.Next(cctx))
- require.Nil(t, iter.Envelope())
- },
- },
- {
- Name: "IteratorWithCanceledContext",
- Case: func(ctx context.Context, t *testing.T) {
- _, ch := testChannel(0)
-
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
-
- cctx, ccancel := context.WithCancel(ctx)
- ccancel()
- require.False(t, iter.Next(cctx))
- require.Nil(t, iter.Envelope())
- },
- },
- {
- Name: "IteratorCanceledAfterFirstUseBecomesNil",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
-
- ins.In <- Envelope{From: "kip", To: "merlin"}
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
-
- require.True(t, iter.Next(ctx))
-
- res := iter.Envelope()
- require.EqualValues(t, "kip", res.From)
- require.EqualValues(t, "merlin", res.To)
-
- cctx, ccancel := context.WithCancel(ctx)
- ccancel()
-
- require.False(t, iter.Next(cctx))
- require.Nil(t, iter.Envelope())
- },
- },
- {
- Name: "IteratorMultipleNextCalls",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
-
- ins.In <- Envelope{From: "kip", To: "merlin"}
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
-
- require.True(t, iter.Next(ctx))
-
- res := iter.Envelope()
- require.EqualValues(t, "kip", res.From)
- require.EqualValues(t, "merlin", res.To)
-
- res1 := iter.Envelope()
- require.Equal(t, res, res1)
- },
- },
- {
- Name: "IteratorProducesNilObjectBeforeNext",
- Case: func(ctx context.Context, t *testing.T) {
- ins, ch := testChannel(1)
-
- iter := ch.Receive(ctx)
- require.NotNil(t, iter)
- require.Nil(t, iter.Envelope())
-
- ins.In <- Envelope{From: "kip", To: "merlin"}
- require.NotNil(t, iter)
- require.True(t, iter.Next(ctx))
-
- res := iter.Envelope()
- require.NotNil(t, res)
- require.EqualValues(t, "kip", res.From)
- require.EqualValues(t, "merlin", res.To)
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.Name, func(t *testing.T) {
- t.Cleanup(leaktest.Check(t))
-
- ctx, cancel := context.WithCancel(bctx)
- defer cancel()
-
- tc.Case(ctx, t)
- })
- }
- }
|