package storage import ( "testing" "time" ) func TestHoldCache_SetAndGet(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } did := "did:plc:test123" repo := "myapp" holdDID := "did:web:hold01.atcr.io" ttl := 10 * time.Minute // Set a value cache.Set(did, repo, holdDID, ttl) // Get the value - should succeed gotHoldDID, ok := cache.Get(did, repo) if !ok { t.Fatal("Expected Get to return true, got false") } if gotHoldDID != holdDID { t.Errorf("Expected hold DID %q, got %q", holdDID, gotHoldDID) } } func TestHoldCache_GetNonExistent(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } // Get non-existent value _, ok := cache.Get("did:plc:nonexistent", "repo") if ok { t.Error("Expected Get to return false for non-existent key") } } func TestHoldCache_ExpiredEntry(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } did := "did:plc:test123" repo := "myapp" holdDID := "did:web:hold01.atcr.io" // Set with very short TTL cache.Set(did, repo, holdDID, 10*time.Millisecond) // Wait for expiration time.Sleep(20 * time.Millisecond) // Get should return false _, ok := cache.Get(did, repo) if ok { t.Error("Expected Get to return false for expired entry") } } func TestHoldCache_Cleanup(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } // Add multiple entries with different TTLs cache.Set("did:plc:1", "repo1", "hold1", 10*time.Millisecond) cache.Set("did:plc:2", "repo2", "hold2", 1*time.Hour) cache.Set("did:plc:3", "repo3", "hold3", 10*time.Millisecond) // Wait for some to expire time.Sleep(20 * time.Millisecond) // Run cleanup cache.Cleanup() // Verify expired entries are removed if _, ok := cache.Get("did:plc:1", "repo1"); ok { t.Error("Expected expired entry 1 to be removed") } if _, ok := cache.Get("did:plc:3", "repo3"); ok { t.Error("Expected expired entry 3 to be removed") } // Verify non-expired entry remains if _, ok := cache.Get("did:plc:2", "repo2"); !ok { t.Error("Expected non-expired entry to remain") } } func TestHoldCache_ConcurrentAccess(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } done := make(chan bool) // Concurrent writes for i := 0; i < 10; i++ { go func(id int) { did := "did:plc:concurrent" repo := "repo" + string(rune(id)) holdDID := "hold" + string(rune(id)) cache.Set(did, repo, holdDID, 1*time.Minute) done <- true }(i) } // Concurrent reads for i := 0; i < 10; i++ { go func(id int) { repo := "repo" + string(rune(id)) cache.Get("did:plc:concurrent", repo) done <- true }(i) } // Wait for all goroutines for i := 0; i < 20; i++ { <-done } } func TestHoldCache_KeyFormat(t *testing.T) { cache := &HoldCache{ cache: make(map[string]*holdCacheEntry), } did := "did:plc:test" repo := "myrepo" holdDID := "did:web:hold" cache.Set(did, repo, holdDID, 1*time.Minute) // Verify the key is stored correctly (did:repo) expectedKey := did + ":" + repo if _, exists := cache.cache[expectedKey]; !exists { t.Errorf("Expected key %q to exist in cache", expectedKey) } } // TODO: Add more comprehensive tests: // - Test GetGlobalHoldCache() // - Test cache size monitoring // - Benchmark cache performance under load // - Test cleanup goroutine timing