196 lines
5.0 KiB
Go
196 lines
5.0 KiB
Go
package auth
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestGetServiceToken_NotCached(t *testing.T) {
|
|
// Clear cache first
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens = make(map[string]*serviceTokenEntry)
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
did := "did:plc:test123"
|
|
holdDID := "did:web:hold.example.com"
|
|
|
|
token, expiresAt := GetServiceToken(did, holdDID)
|
|
if token != "" {
|
|
t.Errorf("Expected empty token for uncached entry, got %q", token)
|
|
}
|
|
if !expiresAt.IsZero() {
|
|
t.Error("Expected zero time for uncached entry")
|
|
}
|
|
}
|
|
|
|
func TestSetServiceToken_ManualExpiry(t *testing.T) {
|
|
// Clear cache first
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens = make(map[string]*serviceTokenEntry)
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
did := "did:plc:test123"
|
|
holdDID := "did:web:hold.example.com"
|
|
token := "invalid_jwt_token" // Will fall back to 50s default
|
|
|
|
// This should succeed with default 50s TTL since JWT parsing will fail
|
|
err := SetServiceToken(did, holdDID, token)
|
|
if err != nil {
|
|
t.Fatalf("SetServiceToken() error = %v", err)
|
|
}
|
|
|
|
// Verify token was cached
|
|
cachedToken, expiresAt := GetServiceToken(did, holdDID)
|
|
if cachedToken != token {
|
|
t.Errorf("Expected token %q, got %q", token, cachedToken)
|
|
}
|
|
if expiresAt.IsZero() {
|
|
t.Error("Expected non-zero expiry time")
|
|
}
|
|
|
|
// Expiry should be approximately 50s from now (with 10s margin subtracted in some cases)
|
|
expectedExpiry := time.Now().Add(50 * time.Second)
|
|
diff := expiresAt.Sub(expectedExpiry)
|
|
if diff < -5*time.Second || diff > 5*time.Second {
|
|
t.Errorf("Expiry time off by %v (expected ~50s from now)", diff)
|
|
}
|
|
}
|
|
|
|
func TestGetServiceToken_Expired(t *testing.T) {
|
|
// Manually insert an expired token
|
|
did := "did:plc:test123"
|
|
holdDID := "did:web:hold.example.com"
|
|
cacheKey := did + ":" + holdDID
|
|
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens[cacheKey] = &serviceTokenEntry{
|
|
token: "expired_token",
|
|
expiresAt: time.Now().Add(-1 * time.Hour), // 1 hour ago
|
|
}
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
// Try to get - should return empty since expired
|
|
token, expiresAt := GetServiceToken(did, holdDID)
|
|
if token != "" {
|
|
t.Errorf("Expected empty token for expired entry, got %q", token)
|
|
}
|
|
if !expiresAt.IsZero() {
|
|
t.Error("Expected zero time for expired entry")
|
|
}
|
|
|
|
// Verify token was removed from cache
|
|
globalServiceTokensMu.RLock()
|
|
_, exists := globalServiceTokens[cacheKey]
|
|
globalServiceTokensMu.RUnlock()
|
|
|
|
if exists {
|
|
t.Error("Expected expired token to be removed from cache")
|
|
}
|
|
}
|
|
|
|
func TestInvalidateServiceToken(t *testing.T) {
|
|
// Set a token
|
|
did := "did:plc:test123"
|
|
holdDID := "did:web:hold.example.com"
|
|
token := "test_token"
|
|
|
|
err := SetServiceToken(did, holdDID, token)
|
|
if err != nil {
|
|
t.Fatalf("SetServiceToken() error = %v", err)
|
|
}
|
|
|
|
// Verify it's cached
|
|
cachedToken, _ := GetServiceToken(did, holdDID)
|
|
if cachedToken != token {
|
|
t.Fatal("Token should be cached")
|
|
}
|
|
|
|
// Invalidate
|
|
InvalidateServiceToken(did, holdDID)
|
|
|
|
// Verify it's gone
|
|
cachedToken, _ = GetServiceToken(did, holdDID)
|
|
if cachedToken != "" {
|
|
t.Error("Expected token to be invalidated")
|
|
}
|
|
}
|
|
|
|
func TestCleanExpiredTokens(t *testing.T) {
|
|
// Clear cache first
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens = make(map[string]*serviceTokenEntry)
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
// Add expired and valid tokens
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens["expired:hold1"] = &serviceTokenEntry{
|
|
token: "expired1",
|
|
expiresAt: time.Now().Add(-1 * time.Hour),
|
|
}
|
|
globalServiceTokens["valid:hold2"] = &serviceTokenEntry{
|
|
token: "valid1",
|
|
expiresAt: time.Now().Add(1 * time.Hour),
|
|
}
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
// Clean expired
|
|
CleanExpiredTokens()
|
|
|
|
// Verify only valid token remains
|
|
globalServiceTokensMu.RLock()
|
|
_, expiredExists := globalServiceTokens["expired:hold1"]
|
|
_, validExists := globalServiceTokens["valid:hold2"]
|
|
globalServiceTokensMu.RUnlock()
|
|
|
|
if expiredExists {
|
|
t.Error("Expected expired token to be removed")
|
|
}
|
|
if !validExists {
|
|
t.Error("Expected valid token to remain")
|
|
}
|
|
}
|
|
|
|
func TestGetCacheStats(t *testing.T) {
|
|
// Clear cache first
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens = make(map[string]*serviceTokenEntry)
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
// Add some tokens
|
|
globalServiceTokensMu.Lock()
|
|
globalServiceTokens["did1:hold1"] = &serviceTokenEntry{
|
|
token: "token1",
|
|
expiresAt: time.Now().Add(1 * time.Hour),
|
|
}
|
|
globalServiceTokens["did2:hold2"] = &serviceTokenEntry{
|
|
token: "token2",
|
|
expiresAt: time.Now().Add(1 * time.Hour),
|
|
}
|
|
globalServiceTokensMu.Unlock()
|
|
|
|
stats := GetCacheStats()
|
|
if stats == nil {
|
|
t.Fatal("Expected non-nil stats")
|
|
}
|
|
|
|
// GetCacheStats returns map[string]any with "total_entries" key
|
|
totalEntries, ok := stats["total_entries"].(int)
|
|
if !ok {
|
|
t.Fatalf("Expected total_entries in stats map, got: %v", stats)
|
|
}
|
|
|
|
if totalEntries != 2 {
|
|
t.Errorf("Expected 2 entries, got %d", totalEntries)
|
|
}
|
|
|
|
// Also check valid_tokens
|
|
validTokens, ok := stats["valid_tokens"].(int)
|
|
if !ok {
|
|
t.Fatal("Expected valid_tokens in stats map")
|
|
}
|
|
|
|
if validTokens != 2 {
|
|
t.Errorf("Expected 2 valid tokens, got %d", validTokens)
|
|
}
|
|
}
|