mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-12 04:04:26 +00:00
- fail-on-old regression tests for every shipped fix (R-rounds) - fuzz targets (parseJWT, bearer), concurrency-stress, shuffle-flake guards - coverage-closing contract tests (health-check backend, TLS-posture reuse) - r154 ID-token fixture built from parts to avoid false-positive secret scan
64 lines
2.0 KiB
Go
64 lines
2.0 KiB
Go
package traefikoidc
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// ============================================================================
|
|
// R189: the global health-check pass is single-threaded
|
|
// ---------------------------------------------------------------------------
|
|
// globalPerformHealthChecks runs from more than one goroutine — the shared
|
|
// singleton task's run loop AND the once-guarded StartBackgroundTask path —
|
|
// so a health check registered via the public RegisterHealthCheck API could
|
|
// be invoked concurrently (a latent production race, and the source of an
|
|
// intermittent full-suite race once tests register a health check that
|
|
// mutates a captured value). The global pass is now serialized.
|
|
// Fail-on-old: a slow health check, invoked from many goroutines at once,
|
|
// sees concurrent (overlapping) invocations.
|
|
func TestR189_GlobalHealthCheckPassIsSerialized(t *testing.T) {
|
|
logger := GetSingletonNoOpLogger()
|
|
config := DefaultGracefulDegradationConfig()
|
|
|
|
gd := NewGracefulDegradation(config, logger)
|
|
defer gd.Close()
|
|
|
|
var active, maxActive int64
|
|
gd.RegisterHealthCheck("svc", func() bool {
|
|
cur := atomic.AddInt64(&active, 1)
|
|
// Record peak concurrency.
|
|
for {
|
|
m := atomic.LoadInt64(&maxActive)
|
|
if cur <= m || atomic.CompareAndSwapInt64(&maxActive, m, cur) {
|
|
break
|
|
}
|
|
}
|
|
// Widen the window so an unsynchronized implementation overlaps.
|
|
time.Sleep(2 * time.Millisecond)
|
|
atomic.AddInt64(&active, -1)
|
|
return true
|
|
})
|
|
|
|
// Ensure the instance is visible to the global pass regardless of the
|
|
// async startHealthCheckRoutine registration timing.
|
|
gdInstances.Lock()
|
|
gdInstances.set[gd] = struct{}{}
|
|
gdInstances.Unlock()
|
|
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 8; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
globalPerformHealthChecks()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
if got := atomic.LoadInt64(&maxActive); got != 1 {
|
|
t.Fatalf("health check ran with peak concurrency %d; want 1 (global pass must be serialized)", got)
|
|
}
|
|
}
|