Files
bft/wal/record_test.go

100 lines
2.3 KiB
Go

// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package wal
import (
"bytes"
"encoding/binary"
"io"
"math"
"testing"
"github.com/stretchr/testify/require"
)
func TestWriteRecord(t *testing.T) {
require := require.New(t)
r := []byte{3, 4, 5}
var buff bytes.Buffer
require.NoError(writeRecord(&buff, r))
require.Equal(
[]byte{
0, 0, 0, 3, // Length of the payload
3, 4, 5, // Payload
0x8f, 0x9, 0x7f, 0xad, 0x19, 0xf9, 0xac, 0x8f, // CRC
},
buff.Bytes(),
)
}
func TestReadRecord(t *testing.T) {
require := require.New(t)
r := []byte{3, 4, 5}
var buff bytes.Buffer
require.NoError(writeRecord(&buff, r))
validBuff := bytes.NewBuffer(buff.Bytes())
readPayload, _, err := readRecord(validBuff, math.MaxUint32)
require.NoError(err)
require.Equal(r, readPayload)
buffBytes := buff.Bytes()
buffBytes[len(buffBytes)-1]++ // Corrupt the CRC of the buffer
invalidBuff := bytes.NewBuffer(buffBytes)
_, _, err = readRecord(invalidBuff, math.MaxUint32)
require.ErrorIs(err, ErrInvalidCRC)
}
func FuzzRecord(f *testing.F) {
f.Fuzz(func(t *testing.T, payload []byte, badCRCVal uint64) {
require := require.New(t)
var buff bytes.Buffer
require.NoError(writeRecord(&buff, payload))
validBuff := bytes.NewBuffer(buff.Bytes())
readPayload, n, err := readRecord(validBuff, math.MaxUint32)
require.NoError(err)
require.Equal(payload, readPayload)
require.Equal(recordSizeLen+len(payload)+recordChecksumLen, int(n))
recordBytes := buff.Bytes()
crc := recordBytes[len(recordBytes)-recordChecksumLen:]
badCRC := make([]byte, recordChecksumLen)
binary.BigEndian.PutUint64(badCRC, badCRCVal)
if bytes.Equal(crc, badCRC) {
return
}
// Corrupt the CRC of the buffer
copy(crc, badCRC)
invalidBuff := bytes.NewBuffer(buff.Bytes())
_, _, err = readRecord(invalidBuff, math.MaxUint32)
require.ErrorIs(err, ErrInvalidCRC)
})
}
func BenchmarkWriteRecord(b *testing.B) {
payload := []byte{3, 4, 5}
for range b.N {
_ = writeRecord(io.Discard, payload)
}
}
func BenchmarkReadRecord(b *testing.B) {
payload := []byte{3, 4, 5}
var originalBuffer bytes.Buffer
require.NoError(b, writeRecord(&originalBuffer, payload))
var loopBuffer bytes.Buffer
for range b.N {
loopBuffer = originalBuffer // reset the buffer
_, _, _ = readRecord(&loopBuffer, math.MaxUint32)
}
}