Documentation
¶
Overview ¶
Package wait provides polling helpers for tests that cannot import the top-level testutil package due to import cycles with the session package.
Index ¶
- Variables
- func LoadFactor() float64
- func RequireEventually(t testing.TB, condition func() bool, baseTimeout, tick time.Duration, ...)
- func ScaleTimeout(base time.Duration) time.Duration
- func WaitForCondition(condition func() bool, config WaitConfig) error
- func WaitForConditionWithError(condition func() (bool, error), config WaitConfig) error
- type WaitConfig
Constants ¶
This section is empty.
Variables ¶
var ( FastTimeout = 2 * time.Second // For unit tests and quick operations DefaultTimeout = 10 * time.Second // For most integration tests SlowTimeout = 30 * time.Second // For complex operations (file I/O, network) )
Common timeout durations for different test scenarios.
Functions ¶
func LoadFactor ¶ added in v1.54.0
func LoadFactor() float64
LoadFactor returns a multiplier for scaling test wait timeouts to current system load: 1.0 when the machine has full headroom (1-minute load average per core at or below 1), rising linearly with load average per core above that, capped at maxLoadFactor. Returns 1.0 -- never shrinks a timeout below what the test author chose -- if load average can't be read on this platform, so a read failure fails open rather than tightening a bound.
This exists because a fixed wall-clock require.Eventually/WaitForCondition bound assumes the goroutines it's waiting on get scheduled promptly. That assumption breaks on a machine running other CPU-heavy work concurrently (a live production instance of this same service, another test run, a loaded CI runner) -- see BUG-103 and docs/explanation/test-io-storage-isolation.md.
func RequireEventually ¶ added in v1.54.0
func RequireEventually(t testing.TB, condition func() bool, baseTimeout, tick time.Duration, msgAndArgs ...any)
RequireEventually polls condition until it returns true, failing t via t.Fatalf if it never does within baseTimeout scaled by ScaleTimeout. Drop-in-shaped replacement for testify's require.Eventually(t, condition, timeout, tick, msgAndArgs...), differing only in that timeout is a base value stretched to current machine load rather than a literal bound.
Unlike require.Eventually, a timeout here logs via t.Logf partway through (at roughly the halfway point) so a long-running CI/local log shows a "still waiting" line distinguishing an in-progress, load-slowed wait from a silently hung one before the final failure -- see LoadFactor's doc comment for the underlying motivation (BUG-103).
func ScaleTimeout ¶ added in v1.54.0
ScaleTimeout multiplies base by the current LoadFactor and any explicit STAPLER_SQUAD_TEST_TIMEOUT_SCALE override. Use this wherever a test would otherwise hardcode a wall-clock wait bound.
func WaitForCondition ¶
func WaitForCondition(condition func() bool, config WaitConfig) error
WaitForCondition polls a condition until it returns true or timeout occurs. config.Timeout is scaled by ScaleTimeout before use, so the effective bound stretches under real machine load instead of assuming an idle CPU.
func WaitForConditionWithError ¶
func WaitForConditionWithError(condition func() (bool, error), config WaitConfig) error
WaitForConditionWithError polls a condition that can return an error. config.Timeout is scaled by ScaleTimeout before use, so the effective bound stretches under real machine load instead of assuming an idle CPU.
Types ¶
type WaitConfig ¶
type WaitConfig struct {
Timeout time.Duration
PollInterval time.Duration
Description string // For better error messages
}
WaitConfig allows customizing wait behaviour.
func DefaultWaitConfig ¶
func DefaultWaitConfig() WaitConfig
DefaultWaitConfig provides sensible defaults.