* 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())
|
|
})
|
|
}
|
|
}
|