github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/unicast/protocols/internal/compressedStream_test.go (about)

     1  package internal_test
     2  
     3  import (
     4  	"io"
     5  	"sync"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/onflow/flow-go/network/compressor"
    12  	p2ptest "github.com/onflow/flow-go/network/p2p/test"
    13  	"github.com/onflow/flow-go/network/p2p/unicast/protocols/internal"
    14  	"github.com/onflow/flow-go/utils/unittest"
    15  )
    16  
    17  // TestHappyPath evaluates reading from a compressed stream retrieves what originally has been written on it.
    18  func TestHappyPath(t *testing.T) {
    19  	text := "hello world, hello world!"
    20  	textByte := []byte(text)
    21  	textByteLen := len(textByte)
    22  
    23  	// creates a pair of compressed streams
    24  	mca, _, mcb, _ := newCompressedStreamPair(t)
    25  
    26  	// writes on stream mca
    27  	writeWG := sync.WaitGroup{}
    28  	writeWG.Add(1)
    29  	go func() {
    30  		defer writeWG.Done()
    31  
    32  		n, err := mca.Write(textByte)
    33  		require.NoError(t, err)
    34  
    35  		require.Equal(t, n, len(text))
    36  	}()
    37  
    38  	// write on stream mca should be read on steam mcb
    39  	readWG := sync.WaitGroup{}
    40  	readWG.Add(1)
    41  	go func() {
    42  		defer readWG.Done()
    43  
    44  		b := make([]byte, textByteLen)
    45  		n, err := mcb.Read(b)
    46  		require.NoError(t, err)
    47  
    48  		require.Equal(t, n, textByteLen)
    49  		require.Equal(t, b, textByte)
    50  	}()
    51  
    52  	unittest.RequireReturnsBefore(t, writeWG.Wait, 1*time.Second, "timeout for writing on stream")
    53  	unittest.RequireReturnsBefore(t, readWG.Wait, 1*time.Second, "timeout for reading from stream")
    54  }
    55  
    56  // TestUnhappyPath evaluates that sending uncompressed data to the compressed end of a stream results
    57  // in an error at the reader side.
    58  func TestUnhappyPath(t *testing.T) {
    59  	text := "hello world, hello world!"
    60  	textByte := []byte(text)
    61  	textByteLen := len(textByte)
    62  
    63  	// sa is the underlying stream of sender (non-compressed)
    64  	// mcb is the compressed stream of receiver
    65  	_, sa, mcb, _ := newCompressedStreamPair(t)
    66  
    67  	// writes on sa (uncompressed)
    68  	writeWG := sync.WaitGroup{}
    69  	writeWG.Add(1)
    70  	go func() {
    71  		defer writeWG.Done()
    72  
    73  		// writes data uncompressed
    74  		n, err := sa.Write(textByte)
    75  		require.NoError(t, err)
    76  
    77  		require.Equal(t, n, len(text))
    78  	}()
    79  
    80  	// write on uncompressed stream sa should NOT be read on compressed steam mcb
    81  	readWG := sync.WaitGroup{}
    82  	readWG.Add(1)
    83  	go func() {
    84  		defer readWG.Done()
    85  
    86  		b := make([]byte, textByteLen)
    87  		n, err := mcb.Read(b)
    88  		// since a compressed stream is reading an uncompressed data,
    89  		// it should return an error.
    90  		require.Error(t, err)
    91  		// number of bytes read should be zero, and nothing should be written to
    92  		// b on reader side.
    93  		require.Equal(t, n, 0)
    94  		require.Equal(t, b, make([]byte, textByteLen))
    95  	}()
    96  
    97  	unittest.RequireReturnsBefore(t, writeWG.Wait, 1*time.Second, "timeout for writing on stream")
    98  	unittest.RequireReturnsBefore(t, readWG.Wait, 1*time.Second, "timeout for reading from stream")
    99  }
   100  
   101  // newStreamPair is a test helper that creates a pair of compressed streams a and b such that
   102  // a reads what b writes and b reads what a writes.
   103  func newStreamPair() (*p2ptest.MockStream, *p2ptest.MockStream) {
   104  	ra, wb := io.Pipe()
   105  	rb, wa := io.Pipe()
   106  
   107  	sa := p2ptest.NewMockStream(wa, ra)
   108  	sb := p2ptest.NewMockStream(wb, rb)
   109  
   110  	return sa, sb
   111  }
   112  
   113  // newCompressedStreamPair is a test helper that creates a pair of compressed streams a and b such that
   114  // a reads what b writes and b reads what a writes.
   115  func newCompressedStreamPair(t *testing.T) (*internal.CompressedStream, *p2ptest.MockStream, *internal.CompressedStream, *p2ptest.MockStream) {
   116  	sa, sb := newStreamPair()
   117  
   118  	mca, err := internal.NewCompressedStream(sa, compressor.GzipStreamCompressor{})
   119  	require.NoError(t, err)
   120  
   121  	mcb, err := internal.NewCompressedStream(sb, compressor.GzipStreamCompressor{})
   122  	require.NoError(t, err)
   123  
   124  	return mca, sa, mcb, sb
   125  }