Files

102 lines
3.3 KiB
Go
Raw Permalink Normal View History

package catalog
import (
"context"
"fmt"
"os"
"slices"
"testing"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
func newArtworkSelectionTestPool(t *testing.T) *pgxpool.Pool {
t.Helper()
dsn := os.Getenv("SILO_TEST_DATABASE_URL")
if dsn == "" {
t.Skip("SILO_TEST_DATABASE_URL is not set")
}
pool, err := pgxpool.New(context.Background(), dsn)
if err != nil {
t.Fatalf("connect test database: %v", err)
}
t.Cleanup(pool.Close)
return pool
}
func TestQueueAndParkArtworkRevisionUpserts(t *testing.T) {
pool := newArtworkSelectionTestPool(t)
ctx := context.Background()
suffix := time.Now().UnixNano()
path := fmt.Sprintf("tmdb/movies/%d/poster/original.rev.webp", suffix)
t.Cleanup(func() {
_, _ = pool.Exec(ctx, `DELETE FROM artwork_revision_gc_candidates WHERE original_path = $1`, path)
})
// Arming registers the revision for verification after the grace period.
if err := queueArtworkRevisionGC(ctx, pool, path, "poster", time.Now().Add(time.Hour)); err != nil {
t.Fatalf("queueArtworkRevisionGC: %v", err)
}
var imageType string
var nextAttempt *time.Time
if err := pool.QueryRow(ctx, `
SELECT image_type, next_attempt_at FROM artwork_revision_gc_candidates
WHERE original_path = $1`, path).Scan(&imageType, &nextAttempt); err != nil {
t.Fatalf("load armed candidate: %v", err)
}
if imageType != "poster" {
t.Fatalf("image_type = %q, want poster", imageType)
}
if nextAttempt == nil {
t.Fatal("armed candidate has NULL next_attempt_at")
}
// Publication parks the selected revision: referenced by construction.
if err := parkArtworkRevision(ctx, pool, path, "poster", time.Now().Add(time.Hour)); err != nil {
t.Fatalf("parkArtworkRevision: %v", err)
}
if err := pool.QueryRow(ctx, `
SELECT next_attempt_at FROM artwork_revision_gc_candidates
WHERE original_path = $1`, path).Scan(&nextAttempt); err != nil {
t.Fatalf("load parked candidate: %v", err)
}
if nextAttempt != nil {
t.Fatalf("parked candidate next_attempt_at = %v, want NULL", *nextAttempt)
}
}
func TestTrackArtworkRevisionKeepsDormantRowsDormant(t *testing.T) {
pool := newArtworkSelectionTestPool(t)
ctx := context.Background()
suffix := time.Now().UnixNano()
path := fmt.Sprintf("tmdb/movies/%d/poster/original.live.webp", suffix)
keys := []string{path, fmt.Sprintf("tmdb/movies/%d/poster/w500.live.webp", suffix)}
t.Cleanup(func() {
_, _ = pool.Exec(ctx, `DELETE FROM artwork_revision_gc_candidates WHERE original_path = $1`, path)
})
if err := parkArtworkRevision(ctx, pool, path, "poster", time.Now().Add(time.Hour)); err != nil {
t.Fatalf("parkArtworkRevision: %v", err)
}
// A re-cache of live artwork must not re-arm the parked row.
tracker := NewArtworkRevisionTracker(pool)
if err := tracker.TrackArtworkRevision(ctx, path, "poster", keys); err != nil {
t.Fatalf("TrackArtworkRevision: %v", err)
}
var nextAttempt *time.Time
var storedKeys []string
if err := pool.QueryRow(ctx, `
SELECT next_attempt_at, object_keys FROM artwork_revision_gc_candidates
WHERE original_path = $1`, path).Scan(&nextAttempt, &storedKeys); err != nil {
t.Fatalf("load candidate: %v", err)
}
if nextAttempt != nil {
t.Fatalf("re-cache re-armed dormant row: next_attempt_at = %v", *nextAttempt)
}
if !slices.Equal(storedKeys, keys) {
t.Fatalf("stored manifest = %v, want exact tracked manifest %v", storedKeys, keys)
}
}