skyview/internal/database/optimization_test.go
Ole-Morten Duesund 2bffa2c418 style: Apply code formatting with go fmt
- Run 'make format' to ensure all Go code follows standard formatting
- Maintains consistent code style across the entire codebase
- No functional changes, only whitespace and formatting improvements
2025-09-01 10:05:29 +02:00

307 lines
8.1 KiB
Go

package database
import (
"os"
"testing"
"time"
)
func TestOptimizationManager_VacuumDatabase(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
err := optimizer.VacuumDatabase()
if err != nil {
t.Fatal("VacuumDatabase failed:", err)
}
// Verify vacuum was successful by checking database integrity
conn := db.GetConnection()
var result string
err = conn.QueryRow("PRAGMA integrity_check").Scan(&result)
if err != nil {
t.Error("Failed to run integrity check:", err)
}
if result != "ok" {
t.Errorf("Database integrity check failed: %s", result)
}
}
func TestOptimizationManager_OptimizeDatabase(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
err := optimizer.OptimizeDatabase()
if err != nil {
t.Fatal("OptimizeDatabase failed:", err)
}
// Check that auto_vacuum was set
conn := db.GetConnection()
var autoVacuum int
err = conn.QueryRow("PRAGMA auto_vacuum").Scan(&autoVacuum)
if err != nil {
t.Error("Failed to check auto_vacuum setting:", err)
}
// Should be 2 (INCREMENTAL) after optimization
if autoVacuum != 2 {
t.Errorf("Expected auto_vacuum = 2 (INCREMENTAL), got %d", autoVacuum)
}
}
func TestOptimizationManager_OptimizePageSize(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
// Get current page size
conn := db.GetConnection()
var currentPageSize int
err := conn.QueryRow("PRAGMA page_size").Scan(&currentPageSize)
if err != nil {
t.Fatal("Failed to get current page size:", err)
}
// Set a different page size
targetPageSize := 8192
if currentPageSize == targetPageSize {
targetPageSize = 4096 // Use different size if already at target
}
err = optimizer.OptimizePageSize(targetPageSize)
if err != nil {
t.Fatal("OptimizePageSize failed:", err)
}
// Verify page size was changed
var newPageSize int
err = conn.QueryRow("PRAGMA page_size").Scan(&newPageSize)
if err != nil {
t.Error("Failed to get new page size:", err)
}
if newPageSize != targetPageSize {
t.Errorf("Expected page size %d, got %d", targetPageSize, newPageSize)
}
// Test setting same page size (should be no-op)
err = optimizer.OptimizePageSize(targetPageSize)
if err != nil {
t.Error("OptimizePageSize failed for same page size:", err)
}
}
func TestOptimizationManager_GetOptimizationStats(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
// Insert some test data to make stats more meaningful
conn := db.GetConnection()
_, err := conn.Exec(`
INSERT INTO airlines (id, name, alias, iata_code, icao_code, callsign, country, active, data_source)
VALUES (1, 'Test Airways', 'Test', 'TA', 'TST', 'TESTAIR', 'United States', 1, 'test')
`)
if err != nil {
t.Error("Failed to insert test data:", err)
}
stats, err := optimizer.GetOptimizationStats()
if err != nil {
t.Fatal("GetOptimizationStats failed:", err)
}
if stats == nil {
t.Fatal("Expected stats, got nil")
}
// Check basic stats
if stats.DatabaseSize <= 0 {
t.Error("Database size should be greater than 0")
}
if stats.PageSize <= 0 {
t.Error("Page size should be greater than 0")
}
if stats.PageCount <= 0 {
t.Error("Page count should be greater than 0")
}
if stats.UsedPages < 0 {
t.Error("Used pages should be non-negative")
}
if stats.FreePages < 0 {
t.Error("Free pages should be non-negative")
}
if stats.Efficiency < 0 || stats.Efficiency > 100 {
t.Errorf("Efficiency should be between 0-100%%, got %.2f%%", stats.Efficiency)
}
t.Logf("Database stats: Size=%d bytes, Pages=%d (used=%d, free=%d), Efficiency=%.1f%%",
stats.DatabaseSize, stats.PageCount, stats.UsedPages, stats.FreePages, stats.Efficiency)
}
func TestOptimizationManager_PerformMaintenance(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{
Path: db.config.Path,
VacuumInterval: time.Millisecond, // Very short interval for testing
}
optimizer := NewOptimizationManager(db, config)
// Should perform vacuum due to short interval
err := optimizer.PerformMaintenance()
if err != nil {
t.Fatal("PerformMaintenance failed:", err)
}
// Check that lastVacuum was updated
if optimizer.lastVacuum.IsZero() {
t.Error("lastVacuum should be set after maintenance")
}
// Wait a bit and run again with longer interval
config.VacuumInterval = time.Hour // Long interval
err = optimizer.PerformMaintenance()
if err != nil {
t.Fatal("Second PerformMaintenance failed:", err)
}
}
func TestOptimizationManager_getDatabaseSize(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
size, err := optimizer.getDatabaseSize()
if err != nil {
t.Fatal("getDatabaseSize failed:", err)
}
if size <= 0 {
t.Error("Database size should be greater than 0")
}
// Verify size matches actual file size
stat, err := os.Stat(db.config.Path)
if err != nil {
t.Fatal("Failed to stat database file:", err)
}
if size != stat.Size() {
t.Errorf("getDatabaseSize returned %d, but file size is %d", size, stat.Size())
}
}
func TestOptimizationManager_InvalidPath(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
// Test with invalid path
config := &Config{Path: "/nonexistent/path/database.db"}
optimizer := NewOptimizationManager(db, config)
_, err := optimizer.getDatabaseSize()
if err == nil {
t.Error("getDatabaseSize should fail with invalid path")
}
}
func TestOptimizationStats_JSON(t *testing.T) {
stats := &OptimizationStats{
DatabaseSize: 1024000,
PageSize: 4096,
PageCount: 250,
UsedPages: 200,
FreePages: 50,
Efficiency: 80.0,
AutoVacuumEnabled: true,
LastVacuum: time.Now(),
}
// Test that all fields are accessible
if stats.DatabaseSize != 1024000 {
t.Error("DatabaseSize not preserved")
}
if stats.PageSize != 4096 {
t.Error("PageSize not preserved")
}
if stats.Efficiency != 80.0 {
t.Error("Efficiency not preserved")
}
if !stats.AutoVacuumEnabled {
t.Error("AutoVacuumEnabled not preserved")
}
}
func TestOptimizationManager_WithRealData(t *testing.T) {
db, cleanup := setupTestDatabase(t)
defer cleanup()
// Load some real data to make optimization more realistic
// Skip actual data loading in tests as it requires network access
// Just insert minimal test data
conn := db.GetConnection()
_, err := conn.Exec(`INSERT INTO airlines (id, name, alias, iata_code, icao_code, callsign, country, active, data_source)
VALUES (1, 'Test Airways', 'Test', 'TA', 'TST', 'TESTAIR', 'United States', 1, 'test')`)
if err != nil {
t.Fatal("Failed to insert test data:", err)
}
config := &Config{Path: db.config.Path}
optimizer := NewOptimizationManager(db, config)
// Get stats before optimization
statsBefore, err := optimizer.GetOptimizationStats()
if err != nil {
t.Fatal("Failed to get stats before optimization:", err)
}
// Run optimization
err = optimizer.OptimizeDatabase()
if err != nil {
t.Fatal("OptimizeDatabase failed:", err)
}
err = optimizer.VacuumDatabase()
if err != nil {
t.Fatal("VacuumDatabase failed:", err)
}
// Get stats after optimization
statsAfter, err := optimizer.GetOptimizationStats()
if err != nil {
t.Fatal("Failed to get stats after optimization:", err)
}
// Compare efficiency
t.Logf("Optimization results: %.2f%% → %.2f%% efficiency",
statsBefore.Efficiency, statsAfter.Efficiency)
// After optimization, we should have auto-vacuum enabled
if !statsAfter.AutoVacuumEnabled {
t.Error("Auto-vacuum should be enabled after optimization")
}
// Database should still be functional
conn = db.GetConnection()
var count int
err = conn.QueryRow("SELECT COUNT(*) FROM airlines").Scan(&count)
if err != nil {
t.Error("Database not functional after optimization:", err)
}
if count == 0 {
t.Error("Data lost during optimization")
}
}