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 }