124 lines
4.9 KiB
Go
124 lines
4.9 KiB
Go
package config
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCredentialConcurrencyLimiterConfig(t *testing.T) {
|
|
got := (CredentialConcurrencyConfig{}).WithDefaults()
|
|
if got.LifecycleConfigRevision != 0 || got.ObservationBarrierRevision != 0 {
|
|
t.Fatalf("default revisions = %d, %d, want 0, 0", got.LifecycleConfigRevision, got.ObservationBarrierRevision)
|
|
}
|
|
if got.CPAHeartbeatTimeout != 3*time.Second || got.CPACancelBound != 5*time.Second || got.ReclaimGrace != 5*time.Second || got.CleanupInterval != 5*time.Second {
|
|
t.Fatalf("default lifecycle config = %#v", got)
|
|
}
|
|
if got.ReleaseFlushInterval != 250*time.Millisecond || got.ReleaseMaxBackoff != 2*time.Second || got.BusyRetryMin != 250*time.Millisecond || got.BusyRetryMax != time.Second || got.MaxLimit != 1_000_000 {
|
|
t.Fatalf("default limiter config = %#v", got)
|
|
}
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(20*time.Second, got); errValidate != nil {
|
|
t.Fatalf("ValidateCredentialConcurrencyLifecycle() error = %v", errValidate)
|
|
}
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(2*time.Second, got); errValidate == nil {
|
|
t.Fatal("ValidateCredentialConcurrencyLifecycle() error = nil, want timing invariant failure")
|
|
}
|
|
}
|
|
|
|
func TestValidateCredentialConcurrencyAcceptsHomeAuthoritativeHeartbeat(t *testing.T) {
|
|
cfg := (CredentialConcurrencyConfig{}).WithDefaults()
|
|
cfg.CPAHeartbeatTimeout = 20 * time.Second
|
|
|
|
if errValidate := ValidateCredentialConcurrency(cfg); errValidate != nil {
|
|
t.Fatalf("ValidateCredentialConcurrency() error = %v", errValidate)
|
|
}
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(20*time.Second, cfg); errValidate == nil {
|
|
t.Fatal("ValidateCredentialConcurrencyLifecycle() error = nil, want Home timing invariant failure")
|
|
}
|
|
}
|
|
|
|
func TestCredentialConcurrencyConfigDefaultsOnlyMissingFields(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
payload string
|
|
}{
|
|
{
|
|
name: "explicit zero revision",
|
|
payload: "credential-concurrency:\n" +
|
|
" lifecycle-config-revision: 0\n" +
|
|
" cpa-heartbeat-timeout: 3s\n" +
|
|
" cpa-cancel-bound: 5s\n" +
|
|
" reclaim-grace: 5s\n" +
|
|
" cleanup-interval: 5s\n",
|
|
},
|
|
{
|
|
name: "explicit zero duration",
|
|
payload: "credential-concurrency:\n" +
|
|
" lifecycle-config-revision: 1\n" +
|
|
" cpa-heartbeat-timeout: 0s\n" +
|
|
" cpa-cancel-bound: 5s\n" +
|
|
" reclaim-grace: 5s\n" +
|
|
" cleanup-interval: 5s\n",
|
|
},
|
|
{
|
|
name: "explicit null duration",
|
|
payload: "credential-concurrency:\n" +
|
|
" lifecycle-config-revision: 1\n" +
|
|
" cpa-heartbeat-timeout: null\n" +
|
|
" cpa-cancel-bound: 5s\n" +
|
|
" reclaim-grace: 5s\n" +
|
|
" cleanup-interval: 5s\n",
|
|
},
|
|
{
|
|
name: "negative observation barrier",
|
|
payload: "credential-concurrency:\n" +
|
|
" lifecycle-config-revision: 1\n" +
|
|
" observation-barrier-revision: -1\n" +
|
|
" cpa-heartbeat-timeout: 3s\n" +
|
|
" cpa-cancel-bound: 5s\n" +
|
|
" reclaim-grace: 5s\n" +
|
|
" cleanup-interval: 5s\n",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
parsed, errParse := ParseConfigBytes([]byte(test.payload))
|
|
if errParse != nil {
|
|
t.Fatalf("ParseConfigBytes() error = %v", errParse)
|
|
}
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(20*time.Second, parsed.CredentialConcurrency); errValidate == nil {
|
|
t.Fatal("ValidateCredentialConcurrencyLifecycle() error = nil, want explicit invalid lifecycle value rejection")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCredentialConcurrencyConfigRejectsInvalidLimiter(t *testing.T) {
|
|
tests := []CredentialConcurrencyConfig{
|
|
{ReleaseFlushInterval: time.Second, ReleaseMaxBackoff: 500 * time.Millisecond, BusyRetryMin: time.Millisecond, BusyRetryMax: time.Millisecond, MaxLimit: 1},
|
|
{ReleaseFlushInterval: time.Millisecond, ReleaseMaxBackoff: time.Millisecond, BusyRetryMin: 1500 * time.Microsecond, BusyRetryMax: 2 * time.Millisecond, MaxLimit: 1},
|
|
{ReleaseFlushInterval: time.Millisecond, ReleaseMaxBackoff: time.Millisecond, BusyRetryMin: time.Millisecond, BusyRetryMax: time.Millisecond, MaxLimit: 1_000_001},
|
|
}
|
|
for _, cfg := range tests {
|
|
cfg.CPAHeartbeatTimeout = 3 * time.Second
|
|
cfg.CPACancelBound = 5 * time.Second
|
|
cfg.ReclaimGrace = 5 * time.Second
|
|
cfg.CleanupInterval = 5 * time.Second
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(20*time.Second, cfg); errValidate == nil {
|
|
t.Fatalf("ValidateCredentialConcurrencyLifecycle(%#v) error = nil", cfg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateCredentialConcurrencyLifecycleRejectsSafetyOverflow(t *testing.T) {
|
|
cfg := CredentialConcurrencyConfig{
|
|
LifecycleConfigRevision: 1,
|
|
CPAHeartbeatTimeout: time.Duration(1<<63 - 1),
|
|
CPACancelBound: time.Nanosecond,
|
|
ReclaimGrace: time.Second,
|
|
CleanupInterval: time.Second,
|
|
}
|
|
if errValidate := ValidateCredentialConcurrencyLifecycle(time.Second, cfg); errValidate == nil {
|
|
t.Fatal("ValidateCredentialConcurrencyLifecycle() error = nil, want overflow rejection")
|
|
}
|
|
}
|