package fileuploadcleanup import ( "context" "testing" "time" "hfb_sys/backend/internal/model" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func TestCleanupOnlyDeletesExpiredUnreferencedUploads(t *testing.T) { db := openTestDB(t) if err := db.AutoMigrate(&model.FileUploadOwner{}); err != nil { t.Fatalf("AutoMigrate() error = %v", err) } createReferenceTables(t, db) now := time.Date(2026, 8, 16, 0, 0, 0, 0, time.UTC) old := now.Add(-31 * 24 * time.Hour) recent := now.Add(-29 * 24 * time.Hour) records := []model.FileUploadOwner{ {UserID: 1, ObjectKey: "listing/orphan.jpg", CreatedAt: old}, {UserID: 1, ObjectKey: "listing/referenced.jpg", CreatedAt: old}, {UserID: 1, ObjectKey: "listing/recent.jpg", CreatedAt: recent}, } if err := db.Create(&records).Error; err != nil { t.Fatalf("create upload owners error = %v", err) } if err := db.Exec("INSERT INTO game_accounts (id, screenshot_urls) VALUES (1, ?)", `["/api/files/object?key=listing%2Freferenced.jpg"]`).Error; err != nil { t.Fatalf("create referenced account error = %v", err) } job := New(db, nil, nil) deleted, err := job.cleanup(context.Background(), now) if err != nil { t.Fatalf("cleanup() error = %v", err) } if deleted != 1 { t.Fatalf("cleanup() deleted = %d, want 1", deleted) } var remaining []model.FileUploadOwner if err := db.Order("id ASC").Find(&remaining).Error; err != nil { t.Fatalf("load remaining uploads error = %v", err) } if len(remaining) != 2 || remaining[0].ObjectKey != "listing/referenced.jpg" || remaining[1].ObjectKey != "listing/recent.jpg" { t.Fatalf("unexpected remaining uploads: %#v", remaining) } } func openTestDB(t *testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) if err != nil { t.Fatalf("open sqlite error = %v", err) } return db } func createReferenceTables(t *testing.T, db *gorm.DB) { t.Helper() statements := []string{ "CREATE TABLE game_accounts (id INTEGER PRIMARY KEY, screenshot_urls TEXT)", "CREATE TABLE order_checkouts (id INTEGER PRIMARY KEY, evidence_urls TEXT)", "CREATE TABLE disputes (id INTEGER PRIMARY KEY, evidence_urls TEXT)", "CREATE TABLE handoff_records (id INTEGER PRIMARY KEY, attachment_urls TEXT)", "CREATE TABLE chat_messages (id INTEGER PRIMARY KEY, attachment_urls TEXT)", "CREATE TABLE user_payment_accounts (id INTEGER PRIMARY KEY, certificate_urls TEXT)", } for _, statement := range statements { if err := db.Exec(statement).Error; err != nil { t.Fatalf("create reference table error = %v", err) } } }