zsvo/test/test_singleton_fix.go
2026-03-15 17:24:01 +03:00

121 lines
3.5 KiB
Go

package main
import (
"fmt"
"os"
"time"
"zsvo/pkg/resolver"
)
func main() {
fmt.Println("🧪 Testing Singleton Resolver Fix")
fmt.Println("=================================")
cacheDir := "/tmp/zsvo_test_singleton"
mirror := "https://deb.debian.org/debian"
suite := "stable"
component := "main"
// Remove any existing cache
os.RemoveAll(cacheDir)
// Test 1: Multiple GetResolver calls should only parse once
fmt.Printf("\n📦 Test 1: Multiple GetResolver calls...\n")
start := time.Now()
// First call - should parse Sources.xz or load JSON cache
fmt.Printf("Call 1: ")
r1, err := resolver.GetResolver(cacheDir, mirror, suite, component)
if err != nil {
fmt.Printf("❌ Error: %v\n", err)
return
}
duration1 := time.Since(start)
fmt.Printf("✅ %v\n", duration1)
// Second call - should be instant
start = time.Now()
fmt.Printf("Call 2: ")
r2, err := resolver.GetResolver(cacheDir, mirror, suite, component)
if err != nil {
fmt.Printf("❌ Error: %v\n", err)
return
}
duration2 := time.Since(start)
fmt.Printf("✅ %v\n", duration2)
// Third call - should also be instant
start = time.Now()
fmt.Printf("Call 3: ")
r3, err := resolver.GetResolver(cacheDir, mirror, suite, component)
if err != nil {
fmt.Printf("❌ Error: %v\n", err)
return
}
duration3 := time.Since(start)
fmt.Printf("✅ %v\n", duration3)
// Verify same instance
if r1 == r2 && r2 == r3 {
fmt.Printf("✅ Same resolver instance (singleton working)\n")
} else {
fmt.Printf("❌ Different instances (singleton failed)\n")
}
// Test 2: Multiple dependency resolutions should not re-parse
fmt.Printf("\n📦 Test 2: Multiple dependency resolutions...\n")
totalStart := time.Now()
resolutions := 0
for i := 0; i < 5; i++ {
start = time.Now()
// Try to resolve a package (this will trigger dependency resolution)
graph, err := r1.ResolveDependencies("cmake")
if err != nil {
fmt.Printf(" Resolution %d: ❌ %v\n", i+1, err)
} else {
duration := time.Since(start)
nodeCount, maxLevel := graph.GetStats()
fmt.Printf(" Resolution %d: ✅ %v (%d packages, %d levels)\n",
i+1, duration, nodeCount, maxLevel)
}
resolutions++
}
totalDuration := time.Since(totalStart)
avgDuration := totalDuration / time.Duration(resolutions)
fmt.Printf("📊 Total time for %d resolutions: %v\n", resolutions, totalDuration)
fmt.Printf("📈 Average per resolution: %v\n", avgDuration)
// Results
fmt.Printf("\n🎯 Test Results:\n")
fmt.Printf("• First resolver init: %v\n", duration1)
fmt.Printf("• Second resolver init: %v\n", duration2)
fmt.Printf("• Third resolver init: %v\n", duration3)
fmt.Printf("• Average resolution time: %v\n", avgDuration)
// Check if singleton is working correctly
if duration2 < time.Millisecond && duration3 < time.Millisecond {
fmt.Printf("✅ SUCCESS: Singleton pattern working (subsequent calls <1ms)\n")
} else {
fmt.Printf("❌ FAILED: Singleton pattern broken (subsequent calls >1ms)\n")
fmt.Printf(" Expected: <1ms, Got: %v, %v\n", duration2, duration3)
}
// Check for performance regression
if avgDuration < 10*time.Millisecond {
fmt.Printf("✅ SUCCESS: No repeated parsing (avg resolution <10ms)\n")
} else {
fmt.Printf("❌ FAILED: Repeated parsing detected (avg resolution >10ms)\n")
}
fmt.Printf("\n📋 Expected behavior:\n")
fmt.Printf("• LoadIndex() should execute only once inside sync.Once\n")
fmt.Printf("• Subsequent GetResolver() calls should be <1ms\n")
fmt.Printf("• Dependency resolutions should not trigger re-parsing\n")
}