kevo/pkg/config/config_test.go
Jeremy Tregunna 6fc3be617d
Some checks failed
Go Tests / Run Tests (1.24.2) (push) Has been cancelled
feat: Initial release of kevo storage engine.
Adds a complete LSM-based storage engine with these features:
- Single-writer based architecture for the storage engine
- WAL for durability, and hey it's configurable
- MemTable with skip list implementation for fast read/writes
- SSTable with block-based structure for on-disk level-based storage
- Background compaction with tiered strategy
- ACID transactions
- Good documentation (I hope)
2025-04-20 14:06:50 -06:00

168 lines
4.0 KiB
Go

package config
import (
"os"
"path/filepath"
"testing"
)
func TestNewDefaultConfig(t *testing.T) {
dbPath := "/tmp/testdb"
cfg := NewDefaultConfig(dbPath)
if cfg.Version != CurrentManifestVersion {
t.Errorf("expected version %d, got %d", CurrentManifestVersion, cfg.Version)
}
if cfg.WALDir != filepath.Join(dbPath, "wal") {
t.Errorf("expected WAL dir %s, got %s", filepath.Join(dbPath, "wal"), cfg.WALDir)
}
if cfg.SSTDir != filepath.Join(dbPath, "sst") {
t.Errorf("expected SST dir %s, got %s", filepath.Join(dbPath, "sst"), cfg.SSTDir)
}
// Test default values
if cfg.WALSyncMode != SyncBatch {
t.Errorf("expected WAL sync mode %d, got %d", SyncBatch, cfg.WALSyncMode)
}
if cfg.MemTableSize != 32*1024*1024 {
t.Errorf("expected memtable size %d, got %d", 32*1024*1024, cfg.MemTableSize)
}
}
func TestConfigValidate(t *testing.T) {
cfg := NewDefaultConfig("/tmp/testdb")
// Valid config
if err := cfg.Validate(); err != nil {
t.Errorf("expected valid config, got error: %v", err)
}
// Test invalid configs
testCases := []struct {
name string
mutate func(*Config)
expected string
}{
{
name: "invalid version",
mutate: func(c *Config) {
c.Version = 0
},
expected: "invalid configuration: invalid version 0",
},
{
name: "empty WAL dir",
mutate: func(c *Config) {
c.WALDir = ""
},
expected: "invalid configuration: WAL directory not specified",
},
{
name: "empty SST dir",
mutate: func(c *Config) {
c.SSTDir = ""
},
expected: "invalid configuration: SSTable directory not specified",
},
{
name: "zero memtable size",
mutate: func(c *Config) {
c.MemTableSize = 0
},
expected: "invalid configuration: MemTable size must be positive",
},
{
name: "negative max memtables",
mutate: func(c *Config) {
c.MaxMemTables = -1
},
expected: "invalid configuration: Max MemTables must be positive",
},
{
name: "zero block size",
mutate: func(c *Config) {
c.SSTableBlockSize = 0
},
expected: "invalid configuration: SSTable block size must be positive",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
cfg := NewDefaultConfig("/tmp/testdb")
tc.mutate(cfg)
err := cfg.Validate()
if err == nil {
t.Fatal("expected error, got nil")
}
if err.Error() != tc.expected {
t.Errorf("expected error %q, got %q", tc.expected, err.Error())
}
})
}
}
func TestConfigManifestSaveLoad(t *testing.T) {
// Create a temporary directory for the test
tempDir, err := os.MkdirTemp("", "config_test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
// Create a config and save it
cfg := NewDefaultConfig(tempDir)
cfg.MemTableSize = 16 * 1024 * 1024 // 16MB
cfg.CompactionThreads = 4
if err := cfg.SaveManifest(tempDir); err != nil {
t.Fatalf("failed to save manifest: %v", err)
}
// Load the config
loadedCfg, err := LoadConfigFromManifest(tempDir)
if err != nil {
t.Fatalf("failed to load manifest: %v", err)
}
// Verify loaded config
if loadedCfg.MemTableSize != cfg.MemTableSize {
t.Errorf("expected memtable size %d, got %d", cfg.MemTableSize, loadedCfg.MemTableSize)
}
if loadedCfg.CompactionThreads != cfg.CompactionThreads {
t.Errorf("expected compaction threads %d, got %d", cfg.CompactionThreads, loadedCfg.CompactionThreads)
}
// Test loading non-existent manifest
nonExistentDir := filepath.Join(tempDir, "nonexistent")
_, err = LoadConfigFromManifest(nonExistentDir)
if err != ErrManifestNotFound {
t.Errorf("expected ErrManifestNotFound, got %v", err)
}
}
func TestConfigUpdate(t *testing.T) {
cfg := NewDefaultConfig("/tmp/testdb")
// Update config
cfg.Update(func(c *Config) {
c.MemTableSize = 64 * 1024 * 1024 // 64MB
c.MaxMemTables = 8
})
// Verify update
if cfg.MemTableSize != 64*1024*1024 {
t.Errorf("expected memtable size %d, got %d", 64*1024*1024, cfg.MemTableSize)
}
if cfg.MaxMemTables != 8 {
t.Errorf("expected max memtables %d, got %d", 8, cfg.MaxMemTables)
}
}