package imgcache import ( "context" "errors" "testing" "time" ) func TestNegativeCache_StoreAndCheck(t *testing.T) { db := setupTestDB(t) dir := t.TempDir() cache, err := NewCache(db, CacheConfig{ StateDir: dir, CacheTTL: time.Hour, NegativeTTL: 5 * time.Minute, }) if err != nil { t.Fatal(err) } ctx := context.Background() req := &ImageRequest{ SourceHost: "example.com", SourcePath: "/missing.jpg", } // Initially should not be in negative cache hit, err := cache.checkNegativeCache(ctx, req) if err != nil { t.Fatal(err) } if hit { t.Error("expected no negative cache hit initially") } // Store a negative entry err = cache.StoreNegative(ctx, req, 404, "not found") if err != nil { t.Fatal(err) } // Now should be in negative cache hit, err = cache.checkNegativeCache(ctx, req) if err != nil { t.Fatal(err) } if !hit { t.Error("expected negative cache hit after storing") } } func TestNegativeCache_Expired(t *testing.T) { db := setupTestDB(t) dir := t.TempDir() cache, err := NewCache(db, CacheConfig{ StateDir: dir, CacheTTL: time.Hour, NegativeTTL: 1 * time.Millisecond, // very short TTL }) if err != nil { t.Fatal(err) } ctx := context.Background() req := &ImageRequest{ SourceHost: "example.com", SourcePath: "/expired.jpg", } // Store a negative entry with very short TTL err = cache.StoreNegative(ctx, req, 500, "server error") if err != nil { t.Fatal(err) } // Wait for expiry time.Sleep(10 * time.Millisecond) // Should no longer be in negative cache hit, err := cache.checkNegativeCache(ctx, req) if err != nil { t.Fatal(err) } if hit { t.Error("expected expired negative cache entry to be a miss") } } func TestService_Get_ReturnsErrorForNegativeCachedURL(t *testing.T) { // This test verifies that Service.Get() checks the negative cache // We can't easily test the full pipeline without vips, but we can // verify the error type err := ErrNegativeCached if !errors.Is(err, ErrNegativeCached) { t.Error("ErrNegativeCached should be identifiable with errors.Is") } }