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") }