Files
traefikoidc/session_bench_test.go
T
lukaszraczylo c474bbafd6 Cleanup [dec2025] (#101)
* Cleanup excessive comments.

* Remove leftovers hanging around from previous refactor

* Improve test coverage
2025-12-09 01:38:02 +00:00

199 lines
5.4 KiB
Go

package traefikoidc
import (
"crypto/rand"
"encoding/base64"
"net/http/httptest"
"strings"
"sync/atomic"
"testing"
)
// BenchmarkSessionCreation benchmarks session creation operations
func BenchmarkSessionCreation(b *testing.B) {
framework := &SessionTestFramework{
metrics: &SessionTestMetrics{},
testTokens: make(map[string]string),
config: &SessionTestConfig{
MaxChunkSize: 3900,
MaxSessions: 1000,
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
atomic.AddInt64(&framework.metrics.SessionsCreated, 1)
atomic.AddInt64(&framework.metrics.SessionsDestroyed, 1)
}
b.ReportMetric(float64(framework.metrics.SessionsCreated)/float64(b.N), "sessions/op")
}
// BenchmarkTokenGeneration benchmarks token generation operations
func BenchmarkTokenGeneration(b *testing.B) {
framework := NewSessionTestFramework(&testing.T{})
defer framework.Cleanup()
b.ResetTimer()
for i := 0; i < b.N; i++ {
framework.generateTestToken("access", 3600)
}
b.ReportMetric(float64(framework.metrics.TokensGenerated)/float64(b.N), "tokens/op")
}
// BenchmarkTokenValidation benchmarks token validation operations
func BenchmarkTokenValidation(b *testing.B) {
framework := NewSessionTestFramework(&testing.T{})
defer framework.Cleanup()
token := framework.generateTestToken("access", 3600)
b.ResetTimer()
for i := 0; i < b.N; i++ {
parts := strings.Split(token, ".")
if len(parts) == 3 {
atomic.AddInt64(&framework.metrics.TokensValidated, 1)
}
}
b.ReportMetric(float64(framework.metrics.TokensValidated)/float64(b.N), "validations/op")
}
// BenchmarkLargeTokenChunking benchmarks large token chunking operations
func BenchmarkLargeTokenChunking(b *testing.B) {
framework := &SessionTestFramework{
metrics: &SessionTestMetrics{},
testTokens: make(map[string]string),
config: &SessionTestConfig{
MaxChunkSize: 3900,
},
}
// Generate test token once
largeToken := strings.Repeat("A", 10000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
chunks := make([]string, 0)
for j := 0; j < len(largeToken); j += framework.config.MaxChunkSize {
end := j + framework.config.MaxChunkSize
if end > len(largeToken) {
end = len(largeToken)
}
chunks = append(chunks, largeToken[j:end])
atomic.AddInt64(&framework.metrics.ChunksCreated, 1)
}
// Reconstruct
_ = strings.Join(chunks, "")
atomic.AddInt64(&framework.metrics.ChunksRetrieved, int64(len(chunks)))
}
b.ReportMetric(float64(framework.metrics.ChunksCreated)/float64(b.N), "chunks_created/op")
b.ReportMetric(float64(framework.metrics.ChunksRetrieved)/float64(b.N), "chunks_retrieved/op")
}
// BenchmarkConcurrentSessionOperations benchmarks concurrent session operations
func BenchmarkConcurrentSessionOperations(b *testing.B) {
framework := &SessionTestFramework{
metrics: &SessionTestMetrics{},
testTokens: make(map[string]string),
sessionIDs: make([]string, 0),
config: &SessionTestConfig{
MaxSessions: 10000,
},
}
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Create session
atomic.AddInt64(&framework.metrics.SessionsCreated, 1)
// Generate token
token := make([]byte, 32)
rand.Read(token)
tokenStr := base64.RawURLEncoding.EncodeToString(token)
atomic.AddInt64(&framework.metrics.TokensGenerated, 1)
// Validate token
if len(tokenStr) > 0 {
atomic.AddInt64(&framework.metrics.TokensValidated, 1)
}
// Destroy session
atomic.AddInt64(&framework.metrics.SessionsDestroyed, 1)
}
})
b.ReportMetric(float64(framework.metrics.SessionsCreated)/float64(b.N), "sessions/op")
b.ReportMetric(float64(framework.metrics.TokensGenerated)/float64(b.N), "tokens/op")
}
// BenchmarkSessionOperations provides performance benchmarks for session operations
func BenchmarkSessionOperations(b *testing.B) {
testTokens := NewTestTokens()
perfHelper := NewPerformanceTestHelper()
logger := NewLogger("error") // Reduce logging for benchmarks
sm, err := NewSessionManager("0123456789abcdef0123456789abcdef0123456789abcdef", false, "", "", 0, logger)
if err != nil {
b.Fatalf("Failed to create session manager: %v", err)
}
b.Run("GetSession", func(b *testing.B) {
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
session, err := sm.GetSession(req)
if err != nil {
b.Fatalf("GetSession failed: %v", err)
}
session.ReturnToPool()
}
})
b.Run("SetAccessToken", func(b *testing.B) {
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
session, _ := sm.GetSession(req)
token := testTokens.GetValidTokenSet().AccessToken
b.ResetTimer()
for i := 0; i < b.N; i++ {
perfHelper.Measure(func() {
session.SetAccessToken(token)
})
}
session.ReturnToPool()
b.Logf("Average SetAccessToken time: %v", perfHelper.GetAverageTime())
})
b.Run("GetAccessToken", func(b *testing.B) {
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
session, _ := sm.GetSession(req)
session.SetAccessToken(testTokens.GetValidTokenSet().AccessToken)
b.ResetTimer()
for i := 0; i < b.N; i++ {
perfHelper.Measure(func() {
_ = session.GetAccessToken()
})
}
session.ReturnToPool()
b.Logf("Average GetAccessToken time: %v", perfHelper.GetAverageTime())
})
b.Run("TokenCompression", func(b *testing.B) {
largeToken := testTokens.CreateLargeValidJWT(5000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
compressed := compressToken(largeToken)
_ = decompressToken(compressed)
}
})
}