Files
nuntius/internal/storage/pending_test.go
petrbalvin 3a38f00dc0
Test / test (push) Successful in 2m1s
Release / gates (push) Successful in 1m57s
Release / build (amd64, freebsd) (push) Successful in 1m26s
Release / build (amd64, linux) (push) Successful in 1m30s
Release / build (arm64, freebsd) (push) Successful in 1m28s
Release / build (arm64, linux) (push) Successful in 1m49s
Release / build (loong64, linux) (push) Successful in 1m30s
Release / build (riscv64, linux) (push) Successful in 1m29s
Release / release (push) Successful in 41s
feat: contact form backend for linux and freebsd servers
Assisted-by: GLM 5.3 Flash
2026-09-29 00:32:56 +02:00

92 lines
2.5 KiB
Go

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: MIT
//go:build linux || freebsd
package storage
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func TestPendingStoreRoundTrip(t *testing.T) {
p := NewPendingStore(filepath.Join(t.TempDir(), "pending.json"), 72*time.Hour)
if _, ok := p.Consume("unknown-token"); ok {
t.Fatal("unknown token must not consume")
}
if err := p.Issue("token-a", PendingSubscription{Email: "Jane@Example.COM", IP: "203.0.113.9"}); err != nil {
t.Fatalf("issue: %v", err)
}
sub, ok := p.Consume("token-a")
if !ok {
t.Fatal("valid token must consume")
}
if sub.Email != "Jane@Example.COM" || sub.IP != "203.0.113.9" {
t.Errorf("consumed entry = %+v", sub)
}
if _, ok := p.Consume("token-a"); ok {
t.Error("token must be single-use")
}
}
// An expired entry is never returned and is purged from the file.
func TestPendingStoreExpiry(t *testing.T) {
path := filepath.Join(t.TempDir(), "pending.json")
stale, _ := json.Marshal(pendingFile{Schema: pendingSchema, Entries: map[string]PendingSubscription{
hashToken("old"): {Email: "a@b.c", CreatedAt: time.Now().Add(-96 * time.Hour)},
}})
if err := os.WriteFile(path, stale, 0o600); err != nil {
t.Fatal(err)
}
if _, ok := NewPendingStore(path, 72*time.Hour).Consume("old"); ok {
t.Fatal("expired token must not consume")
}
raw, _ := os.ReadFile(path)
if strings.Contains(string(raw), `"a@b.c"`) {
t.Error("expired entry was not purged from the file")
}
}
// Issue replaces the previous live token for the same address.
func TestPendingStoreRotation(t *testing.T) {
path := filepath.Join(t.TempDir(), "pending.json")
p := NewPendingStore(path, 72*time.Hour)
if err := p.Issue("first", PendingSubscription{Email: "jane@example.com"}); err != nil {
t.Fatal(err)
}
if err := p.Issue("second", PendingSubscription{Email: "jane@example.com"}); err != nil {
t.Fatal(err)
}
raw, _ := os.ReadFile(path)
if strings.Count(string(raw), "@") != 1 {
t.Errorf("expected a single live entry after rotation, got %s", raw)
}
if _, ok := p.Consume("first"); ok {
t.Error("superseded token must no longer work")
}
if _, ok := p.Consume("second"); !ok {
t.Error("current token must still work")
}
}
func TestRandomTokenIsHexAndUnique(t *testing.T) {
a, err := RandomToken()
if err != nil {
t.Fatal(err)
}
b, err := RandomToken()
if err != nil {
t.Fatal(err)
}
if len(a) != 64 || a == b {
t.Errorf("tokens = %q %q, want unique 64-char hex", a, b)
}
}