A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
73
fork

Configure Feed

Select the types of activity you want to include in your feed.

at refactor 195 lines 5.1 kB view raw
1package auth 2 3import ( 4 "testing" 5 "time" 6) 7 8func TestGetServiceToken_NotCached(t *testing.T) { 9 // Clear cache first 10 globalServiceTokensMu.Lock() 11 globalServiceTokens = make(map[string]*serviceTokenEntry) 12 globalServiceTokensMu.Unlock() 13 14 did := "did:plc:test123" 15 holdDID := "did:web:hold.example.com" 16 17 token, expiresAt := GetServiceToken(did, holdDID) 18 if token != "" { 19 t.Errorf("Expected empty token for uncached entry, got %q", token) 20 } 21 if !expiresAt.IsZero() { 22 t.Error("Expected zero time for uncached entry") 23 } 24} 25 26func TestSetServiceToken_ManualExpiry(t *testing.T) { 27 // Clear cache first 28 globalServiceTokensMu.Lock() 29 globalServiceTokens = make(map[string]*serviceTokenEntry) 30 globalServiceTokensMu.Unlock() 31 32 did := "did:plc:test123" 33 holdDID := "did:web:hold.example.com" 34 token := "invalid_jwt_token" // Will fall back to 50s default 35 36 // This should succeed with default 50s TTL since JWT parsing will fail 37 err := SetServiceToken(did, holdDID, token) 38 if err != nil { 39 t.Fatalf("SetServiceToken() error = %v", err) 40 } 41 42 // Verify token was cached 43 cachedToken, expiresAt := GetServiceToken(did, holdDID) 44 if cachedToken != token { 45 t.Errorf("Expected token %q, got %q", token, cachedToken) 46 } 47 if expiresAt.IsZero() { 48 t.Error("Expected non-zero expiry time") 49 } 50 51 // Expiry should be approximately 50s from now (with 10s margin subtracted in some cases) 52 expectedExpiry := time.Now().Add(50 * time.Second) 53 diff := expiresAt.Sub(expectedExpiry) 54 if diff < -5*time.Second || diff > 5*time.Second { 55 t.Errorf("Expiry time off by %v (expected ~50s from now)", diff) 56 } 57} 58 59func TestGetServiceToken_Expired(t *testing.T) { 60 // Manually insert an expired token 61 did := "did:plc:test123" 62 holdDID := "did:web:hold.example.com" 63 cacheKey := did + ":" + holdDID 64 65 globalServiceTokensMu.Lock() 66 globalServiceTokens[cacheKey] = &serviceTokenEntry{ 67 token: "expired_token", 68 expiresAt: time.Now().Add(-1 * time.Hour), // 1 hour ago 69 } 70 globalServiceTokensMu.Unlock() 71 72 // Try to get - should return empty since expired 73 token, expiresAt := GetServiceToken(did, holdDID) 74 if token != "" { 75 t.Errorf("Expected empty token for expired entry, got %q", token) 76 } 77 if !expiresAt.IsZero() { 78 t.Error("Expected zero time for expired entry") 79 } 80 81 // Verify token was removed from cache 82 globalServiceTokensMu.RLock() 83 _, exists := globalServiceTokens[cacheKey] 84 globalServiceTokensMu.RUnlock() 85 86 if exists { 87 t.Error("Expected expired token to be removed from cache") 88 } 89} 90 91func TestInvalidateServiceToken(t *testing.T) { 92 // Set a token 93 did := "did:plc:test123" 94 holdDID := "did:web:hold.example.com" 95 token := "test_token" 96 97 err := SetServiceToken(did, holdDID, token) 98 if err != nil { 99 t.Fatalf("SetServiceToken() error = %v", err) 100 } 101 102 // Verify it's cached 103 cachedToken, _ := GetServiceToken(did, holdDID) 104 if cachedToken != token { 105 t.Fatal("Token should be cached") 106 } 107 108 // Invalidate 109 InvalidateServiceToken(did, holdDID) 110 111 // Verify it's gone 112 cachedToken, _ = GetServiceToken(did, holdDID) 113 if cachedToken != "" { 114 t.Error("Expected token to be invalidated") 115 } 116} 117 118func TestCleanExpiredTokens(t *testing.T) { 119 // Clear cache first 120 globalServiceTokensMu.Lock() 121 globalServiceTokens = make(map[string]*serviceTokenEntry) 122 globalServiceTokensMu.Unlock() 123 124 // Add expired and valid tokens 125 globalServiceTokensMu.Lock() 126 globalServiceTokens["expired:hold1"] = &serviceTokenEntry{ 127 token: "expired1", 128 expiresAt: time.Now().Add(-1 * time.Hour), 129 } 130 globalServiceTokens["valid:hold2"] = &serviceTokenEntry{ 131 token: "valid1", 132 expiresAt: time.Now().Add(1 * time.Hour), 133 } 134 globalServiceTokensMu.Unlock() 135 136 // Clean expired 137 CleanExpiredTokens() 138 139 // Verify only valid token remains 140 globalServiceTokensMu.RLock() 141 _, expiredExists := globalServiceTokens["expired:hold1"] 142 _, validExists := globalServiceTokens["valid:hold2"] 143 globalServiceTokensMu.RUnlock() 144 145 if expiredExists { 146 t.Error("Expected expired token to be removed") 147 } 148 if !validExists { 149 t.Error("Expected valid token to remain") 150 } 151} 152 153func TestGetCacheStats(t *testing.T) { 154 // Clear cache first 155 globalServiceTokensMu.Lock() 156 globalServiceTokens = make(map[string]*serviceTokenEntry) 157 globalServiceTokensMu.Unlock() 158 159 // Add some tokens 160 globalServiceTokensMu.Lock() 161 globalServiceTokens["did1:hold1"] = &serviceTokenEntry{ 162 token: "token1", 163 expiresAt: time.Now().Add(1 * time.Hour), 164 } 165 globalServiceTokens["did2:hold2"] = &serviceTokenEntry{ 166 token: "token2", 167 expiresAt: time.Now().Add(1 * time.Hour), 168 } 169 globalServiceTokensMu.Unlock() 170 171 stats := GetCacheStats() 172 if stats == nil { 173 t.Fatal("Expected non-nil stats") 174 } 175 176 // GetCacheStats returns map[string]any with "total_entries" key 177 totalEntries, ok := stats["total_entries"].(int) 178 if !ok { 179 t.Fatalf("Expected total_entries in stats map, got: %v", stats) 180 } 181 182 if totalEntries != 2 { 183 t.Errorf("Expected 2 entries, got %d", totalEntries) 184 } 185 186 // Also check valid_tokens 187 validTokens, ok := stats["valid_tokens"].(int) 188 if !ok { 189 t.Fatal("Expected valid_tokens in stats map") 190 } 191 192 if validTokens != 2 { 193 t.Errorf("Expected 2 valid tokens, got %d", validTokens) 194 } 195}