Documentation
¶
Overview ¶
Package exectest is the conformance suite every exec.Executor must pass.
The rungs of the isolation ladder are meant to be interchangeable: the same handler, the same payload, and the same declared inputs must behave the same way whether the handler runs in-process or in a pod. One shared table-driven suite is how that stays true, and it is what lets a new rung land without redesigning the ones before it.
Rungs differ in what they can enforce — in-process cannot kill a handler that ignores its deadline — so a rung declares its Capabilities and the suite asserts the enforcement cases only against rungs that claim them.
Index ¶
- Constants
- Variables
- func CheckCapabilities(name string, level exec.Level, caps Capabilities) error
- func HandlerNames() []string
- func Handlers() []job.Registrable
- func RunSuite(t *testing.T, name string, newExecutor func(*testing.T) exec.Executor, ...)
- type Capabilities
- type EchoPayload
- type SlowPayload
Constants ¶
const ( JobOK = "exectest.ok" JobError = "exectest.error" JobPanic = "exectest.panic" JobSlow = "exectest.slow" JobEcho = "exectest.echo" )
Job names the suite installs. Every executor under test must be able to run all of them.
Artifact-carrying fixtures (writing outputs, reading staged inputs) arrive in Phase 2 alongside the suite cases that exercise them. Adding them now would ship handlers no case runs.
Variables ¶
var ErrIntentional = errors.New("intentional failure")
ErrIntentional is what JobError returns, so tests can match it exactly.
Functions ¶
func CheckCapabilities ¶
func CheckCapabilities(name string, level exec.Level, caps Capabilities) error
CheckCapabilities reports whether the capabilities a rung claims are consistent with the isolation it advertises, returning nil when they are.
Without this check Capabilities is an escape hatch: a rung that reports LevelProcess but sets Enforces false skips DeadlineEnforced — the only test proving it can stop a handler that ignores cancellation, which is the property the whole isolation ladder exists to provide — and still passes the suite clean. An executor may run handlers where it cannot kill them, or it may claim LevelProcess; it may not do both.
RunSuite calls this. It is exported so a rung's own tests can assert the same consistency without running the full suite.
func HandlerNames ¶
func HandlerNames() []string
HandlerNames returns the fixture job names, which is what a fingerprint is derived from.
func Handlers ¶
func Handlers() []job.Registrable
Handlers returns the fixture handler set. Registering these is all an executor needs to be run through the suite.
func RunSuite ¶
func RunSuite(t *testing.T, name string, newExecutor func(*testing.T) exec.Executor, caps Capabilities)
RunSuite runs the conformance suite against one executor implementation.
newExecutor is called per subtest so each case gets a clean executor. The returned executor must already have the fixture Handlers registered.
Types ¶
type Capabilities ¶
type Capabilities struct {
// Enforces means the rung can stop a handler that ignores its
// deadline. Only out-of-process rungs can.
Enforces bool
// ReportsUsage means the rung measures CPU time and peak memory
// rather than only wall time.
ReportsUsage bool
// IsolatesPanic means a panicking handler does not take the caller
// down, so the rung reports it as a failed attempt rather than
// relying on the worker's recover middleware.
IsolatesPanic bool
}
Capabilities describes what a rung can actually do, so the suite asserts enforcement only against rungs that provide it.
It describes variation, not an opt-out. RunSuite cross-checks it against the executor's own Level: anything claiming LevelProcess or above must enforce deadlines and isolate panics, and saying otherwise fails the suite rather than skipping the tests that prove it.
type EchoPayload ¶
EchoPayload is the payload JobEcho round-trips. Want, when non-zero, is the byte length the handler asserts Value has, which is how the suite proves a large payload crossed the boundary without truncation.
type SlowPayload ¶
type SlowPayload struct {
SleepMillis int `json:"sleep_millis"`
// IgnoreCtx makes the handler deaf to cancellation entirely, standing
// in for a native library that has stopped honouring it. Only a rung
// that can kill the process will stop this one.
IgnoreCtx bool `json:"ignore_ctx"`
// SwallowCancel only matters when IgnoreCtx is false. A cooperative
// handler normally returns ctx.Err() once its context is done; setting
// this makes it catch that and return nil instead, the shape of a
// handler whose own cleanup swallows context.Canceled. The shim then
// reports StatusOK in its Result frame despite the deadline having
// fired, which is exactly the case that must not fool the executor
// into reporting success — the executor's own timedOut bookkeeping,
// not the frame's contents, has to be what decides the Status.
SwallowCancel bool `json:"swallow_cancel"`
}
SlowPayload controls how long JobSlow sleeps.