Files
pixa/internal/imgcache/cache_internal_test.go
T
clawbot 2f00c50c0b
check / check (push) Canceled after 0s
Split internal/imgcache into the image proxy and the cache (closes #317)
The new package internal/imageproxy holds Proxy, which was imgcache.Service,
with its Config, ImageResponse, CacheStatus and errors. NewProxy makes and
registers the counters of upstream fetches and transforms. internal/imgcache
holds the cache only, with its hit and miss counters, and imgcache.CacheConfig
is imgcache.Config. The cache reads and writes each kind it keeps with one pair
of methods: Variant and PutVariant, Source and PutSource, Failure and
PutFailure. Source replaces LookupSource followed by GetSourceContent.
imgcache.go and module.go are gone. The proxy's tests moved with it. They reach
the cache through its database, its state directory and its metrics registry,
and run its reconciliation pass with a second cache, as pixad does at startup.

Model: opus-5-5
2026-10-26 18:17:35 +00:00

129 lines
2.7 KiB
Go

package imgcache
import (
"context"
"database/sql"
"os"
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
_ "modernc.org/sqlite"
)
func setupTestDB(t *testing.T) *sql.DB {
t.Helper()
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
t.Fatalf("failed to open test db: %v", err)
}
// Create schema
schema := `
CREATE TABLE source_content (
source_key TEXT PRIMARY KEY,
size_bytes INTEGER NOT NULL,
last_accessed_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE negative_cache (
id INTEGER PRIMARY KEY AUTOINCREMENT,
source_host TEXT NOT NULL,
source_path TEXT NOT NULL,
source_query TEXT NOT NULL DEFAULT '',
expires_at DATETIME NOT NULL,
UNIQUE(source_host, source_path, source_query)
);
`
_, err = db.ExecContext(t.Context(), schema)
if err != nil {
t.Fatalf("failed to create schema: %v", err)
}
return db
}
func TestCache_CleanExpired(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
db := setupTestDB(t)
cache, _ := NewCache(db, Config{
StateDir: tmpDir,
NegativeTTL: 1 * time.Millisecond,
MaxBytes: 1 << 30,
}, prometheus.NewRegistry())
ctx := context.Background()
// Insert expired negative cache entry directly
_, err := db.ExecContext(ctx, `
INSERT INTO negative_cache
(source_host, source_path, source_query, expires_at)
VALUES ('example.com', '/old.jpg', '', datetime('now', '-1 hour'))
`)
if err != nil {
t.Fatalf("failed to insert test data: %v", err)
}
// Verify it exists
var count int
err = db.QueryRowContext(ctx, `SELECT COUNT(*) FROM negative_cache`).Scan(&count)
if err != nil {
t.Fatalf("failed to count negative cache entries: %v", err)
}
if count != 1 {
t.Fatalf("expected 1 negative cache entry, got %d", count)
}
// Clean expired
err = cache.CleanExpired(ctx)
if err != nil {
t.Fatalf("CleanExpired() error = %v", err)
}
// Verify it's gone
err = db.QueryRowContext(ctx, `SELECT COUNT(*) FROM negative_cache`).Scan(&count)
if err != nil {
t.Fatalf("failed to count negative cache entries: %v", err)
}
if count != 0 {
t.Errorf("expected 0 negative cache entries after clean, got %d", count)
}
}
func TestCache_StorageDirectoriesCreated(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
db := setupTestDB(t)
_, err := NewCache(db, Config{
StateDir: tmpDir,
MaxBytes: 1 << 30,
}, prometheus.NewRegistry())
if err != nil {
t.Fatalf("NewCache() error = %v", err)
}
// Verify directories were created
dirs := []string{
"cache/sources",
"cache/variants",
}
for _, dir := range dirs {
path := tmpDir + "/" + dir
_, err := os.Stat(path)
if os.IsNotExist(err) {
t.Errorf("directory %s was not created", dir)
}
}
}