package codec import ( "bytes" "encoding/binary" "io" "testing" "github.com/prologic/bitcask/internal" "github.com/stretchr/testify/assert" ) func TestDecodeOnNilEntry(t *testing.T) { t.Parallel() assert := assert.New(t) decoder := NewDecoder(&bytes.Buffer{}, 1, 1) _, err := decoder.Decode(nil) if assert.Error(err) { assert.Equal(errCantDecodeOnNilEntry, err) } } func TestShortPrefix(t *testing.T) { t.Parallel() assert := assert.New(t) maxKeySize, maxValueSize := uint32(10), uint64(20) prefix := make([]byte, keySize+valueSize) binary.BigEndian.PutUint32(prefix, 1) binary.BigEndian.PutUint64(prefix[keySize:], 1) truncBytesCount := 2 buf := bytes.NewBuffer(prefix[:keySize+valueSize-truncBytesCount]) decoder := NewDecoder(buf, maxKeySize, maxValueSize) _, err := decoder.Decode(&internal.Entry{}) if assert.Error(err) { assert.Equal(io.ErrUnexpectedEOF, err) } } func TestInvalidValueKeySizes(t *testing.T) { assert := assert.New(t) maxKeySize, maxValueSize := uint32(10), uint64(20) tests := []struct { keySize uint32 valueSize uint64 name string }{ {keySize: 0, valueSize: 5, name: "zero key size"}, //zero value size is correct for tombstones {keySize: 11, valueSize: 5, name: "key size overflow"}, {keySize: 5, valueSize: 21, name: "value size overflow"}, {keySize: 11, valueSize: 21, name: "key and value size overflow"}, } for i := range tests { i := i t.Run(tests[i].name, func(t *testing.T) { t.Parallel() prefix := make([]byte, keySize+valueSize) binary.BigEndian.PutUint32(prefix, tests[i].keySize) binary.BigEndian.PutUint64(prefix[keySize:], tests[i].valueSize) buf := bytes.NewBuffer(prefix) decoder := NewDecoder(buf, maxKeySize, maxValueSize) _, err := decoder.Decode(&internal.Entry{}) if assert.Error(err) { assert.Equal(errInvalidKeyOrValueSize, err) } }) } } func TestTruncatedData(t *testing.T) { assert := assert.New(t) maxKeySize, maxValueSize := uint32(10), uint64(20) key := []byte("foo") value := []byte("bar") data := make([]byte, keySize+valueSize+len(key)+len(value)+checksumSize) binary.BigEndian.PutUint32(data, uint32(len(key))) binary.BigEndian.PutUint64(data[keySize:], uint64(len(value))) copy(data[keySize+valueSize:], key) copy(data[keySize+valueSize+len(key):], value) copy(data[keySize+valueSize+len(key)+len(value):], bytes.Repeat([]byte("0"), checksumSize)) tests := []struct { data []byte name string }{ {data: data[:keySize+valueSize+len(key)-1], name: "truncated key"}, {data: data[:keySize+valueSize+len(key)+len(value)-1], name: "truncated value"}, {data: data[:keySize+valueSize+len(key)+len(value)+checksumSize-1], name: "truncated checksum"}, } for i := range tests { i := i t.Run(tests[i].name, func(t *testing.T) { t.Parallel() buf := bytes.NewBuffer(tests[i].data) decoder := NewDecoder(buf, maxKeySize, maxValueSize) _, err := decoder.Decode(&internal.Entry{}) if assert.Error(err) { assert.Equal(errTruncatedData, err) } }) } }