Files
go-simple-graphql/performance_regression_test.go

159 lines
4.4 KiB
Go

package gql
import (
"testing"
"time"
cache "github.com/lukaszraczylo/go-simple-graphql/cache"
)
// Performance regression tests to ensure optimizations maintain their benefits
func TestPerformanceRegression(t *testing.T) {
// Test hash performance
t.Run("HashPerformance", func(t *testing.T) {
query := &Query{
Query: "query GetUser($id: ID!) { user(id: $id) { id name email } }",
Variables: map[string]interface{}{
"id": "12345",
},
JsonQuery: []byte(`{"query":"query GetUser($id: ID!) { user(id: $id) { id name email } }","variables":{"id":"12345"}}`),
}
start := time.Now()
for i := 0; i < 10000; i++ {
_ = calculateHash(query)
}
duration := time.Since(start)
// Should complete 10k hashes in under 40ms (accounts for race detection + coverage overhead)
if duration > 40*time.Millisecond {
t.Errorf("Hash performance regression: 10k hashes took %v, expected < 40ms", duration)
}
})
// Test buffer pool performance
t.Run("BufferPoolPerformance", func(t *testing.T) {
start := time.Now()
for i := 0; i < 10000; i++ {
buf := getBuffer(1024)
buf.WriteString("test data")
putBuffer(buf)
}
duration := time.Since(start)
// Should complete 10k buffer operations in under 30ms (accounts for race detection + coverage overhead)
if duration > 30*time.Millisecond {
t.Errorf("Buffer pool performance regression: 10k operations took %v, expected < 30ms", duration)
}
})
// Test cache performance
t.Run("CachePerformance", func(t *testing.T) {
c := cache.New(5 * time.Second) // Use shorter TTL for tests
defer c.Stop()
testData := make([]byte, 512) // Small data that won't be compressed
for i := range testData {
testData[i] = byte(i % 256)
}
start := time.Now()
for i := 0; i < 10000; i++ {
key := "key" + string(rune(i%100))
c.Set(key, testData, time.Minute)
_, _ = c.Get(key)
}
duration := time.Since(start)
// Should complete 10k cache operations in under 50ms
if duration > 50*time.Millisecond {
t.Errorf("Cache performance regression: 10k operations took %v, expected < 50ms", duration)
}
})
// Test processFlags performance
t.Run("ProcessFlagsPerformance", func(t *testing.T) {
variables := map[string]interface{}{
"id": "123",
"gqlcache": true,
"gqlretries": true,
}
headers := map[string]interface{}{}
start := time.Now()
for i := 0; i < 10000; i++ {
_, _, _ = processFlags(variables, headers)
}
duration := time.Since(start)
// Should complete 10k flag processing operations in under 30ms (accounts for race detection + coverage overhead)
if duration > 30*time.Millisecond {
t.Errorf("ProcessFlags performance regression: 10k operations took %v, expected < 30ms", duration)
}
})
// Test query compilation performance
t.Run("QueryCompilationPerformance", func(t *testing.T) {
client := CreateTestClient()
query := "query GetUser($id: ID!) { user(id: $id) { id name email } }"
variables := map[string]interface{}{"id": "123"}
start := time.Now()
for i := 0; i < 1000; i++ {
_ = client.compileQuery(query, variables)
}
duration := time.Since(start)
// Should complete 1k query compilations in under 65ms (accounts for minification overhead)
if duration > 65*time.Millisecond {
t.Errorf("Query compilation performance regression: 1k operations took %v, expected < 65ms", duration)
}
})
}
// Benchmark comprehensive workflow to ensure no regression
func BenchmarkComprehensiveWorkflow(b *testing.B) {
client := CreateTestClient()
query := "query GetUser($id: ID!) { user(id: $id) { id name email profile { avatar bio } } }"
variables := map[string]interface{}{
"id": "123",
"gqlcache": true,
"gqlretries": true,
}
headers := map[string]interface{}{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Process flags
enableCache, enableRetries, cleanedVariables := processFlags(variables, headers)
// Compile query
compiledQuery := client.compileQuery(query, cleanedVariables)
// Calculate hash
if enableCache {
_ = calculateHash(compiledQuery)
}
// Use variables to avoid optimization
_ = enableRetries
}
}
// Memory allocation benchmark
func BenchmarkMemoryAllocations(b *testing.B) {
client := CreateTestClient()
query := "query GetUser($id: ID!) { user(id: $id) { id name } }"
variables := map[string]interface{}{"id": "123"}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
compiledQuery := client.compileQuery(query, variables)
_ = calculateHash(compiledQuery)
}
}