mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-06-05 22:44:17 +00:00
228 lines
5.3 KiB
Go
228 lines
5.3 KiB
Go
package traefikoidc
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTokenBlacklistSizeLimit(t *testing.T) {
|
|
tb := NewTokenBlacklist()
|
|
|
|
// Add tokens up to maxSize
|
|
for i := 0; i < 1000; i++ {
|
|
tb.Add(fmt.Sprintf("token%d", i), time.Now().Add(time.Hour))
|
|
}
|
|
|
|
// Verify size is at max
|
|
if tb.Count() != 1000 {
|
|
t.Errorf("Expected blacklist size to be 1000, got %d", tb.Count())
|
|
}
|
|
|
|
// Add one more token, should trigger cleanup/eviction
|
|
tb.Add("newtoken", time.Now().Add(time.Hour))
|
|
|
|
// Size should still be at max
|
|
if tb.Count() > 1000 {
|
|
t.Errorf("Blacklist exceeded max size: %d", tb.Count())
|
|
}
|
|
}
|
|
|
|
func TestTokenBlacklistExpiredCleanup(t *testing.T) {
|
|
tb := NewTokenBlacklist()
|
|
|
|
// Add some expired tokens
|
|
for i := 0; i < 500; i++ {
|
|
tb.Add(fmt.Sprintf("expired%d", i), time.Now().Add(-time.Hour))
|
|
}
|
|
|
|
// Add some valid tokens
|
|
for i := 0; i < 500; i++ {
|
|
tb.Add(fmt.Sprintf("valid%d", i), time.Now().Add(time.Hour))
|
|
}
|
|
|
|
// Force cleanup
|
|
tb.Cleanup()
|
|
|
|
// Only valid tokens should remain
|
|
if tb.Count() != 500 {
|
|
t.Errorf("Expected 500 valid tokens after cleanup, got %d", tb.Count())
|
|
}
|
|
|
|
// Verify only valid tokens remain
|
|
tb.mutex.RLock()
|
|
defer tb.mutex.RUnlock()
|
|
for token, expiry := range tb.tokens {
|
|
if time.Now().After(expiry) {
|
|
t.Errorf("Found expired token after cleanup: %s", token)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTokenBlacklistOldestEviction(t *testing.T) {
|
|
tb := NewTokenBlacklist()
|
|
|
|
// Add tokens at capacity with different expiration times
|
|
baseTime := time.Now()
|
|
oldestToken := "oldest"
|
|
|
|
// Add oldest token first
|
|
tb.Add(oldestToken, baseTime.Add(time.Hour))
|
|
|
|
// Fill up to capacity with newer tokens
|
|
for i := 0; i < 999; i++ {
|
|
tb.Add(fmt.Sprintf("token%d", i), baseTime.Add(time.Hour*2))
|
|
}
|
|
|
|
// Add a new token that should evict the oldest
|
|
newToken := "newest"
|
|
tb.Add(newToken, baseTime.Add(time.Hour*3))
|
|
|
|
// Verify oldest token was evicted
|
|
if tb.IsBlacklisted(oldestToken) {
|
|
t.Error("Oldest token should have been evicted")
|
|
}
|
|
|
|
// Verify newest token is present
|
|
if !tb.IsBlacklisted(newToken) {
|
|
t.Error("Newest token should be present")
|
|
}
|
|
}
|
|
|
|
func TestTokenBlacklistMemoryUsage(t *testing.T) {
|
|
tb := NewTokenBlacklist()
|
|
iterations := 10000
|
|
|
|
// Force initial GC
|
|
runtime.GC()
|
|
|
|
// Record initial memory stats
|
|
var m1, m2 runtime.MemStats
|
|
runtime.ReadMemStats(&m1)
|
|
|
|
// Simulate heavy usage
|
|
for i := 0; i < iterations; i++ {
|
|
// Add new token
|
|
tb.Add(fmt.Sprintf("token%d", i), time.Now().Add(time.Hour))
|
|
|
|
// Periodically check blacklisted status
|
|
if i%100 == 0 {
|
|
tb.IsBlacklisted(fmt.Sprintf("token%d", i-50))
|
|
}
|
|
|
|
// Periodically cleanup
|
|
if i%1000 == 0 {
|
|
tb.Cleanup()
|
|
}
|
|
}
|
|
|
|
// Force GC and wait for it to complete
|
|
runtime.GC()
|
|
time.Sleep(100 * time.Millisecond)
|
|
runtime.ReadMemStats(&m2)
|
|
|
|
// Check memory growth (using HeapAlloc for more accurate measurement)
|
|
memoryGrowth := int64(m2.HeapAlloc - m1.HeapAlloc)
|
|
maxAllowedGrowth := int64(2 * 1024 * 1024) // 2MB max growth
|
|
|
|
if memoryGrowth > maxAllowedGrowth {
|
|
t.Logf("Initial HeapAlloc: %d, Final HeapAlloc: %d", m1.HeapAlloc, m2.HeapAlloc)
|
|
t.Errorf("Excessive memory growth: %d bytes", memoryGrowth)
|
|
}
|
|
|
|
// Verify size stayed within limits
|
|
if tb.Count() > 1000 {
|
|
t.Errorf("Blacklist exceeded max size: %d", tb.Count())
|
|
}
|
|
}
|
|
|
|
func TestConcurrentTokenBlacklistOperations(t *testing.T) {
|
|
tb := NewTokenBlacklist()
|
|
iterations := 1000
|
|
concurrency := 10
|
|
done := make(chan bool)
|
|
|
|
// Start multiple goroutines performing operations
|
|
for i := 0; i < concurrency; i++ {
|
|
go func(id int) {
|
|
for j := 0; j < iterations; j++ {
|
|
// Add tokens
|
|
token := fmt.Sprintf("token%d-%d", id, j)
|
|
tb.Add(token, time.Now().Add(time.Hour))
|
|
|
|
// Check blacklist status
|
|
tb.IsBlacklisted(token)
|
|
|
|
// Periodic cleanup
|
|
if j%100 == 0 {
|
|
tb.Cleanup()
|
|
}
|
|
}
|
|
done <- true
|
|
}(i)
|
|
}
|
|
|
|
// Wait for all goroutines to complete
|
|
for i := 0; i < concurrency; i++ {
|
|
<-done
|
|
}
|
|
|
|
// Verify size constraints were maintained
|
|
if tb.Count() > 1000 {
|
|
t.Errorf("Blacklist exceeded max size under concurrent operations: %d", tb.Count())
|
|
}
|
|
}
|
|
|
|
func TestTokenCacheMemoryUsage(t *testing.T) {
|
|
tc := NewTokenCache()
|
|
iterations := 10000
|
|
|
|
// Force initial GC
|
|
runtime.GC()
|
|
|
|
// Record initial memory stats
|
|
var m1, m2 runtime.MemStats
|
|
runtime.ReadMemStats(&m1)
|
|
|
|
// Simulate heavy cache usage
|
|
for i := 0; i < iterations; i++ {
|
|
claims := map[string]interface{}{
|
|
"sub": fmt.Sprintf("user%d", i),
|
|
"exp": time.Now().Add(time.Hour).Unix(),
|
|
}
|
|
|
|
// Add to cache
|
|
tc.Set(fmt.Sprintf("token%d", i), claims, time.Hour)
|
|
|
|
// Periodically retrieve
|
|
if i%100 == 0 {
|
|
tc.Get(fmt.Sprintf("token%d", i-50))
|
|
}
|
|
|
|
// Periodically cleanup
|
|
if i%1000 == 0 {
|
|
tc.Cleanup()
|
|
}
|
|
}
|
|
|
|
// Force GC and wait for it to complete
|
|
runtime.GC()
|
|
time.Sleep(100 * time.Millisecond)
|
|
runtime.ReadMemStats(&m2)
|
|
|
|
// Check memory growth (using HeapAlloc for more accurate measurement)
|
|
memoryGrowth := int64(m2.HeapAlloc - m1.HeapAlloc)
|
|
maxAllowedGrowth := int64(2 * 1024 * 1024) // 2MB max growth
|
|
|
|
if memoryGrowth > maxAllowedGrowth {
|
|
t.Logf("Initial HeapAlloc: %d, Final HeapAlloc: %d", m1.HeapAlloc, m2.HeapAlloc)
|
|
t.Errorf("Excessive cache memory growth: %d bytes", memoryGrowth)
|
|
}
|
|
|
|
// Verify cache size stayed within limits
|
|
if len(tc.cache.items) > tc.cache.maxSize {
|
|
t.Errorf("Cache exceeded max size: %d", len(tc.cache.items))
|
|
}
|
|
}
|