github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/morebufio/peekback_test.go (about) 1 package morebufio 2 3 import ( 4 "context" 5 "io" 6 "strings" 7 "testing" 8 9 "github.com/Schaudge/grailbase/ioctx" 10 "github.com/stretchr/testify/require" 11 ) 12 13 const digits = "0123456789" 14 15 func TestPeekBack(t *testing.T) { 16 ctx := context.Background() 17 r := NewPeekBackReader(ioctx.FromStdReader(strings.NewReader(digits)), 4) 18 19 // Initial read, smaller than peek buf. 20 b := make([]byte, 2) 21 n, err := r.Read(ctx, b) 22 require.NoError(t, err) 23 require.Equal(t, len(b), n) 24 require.Equal(t, "01", string(b)) 25 require.Equal(t, "01", string(r.PeekBack())) 26 27 // Read enough to shift buf. 28 b = make([]byte, 3) 29 n, err = r.Read(ctx, b) 30 require.NoError(t, err) 31 require.Equal(t, len(b), n) 32 require.Equal(t, "234", string(b)) 33 require.Equal(t, "1234", string(r.PeekBack())) 34 35 // Read nothing. 36 b = nil 37 n, err = r.Read(ctx, b) 38 require.NoError(t, err) 39 require.Equal(t, len(b), n) 40 require.Equal(t, "1234", string(r.PeekBack())) 41 42 // Read past EOF. 43 b = make([]byte, 8) 44 n, err = r.Read(ctx, b) 45 if err != io.EOF { 46 require.NoError(t, err) 47 } 48 require.Equal(t, 5, n) 49 require.Equal(t, "56789", string(b[:n])) 50 require.Equal(t, "6789", string(r.PeekBack())) 51 52 n, err = r.Read(ctx, b) 53 require.ErrorIs(t, err, io.EOF) 54 require.Equal(t, 0, n) 55 require.Equal(t, "6789", string(r.PeekBack())) 56 } 57 58 func TestPeekBackLargeInitial(t *testing.T) { 59 ctx := context.Background() 60 r := NewPeekBackReader(ioctx.FromStdReader(strings.NewReader(digits)), 3) 61 62 // Initial read, larger than peek buf. 63 b := make([]byte, 6) 64 n, err := r.Read(ctx, b) 65 require.NoError(t, err) 66 require.Equal(t, len(b), n) 67 require.Equal(t, "012345", string(b)) 68 require.Equal(t, "345", string(r.PeekBack())) 69 70 // Shift. 71 b = make([]byte, 1) 72 n, err = r.Read(ctx, b) 73 require.NoError(t, err) 74 require.Equal(t, len(b), n) 75 require.Equal(t, "6", string(b)) 76 require.Equal(t, "456", string(r.PeekBack())) 77 } 78 79 func TestPeekBackNeverFull(t *testing.T) { 80 ctx := context.Background() 81 r := NewPeekBackReader(ioctx.FromStdReader(strings.NewReader(digits)), 20) 82 83 b := make([]byte, 6) 84 n, err := r.Read(ctx, b) 85 require.NoError(t, err) 86 require.Equal(t, len(b), n) 87 require.Equal(t, "012345", string(b)) 88 require.Equal(t, "012345", string(r.PeekBack())) 89 90 b = make([]byte, 20) 91 n, err = r.Read(ctx, b) 92 if err != io.EOF { 93 require.NoError(t, err) 94 } 95 require.Equal(t, 4, n) 96 require.Equal(t, "6789", string(b[:n])) 97 require.Equal(t, "0123456789", string(r.PeekBack())) 98 99 n, err = r.Read(ctx, b) 100 require.ErrorIs(t, err, io.EOF) 101 require.Equal(t, 0, n) 102 require.Equal(t, "0123456789", string(r.PeekBack())) 103 } 104 105 func TestPeekBackZero(t *testing.T) { 106 ctx := context.Background() 107 r := NewPeekBackReader(ioctx.FromStdReader(strings.NewReader(digits)), 0) 108 109 b := make([]byte, 6) 110 n, err := r.Read(ctx, b) 111 require.NoError(t, err) 112 require.Equal(t, len(b), n) 113 require.Equal(t, "012345", string(b)) 114 require.Equal(t, "", string(r.PeekBack())) 115 116 b = make([]byte, 20) 117 n, err = r.Read(ctx, b) 118 if err != io.EOF { 119 require.NoError(t, err) 120 } 121 require.Equal(t, 4, n) 122 require.Equal(t, "6789", string(b[:n])) 123 require.Equal(t, "", string(r.PeekBack())) 124 125 n, err = r.Read(ctx, b) 126 require.ErrorIs(t, err, io.EOF) 127 require.Equal(t, 0, n) 128 require.Equal(t, "", string(r.PeekBack())) 129 } 130 131 // TODO: Randomized/fuzz tests.