* add check negative position to Read() and write tests * add tests for Write() method * add tests for Write() method * add checks of whence and negative position to Seek() and write tests * add tests for Rewind() * add tests for Close() * add tests for Reset() * add tests for Len() * add tests for Bytes() * tests polishing * tests polishing * tests polishing * tests polishing
		
			
				
	
	
		
			386 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package buffer
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func TestNewSeekerBuffer(t *testing.T) {
 | |
| 	input := []byte{'a', 'b', 'c', 'd', 'e'}
 | |
| 	expected := &SeekerBuffer{data: []byte{'a', 'b', 'c', 'd', 'e'}, pos: 0}
 | |
| 	require.Equal(t, expected, NewSeekerBuffer(input))
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Read(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name         string
 | |
| 		data         []byte
 | |
| 		initPos      int64
 | |
| 		readBuf      []byte
 | |
| 		expectedN    int
 | |
| 		expectedData []byte
 | |
| 		expectedErr  error
 | |
| 		expectedPos  int64
 | |
| 	}{
 | |
| 		{
 | |
| 			name:         "read with empty buffer",
 | |
| 			data:         []byte("hello"),
 | |
| 			initPos:      0,
 | |
| 			readBuf:      []byte{},
 | |
| 			expectedN:    0,
 | |
| 			expectedData: []byte{},
 | |
| 			expectedErr:  nil,
 | |
| 			expectedPos:  0,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "read with nil buffer",
 | |
| 			data:         []byte("hello"),
 | |
| 			initPos:      0,
 | |
| 			readBuf:      nil,
 | |
| 			expectedN:    0,
 | |
| 			expectedData: nil,
 | |
| 			expectedErr:  nil,
 | |
| 			expectedPos:  0,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "read full buffer",
 | |
| 			data:         []byte("hello"),
 | |
| 			initPos:      0,
 | |
| 			readBuf:      make([]byte, 5),
 | |
| 			expectedN:    5,
 | |
| 			expectedData: []byte("hello"),
 | |
| 			expectedErr:  nil,
 | |
| 			expectedPos:  5,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "read partial buffer",
 | |
| 			data:         []byte("hello"),
 | |
| 			initPos:      2,
 | |
| 			readBuf:      make([]byte, 2),
 | |
| 			expectedN:    2,
 | |
| 			expectedData: []byte("ll"),
 | |
| 			expectedErr:  nil,
 | |
| 			expectedPos:  4,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "read after end",
 | |
| 			data:         []byte("hello"),
 | |
| 			initPos:      5,
 | |
| 			readBuf:      make([]byte, 5),
 | |
| 			expectedN:    0,
 | |
| 			expectedData: make([]byte, 5),
 | |
| 			expectedErr:  io.EOF,
 | |
| 			expectedPos:  5,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			sb := NewSeekerBuffer(tt.data)
 | |
| 			sb.pos = tt.initPos
 | |
| 
 | |
| 			n, err := sb.Read(tt.readBuf)
 | |
| 
 | |
| 			if tt.expectedErr != nil {
 | |
| 				require.Equal(t, err, tt.expectedErr)
 | |
| 			} else {
 | |
| 				require.NoError(t, err)
 | |
| 			}
 | |
| 
 | |
| 			require.Equal(t, tt.expectedN, n)
 | |
| 			require.Equal(t, tt.expectedData, tt.readBuf)
 | |
| 			require.Equal(t, tt.expectedPos, sb.pos)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Write(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name         string
 | |
| 		initialData  []byte
 | |
| 		initialPos   int64
 | |
| 		writeData    []byte
 | |
| 		expectedData []byte
 | |
| 		expectedN    int
 | |
| 	}{
 | |
| 		{
 | |
| 			name:         "write empty slice",
 | |
| 			initialData:  []byte("data"),
 | |
| 			initialPos:   0,
 | |
| 			writeData:    []byte{},
 | |
| 			expectedData: []byte("data"),
 | |
| 			expectedN:    0,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "write nil slice",
 | |
| 			initialData:  []byte("data"),
 | |
| 			initialPos:   0,
 | |
| 			writeData:    nil,
 | |
| 			expectedData: []byte("data"),
 | |
| 			expectedN:    0,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "write to empty buffer",
 | |
| 			initialData:  nil,
 | |
| 			initialPos:   0,
 | |
| 			writeData:    []byte("abc"),
 | |
| 			expectedData: []byte("abc"),
 | |
| 			expectedN:    3,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "write to existing buffer",
 | |
| 			initialData:  []byte("hello"),
 | |
| 			initialPos:   0,
 | |
| 			writeData:    []byte(" world"),
 | |
| 			expectedData: []byte("hello world"),
 | |
| 			expectedN:    6,
 | |
| 		},
 | |
| 		{
 | |
| 			name:         "write after read",
 | |
| 			initialData:  []byte("abc"),
 | |
| 			initialPos:   2,
 | |
| 			writeData:    []byte("XYZ"),
 | |
| 			expectedData: []byte("abcXYZ"),
 | |
| 			expectedN:    3,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			sb := NewSeekerBuffer(tt.initialData)
 | |
| 			sb.pos = tt.initialPos
 | |
| 
 | |
| 			n, err := sb.Write(tt.writeData)
 | |
| 			require.NoError(t, err)
 | |
| 			require.Equal(t, tt.expectedN, n)
 | |
| 			require.Equal(t, tt.expectedData, sb.data)
 | |
| 			require.Equal(t, tt.initialPos, sb.pos)
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Seek(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name        string
 | |
| 		initialData []byte
 | |
| 		initialPos  int64
 | |
| 		offset      int64
 | |
| 		whence      int
 | |
| 		expectedPos int64
 | |
| 		expectedErr error
 | |
| 	}{
 | |
| 		{
 | |
| 			name:        "seek with invalid whence",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      1,
 | |
| 			whence:      12345,
 | |
| 			expectedPos: 0,
 | |
| 			expectedErr: fmt.Errorf("invalid whence: %d", 12345),
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek negative from start",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      -1,
 | |
| 			whence:      io.SeekStart,
 | |
| 			expectedPos: 0,
 | |
| 			expectedErr: fmt.Errorf("invalid seek: resulting position %d is negative", -1),
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek from start to 0",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      0,
 | |
| 			whence:      io.SeekStart,
 | |
| 			expectedPos: 0,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek from start to 3",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      3,
 | |
| 			whence:      io.SeekStart,
 | |
| 			expectedPos: 3,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek from end to -1 (last byte)",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      -1,
 | |
| 			whence:      io.SeekEnd,
 | |
| 			expectedPos: 5,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek from current forward",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  2,
 | |
| 			offset:      2,
 | |
| 			whence:      io.SeekCurrent,
 | |
| 			expectedPos: 4,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek from current backward",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  4,
 | |
| 			offset:      -2,
 | |
| 			whence:      io.SeekCurrent,
 | |
| 			expectedPos: 2,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek to end exactly",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      0,
 | |
| 			whence:      io.SeekEnd,
 | |
| 			expectedPos: 6,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 		{
 | |
| 			name:        "seek to out of range",
 | |
| 			initialData: []byte("abcdef"),
 | |
| 			initialPos:  0,
 | |
| 			offset:      2,
 | |
| 			whence:      io.SeekEnd,
 | |
| 			expectedPos: 8,
 | |
| 			expectedErr: nil,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			sb := NewSeekerBuffer(tt.initialData)
 | |
| 			sb.pos = tt.initialPos
 | |
| 
 | |
| 			newPos, err := sb.Seek(tt.offset, tt.whence)
 | |
| 
 | |
| 			if tt.expectedErr != nil {
 | |
| 				require.Equal(t, tt.expectedErr, err)
 | |
| 			} else {
 | |
| 				require.NoError(t, err)
 | |
| 				require.Equal(t, tt.expectedPos, newPos)
 | |
| 				require.Equal(t, tt.expectedPos, sb.pos)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Rewind(t *testing.T) {
 | |
| 	buf := NewSeekerBuffer([]byte("hello world"))
 | |
| 	buf.pos = 4
 | |
| 
 | |
| 	require.NoError(t, buf.Rewind())
 | |
| 	require.Equal(t, []byte("hello world"), buf.data)
 | |
| 	require.Equal(t, int64(0), buf.pos)
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Close(t *testing.T) {
 | |
| 	buf := NewSeekerBuffer([]byte("hello world"))
 | |
| 	buf.pos = 2
 | |
| 
 | |
| 	require.NoError(t, buf.Close())
 | |
| 	require.Nil(t, buf.data)
 | |
| 	require.Equal(t, int64(0), buf.pos)
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Reset(t *testing.T) {
 | |
| 	buf := NewSeekerBuffer([]byte("hello world"))
 | |
| 	buf.pos = 2
 | |
| 
 | |
| 	buf.Reset()
 | |
| 	require.Nil(t, buf.data)
 | |
| 	require.Equal(t, int64(0), buf.pos)
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Len(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name     string
 | |
| 		data     []byte
 | |
| 		pos      int64
 | |
| 		expected int
 | |
| 	}{
 | |
| 		{
 | |
| 			name:     "full buffer",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      0,
 | |
| 			expected: 5,
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "partial read",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      2,
 | |
| 			expected: 3,
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "fully read",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      5,
 | |
| 			expected: 0,
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "pos > len",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      10,
 | |
| 			expected: 0,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			buf := NewSeekerBuffer(tt.data)
 | |
| 			buf.pos = tt.pos
 | |
| 			require.Equal(t, tt.expected, buf.Len())
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSeekerBuffer_Bytes(t *testing.T) {
 | |
| 	tests := []struct {
 | |
| 		name     string
 | |
| 		data     []byte
 | |
| 		pos      int64
 | |
| 		expected []byte
 | |
| 	}{
 | |
| 		{
 | |
| 			name:     "start of buffer",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      0,
 | |
| 			expected: []byte("abcde"),
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "middle of buffer",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      2,
 | |
| 			expected: []byte("cde"),
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "end of buffer",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      5,
 | |
| 			expected: []byte{},
 | |
| 		},
 | |
| 		{
 | |
| 			name:     "pos beyond end",
 | |
| 			data:     []byte("abcde"),
 | |
| 			pos:      10,
 | |
| 			expected: []byte{},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		t.Run(tt.name, func(t *testing.T) {
 | |
| 			buf := NewSeekerBuffer(tt.data)
 | |
| 			buf.pos = tt.pos
 | |
| 			require.Equal(t, tt.expected, buf.Bytes())
 | |
| 		})
 | |
| 	}
 | |
| }
 |