85 lines
2.7 KiB
Go
85 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// insertPasteWithSlug creates a paste directly with a custom slug and controlled
|
|
// created_at/expires_at, bypassing the API's timestamp handling.
|
|
func insertPasteWithSlug(t *testing.T, s *Store, slug string, createdAt, expiresAt int64) string {
|
|
t.Helper()
|
|
id := genSlug(6)
|
|
_, err := s.db.Exec(`INSERT INTO pastes (id, custom_slug, content, content_type, created_at, expires_at)
|
|
VALUES (?, ?, ?, ?, ?, ?)`, id, slug, "x", "text/plain", createdAt, expiresAt)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return id
|
|
}
|
|
|
|
func strPtr(s string) *string { return &s }
|
|
|
|
func TestReleaseSlugOnExpiredPaste(t *testing.T) {
|
|
s := testServer(t)
|
|
now := time.Now().Unix()
|
|
insertPasteWithSlug(t, s.store, "release-notes", now-3600, now-60)
|
|
if n, err := s.store.ReleaseCustomSlugs(); err != nil || n != 1 {
|
|
t.Fatalf("released %d err %v, want 1", n, err)
|
|
}
|
|
if taken, _ := s.store.SlugTaken("release-notes"); taken {
|
|
t.Fatal("slug should be released after expiry")
|
|
}
|
|
// slug must be reusable by a new paste
|
|
p, err := s.store.CreatePaste(&Paste{Content: "new", CustomSlug: strPtr("release-notes")})
|
|
if err != nil {
|
|
t.Fatalf("reuse slug: %v", err)
|
|
}
|
|
if p.CustomSlug == nil || *p.CustomSlug != "release-notes" {
|
|
t.Fatal("new paste did not claim released slug")
|
|
}
|
|
}
|
|
|
|
func TestReleaseSlugOnOldPaste(t *testing.T) {
|
|
s := testServer(t)
|
|
now := time.Now().Unix()
|
|
// created 31 days ago, no expiry -> released by 30-day reservation rule
|
|
insertPasteWithSlug(t, s.store, "old-url", now-31*86400, 0)
|
|
if n, err := s.store.ReleaseCustomSlugs(); err != nil || n != 1 {
|
|
t.Fatalf("released %d err %v, want 1", n, err)
|
|
}
|
|
if taken, _ := s.store.SlugTaken("old-url"); taken {
|
|
t.Fatal("slug should be released after 30-day reservation")
|
|
}
|
|
}
|
|
|
|
func TestKeepSlugOnRecentUnexpiredPaste(t *testing.T) {
|
|
s := testServer(t)
|
|
now := time.Now().Unix()
|
|
insertPasteWithSlug(t, s.store, "fresh-url", now-3600, now+86400)
|
|
insertPasteWithSlug(t, s.store, "fresh-url2", now-3600, 0)
|
|
if n, err := s.store.ReleaseCustomSlugs(); err != nil || n != 0 {
|
|
t.Fatalf("released %d err %v, want 0", n, err)
|
|
}
|
|
for _, slug := range []string{"fresh-url", "fresh-url2"} {
|
|
if taken, _ := s.store.SlugTaken(slug); !taken {
|
|
t.Fatalf("slug %q should still be held", slug)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSweeperTickerReleasesSlugs(t *testing.T) {
|
|
s := testServer(t)
|
|
now := time.Now().Unix()
|
|
insertPasteWithSlug(t, s.store, "ticker-url", now-7200, now-3600)
|
|
s.store.StartSweeper(10 * time.Millisecond)
|
|
deadline := time.Now().Add(2 * time.Second)
|
|
for time.Now().Before(deadline) {
|
|
if taken, _ := s.store.SlugTaken("ticker-url"); !taken {
|
|
return
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
t.Fatal("ticker did not release slug in time")
|
|
}
|