Files
go-kv/wal/validate_test.go
dailz fede839eb6 feat(wal): implement batch codec, validation, and Arena allocator
- wal/batch.go: WalBatch encode/decode with FragmentCollector state machine
- wal/validate.go: ValidateBatchLimits with checked arithmetic
- memtable/arena.go: Arena allocator with 8-byte alignment and mutex
- Comprehensive tests for all modules, all pass with -race
2026-06-12 13:27:17 +08:00

107 lines
2.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package wal
import (
"strings"
"testing"
"github.com/dailz/go-kv/config"
)
func makeEntry(opType uint8, valueKind uint8, keySize, valSize int) *WalEntry {
key := make([]byte, keySize)
for i := range key {
key[i] = byte('a' + i%26)
}
val := make([]byte, valSize)
for i := range val {
val[i] = byte('x')
}
return &WalEntry{OpType: opType, ValueKind: valueKind, Key: key, Value: val}
}
func TestValidateBatchLimitsPass(t *testing.T) {
cfg := config.Defaults()
entries := make([]*WalEntry, 100)
for i := range entries {
entries[i] = makeEntry(OpPut, VKInline, 10, 10)
}
if err := ValidateBatchLimits(entries, &cfg); err != nil {
t.Fatalf("expected nil error, got: %v", err)
}
}
func TestValidateEntryCountExceeded(t *testing.T) {
cfg := config.Defaults()
entries := make([]*WalEntry, 10001)
for i := range entries {
entries[i] = makeEntry(OpPut, VKInline, 10, 10)
}
err := ValidateBatchLimits(entries, &cfg)
if err == nil {
t.Fatal("expected error for entry count exceeded")
}
if !strings.Contains(err.Error(), "entry count") {
t.Fatalf("expected error containing 'entry count', got: %v", err)
}
}
func TestValidateKeyTooBig(t *testing.T) {
cfg := config.Defaults()
// 5KB key exceeds 4KB limit
entries := []*WalEntry{makeEntry(OpPut, VKInline, 5*1024, 10)}
err := ValidateBatchLimits(entries, &cfg)
if err == nil {
t.Fatal("expected error for key too big")
}
if !strings.Contains(err.Error(), "key") {
t.Fatalf("expected error containing 'key', got: %v", err)
}
}
func TestValidateValueTooBig(t *testing.T) {
cfg := config.Defaults()
// 5KB inline value exceeds 4KB limit
entries := []*WalEntry{makeEntry(OpPut, VKInline, 10, 5*1024)}
err := ValidateBatchLimits(entries, &cfg)
if err == nil {
t.Fatal("expected error for value too big")
}
if !strings.Contains(err.Error(), "value") {
t.Fatalf("expected error containing 'value', got: %v", err)
}
}
func TestValidateEmptyBatch(t *testing.T) {
cfg := config.Defaults()
err := ValidateBatchLimits(nil, &cfg)
if err == nil {
t.Fatal("expected error for empty batch")
}
if !strings.Contains(err.Error(), "entry count") && !strings.Contains(err.Error(), "> 0") {
t.Fatalf("expected error about empty batch, got: %v", err)
}
err = ValidateBatchLimits([]*WalEntry{}, &cfg)
if err == nil {
t.Fatal("expected error for empty batch")
}
}
func TestValidateTotalSizeExceeded(t *testing.T) {
cfg := config.Defaults()
// Create entries that collectively exceed MaxBatchSize (4MB).
// Each entry with 1000-byte key + 1000-byte value ≈ 2012 bytes encoded.
// 2100 entries × ~2012 ≈ ~4.2MB > 4MB
entries := make([]*WalEntry, 2100)
for i := range entries {
entries[i] = makeEntry(OpPut, VKInline, 1000, 1000)
}
err := ValidateBatchLimits(entries, &cfg)
if err == nil {
t.Fatal("expected error for total size exceeded")
}
if !strings.Contains(err.Error(), "batch size") {
t.Fatalf("expected error containing 'batch size', got: %v", err)
}
}