99 lines
2.5 KiB
Go
99 lines
2.5 KiB
Go
package admin_test
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/backend/internal/admin"
|
|
|
|
_ "github.com/jackc/pgx/v5/stdlib"
|
|
)
|
|
|
|
func TestCacheGetReturnsFalseUntilPut(t *testing.T) {
|
|
t.Parallel()
|
|
cache := admin.NewCache()
|
|
if _, _, ok := cache.Get("alice"); ok {
|
|
t.Fatalf("Get on empty cache returned ok=true")
|
|
}
|
|
}
|
|
|
|
func TestCacheReadyFlipsAfterWarm(t *testing.T) {
|
|
t.Parallel()
|
|
cache := admin.NewCache()
|
|
if cache.Ready() {
|
|
t.Fatalf("Ready() = true before Warm")
|
|
}
|
|
store := admin.NewStore(stubDB(t))
|
|
if err := cache.Warm(context.Background(), store); err == nil {
|
|
t.Fatalf("Warm against an empty stub DB unexpectedly succeeded")
|
|
}
|
|
if cache.Ready() {
|
|
t.Fatalf("Ready() flipped after a failed Warm")
|
|
}
|
|
}
|
|
|
|
func TestCachePutIsVisibleToReader(t *testing.T) {
|
|
t.Parallel()
|
|
cache := admin.NewCache()
|
|
now := time.Date(2026, 5, 3, 12, 0, 0, 0, time.UTC)
|
|
cache.Put(admin.Admin{
|
|
Username: "alice",
|
|
CreatedAt: now,
|
|
}, []byte("hash-bytes"))
|
|
|
|
got, hash, ok := cache.Get("alice")
|
|
if !ok {
|
|
t.Fatalf("Get after Put returned ok=false")
|
|
}
|
|
if got.Username != "alice" {
|
|
t.Fatalf("Get returned username %q, want alice", got.Username)
|
|
}
|
|
if string(hash) != "hash-bytes" {
|
|
t.Fatalf("Get returned hash %q, want hash-bytes", string(hash))
|
|
}
|
|
if cache.Size() != 1 {
|
|
t.Fatalf("Size = %d, want 1", cache.Size())
|
|
}
|
|
}
|
|
|
|
func TestCachePutOverwrites(t *testing.T) {
|
|
t.Parallel()
|
|
cache := admin.NewCache()
|
|
cache.Put(admin.Admin{Username: "alice"}, []byte("old"))
|
|
cache.Put(admin.Admin{Username: "alice"}, []byte("new"))
|
|
|
|
_, hash, ok := cache.Get("alice")
|
|
if !ok || string(hash) != "new" {
|
|
t.Fatalf("Get after overwrite returned ok=%v hash=%q, want ok=true hash=new", ok, string(hash))
|
|
}
|
|
if cache.Size() != 1 {
|
|
t.Fatalf("Size after overwrite = %d, want 1", cache.Size())
|
|
}
|
|
}
|
|
|
|
func TestCacheRemove(t *testing.T) {
|
|
t.Parallel()
|
|
cache := admin.NewCache()
|
|
cache.Put(admin.Admin{Username: "alice"}, []byte("hash"))
|
|
cache.Remove("alice")
|
|
if _, _, ok := cache.Get("alice"); ok {
|
|
t.Fatalf("Get after Remove returned ok=true")
|
|
}
|
|
cache.Remove("alice") // idempotent — must not panic
|
|
}
|
|
|
|
// stubDB returns a *sql.DB that fails every query. Used only by the
|
|
// "Warm-on-failure does not flip Ready" test where the actual driver
|
|
// behaviour is irrelevant.
|
|
func stubDB(t *testing.T) *sql.DB {
|
|
t.Helper()
|
|
db, err := sql.Open("pgx", "postgres://disabled.invalid:5432/none?sslmode=disable&connect_timeout=1")
|
|
if err != nil {
|
|
t.Fatalf("sql.Open: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = db.Close() })
|
|
return db
|
|
}
|