package storage import ( "net/http" "net/http/httptest" "net/url" "strconv" "testing" "time" ) func expiryOf(t *testing.T, raw string) int64 { t.Helper() u, err := url.Parse(raw) if err != nil { t.Fatalf("parse url: %v", err) } e, err := strconv.ParseInt(u.Query().Get("e"), 10, 64) if err != nil { t.Fatalf("parse expiry: %v", err) } return e } func TestSignerURLStableWithinWindow(t *testing.T) { s, err := NewSigner("http://app.test", "secret", time.Hour, time.Hour) if err != nil { t.Fatalf("new signer: %v", err) } first := s.URL("objects/a/thumb.webp") second := s.URL("objects/a/thumb.webp") if first != second { t.Fatalf("URL changed within window:\n %q\n %q", first, second) } } func TestSignerURLChangesAcrossWindow(t *testing.T) { s, err := NewSigner("http://app.test", "secret", time.Hour, 10*time.Minute) if err != nil { t.Fatalf("new signer: %v", err) } base := time.Now() s.now = func() time.Time { return base } first := expiryOf(t, s.URL("objects/a/thumb.webp")) s.now = func() time.Time { return base.Add(s.window) } second := expiryOf(t, s.URL("objects/a/thumb.webp")) if first == second { t.Fatalf("expiry did not advance across window: %d", first) } } func TestSignerURLVerifies(t *testing.T) { s, err := NewSigner("http://app.test", "secret", time.Hour, 10*time.Minute) if err != nil { t.Fatalf("new signer: %v", err) } key := "objects/a/thumb.webp" raw := s.URL(key) req := httptest.NewRequest(http.MethodGet, raw, nil) if err := s.VerifyRequest(key, req); err != nil { t.Fatalf("verify issued URL: %v", err) } }