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.