package auth import ( "sync" "testing" "time" ) func TestCachePutGet(t *testing.T) { t.Helper() c := newCache(30 * time.Second) claims := &Claims{Subject: "alice", AccountType: "user", Roles: []string{"reader"}} c.put("abc123", claims) got, ok := c.get("abc123") if !ok { t.Fatal("expected cache hit, got miss") } if got.Subject != "alice" { t.Fatalf("subject: got %q, want %q", got.Subject, "alice") } } func TestCacheTTLExpiry(t *testing.T) { t.Helper() now := time.Now() c := newCache(30 * time.Second) c.now = func() time.Time { return now } claims := &Claims{Subject: "bob"} c.put("def456", claims) // Still within TTL. got, ok := c.get("def456") if !ok { t.Fatal("expected cache hit before TTL expiry") } if got.Subject != "bob" { t.Fatalf("subject: got %q, want %q", got.Subject, "bob") } // Advance clock past TTL. c.now = func() time.Time { return now.Add(31 * time.Second) } _, ok = c.get("def456") if ok { t.Fatal("expected cache miss after TTL expiry, got hit") } } func TestCacheConcurrent(t *testing.T) { t.Helper() c := newCache(30 * time.Second) var wg sync.WaitGroup for i := range 100 { wg.Add(2) key := string(rune('A' + i%26)) go func() { defer wg.Done() c.put(key, &Claims{Subject: key}) }() go func() { defer wg.Done() c.get(key) //nolint:gosec // result intentionally ignored in concurrency test }() } wg.Wait() // If we get here without a race detector complaint, the test passes. }