github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/format/internal/stream/seekable_reader_test.go (about) 1 package stream 2 3 import ( 4 "bytes" 5 "io" 6 "reflect" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestSeekableReader(t *testing.T) { 14 tests := []struct { 15 name string 16 input io.Reader 17 assert func(io.Reader, io.ReadSeeker) 18 wantErr require.ErrorAssertionFunc 19 }{ 20 { 21 name: "nil reader", 22 input: nil, 23 wantErr: require.Error, 24 }, 25 { 26 name: "empty reader", 27 input: bytes.NewBuffer([]byte{}), // does not implement io.Seeker (but does implement io.Reader) 28 assert: func(input io.Reader, got io.ReadSeeker) { 29 impl, ok := got.(*bytes.Reader) // implements bytes.Reader 30 require.True(t, ok) 31 _, err := impl.Seek(0, io.SeekStart) 32 require.NoError(t, err) 33 content, err := io.ReadAll(impl) 34 require.NoError(t, err) 35 require.Equal(t, []byte{}, content) 36 }, 37 }, 38 { 39 name: "empty read seeker", 40 input: bytes.NewReader([]byte{}), // implements io.ReadSeeker 41 assert: func(input io.Reader, got io.ReadSeeker) { 42 impl, ok := got.(*bytes.Reader) 43 require.True(t, ok) 44 _, err := impl.Seek(0, io.SeekStart) 45 require.NoError(t, err) 46 content, err := io.ReadAll(impl) 47 require.NoError(t, err) 48 require.Equal(t, []byte{}, content) 49 50 // assert this is the same read seeker (reflect tt.input pointer is the same as the impl pointer 51 inputImpl, ok := input.(*bytes.Reader) 52 require.True(t, ok) 53 assert.Equal(t, reflect.ValueOf(inputImpl).Pointer(), reflect.ValueOf(impl).Pointer()) 54 }, 55 }, 56 { 57 name: "non-empty read seeker", 58 input: bytes.NewReader([]byte("hello world!")), // implements io.ReadSeeker 59 assert: func(input io.Reader, got io.ReadSeeker) { 60 impl, ok := got.(*bytes.Reader) 61 require.True(t, ok) 62 _, err := impl.Seek(0, io.SeekStart) 63 require.NoError(t, err) 64 content, err := io.ReadAll(impl) 65 require.NoError(t, err) 66 require.Equal(t, []byte("hello world!"), content) 67 68 // assert this is the same read seeker (reflect tt.input pointer is the same as the impl pointer 69 inputImpl, ok := input.(*bytes.Reader) 70 require.True(t, ok) 71 assert.Equal(t, reflect.ValueOf(inputImpl).Pointer(), reflect.ValueOf(impl).Pointer()) 72 }, 73 }, 74 { 75 name: "non-empty reader", 76 input: bytes.NewBufferString("hello world!"), // does not implement io.Seeker (but does implement io.Reader) 77 assert: func(input io.Reader, got io.ReadSeeker) { 78 impl, ok := got.(*bytes.Reader) 79 require.True(t, ok) 80 _, err := impl.Seek(0, io.SeekStart) 81 require.NoError(t, err) 82 content, err := io.ReadAll(impl) 83 require.NoError(t, err) 84 require.Equal(t, []byte("hello world!"), content) 85 }, 86 }, 87 } 88 for _, tt := range tests { 89 t.Run(tt.name, func(t *testing.T) { 90 if tt.wantErr == nil { 91 tt.wantErr = require.NoError 92 } 93 got, err := SeekableReader(tt.input) 94 tt.wantErr(t, err) 95 if err != nil { 96 return 97 } 98 tt.assert(tt.input, got) 99 }) 100 } 101 }