Documentation
¶
Overview ¶
Package seamster provides two test-only instrumentation seams that a white-box test uses to exercise a host's recovery and race paths deterministically, without forging state or hammering on timing. Both are inert unless the host constructs the Seamster enabled:
- Fault injection makes a site MISBEHAVE: a test arms a named fault, the host consults it at the exact point it affects, and simulates an error, drop, or stale write that is otherwise hard to trigger on demand.
- Execution checkpoints make a site OBSERVABLE and PAUSABLE: a test rendezvouses with the host's progress (Seamster.Wait) or freezes the host at an exact point (Seamster.Break / Seamster.Resume).
A "seam" is a place where a test can alter or observe behavior without editing the code in place; a Seamster is the object that works a host's seams. The host embeds one Seamster, plants consult sites (Seamster.IsFault / Seamster.Checkpoint) at the points they affect, and names the valid fault/checkpoint set next to those sites so a test cannot arm a fault no site consumes.
Production inertness is by construction: every consult short-circuits on the enabled bool the host passes to New (typically testing.Testing()), so a disabled Seamster pays a single lock-free bool read per site and neither seam can ever fire. The package imports only the standard library, so a host may embed it on a production hot path without dragging in test-only dependencies.
Index ¶
- type Seamster
- func (s *Seamster) Break(checkpointName string)
- func (s *Seamster) Checkpoint(ctx context.Context, checkpointName string)
- func (s *Seamster) Enabled() bool
- func (s *Seamster) Inject(faultName string, scope ...string)
- func (s *Seamster) InjectN(n int, faultName string, scope ...string)
- func (s *Seamster) IsFault(faultName string, scope ...string) bool
- func (s *Seamster) Resume(checkpointName string)
- func (s *Seamster) Visits(checkpointName string) int
- func (s *Seamster) Wait(checkpointName string)
- func (s *Seamster) Withdraw(faultName string, scope ...string)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Seamster ¶
type Seamster struct {
// contains filtered or unexported fields
}
Seamster works one host's instrumentation seams. It is safe for concurrent use. The zero value is a disabled Seamster; construct one with New. A single Seamster is meant to be embedded per host instance (one per engine, one per connector, ...), not shared as a package global, so distinct hosts arm and consult independently.
func New ¶
New returns a Seamster. When enabled is false every consult is inert, so a host passes its own under-test signal - most commonly testing.Testing() - and embeds the result unconditionally.
func (*Seamster) Break ¶
Break arms a breakpoint so the host blocks the next time it reaches the named checkpoint, until Resume releases it.
func (*Seamster) Checkpoint ¶
Checkpoint is the host-side consult at an instrumented site. Free in production (returns on the enabled bool read). When enabled it wakes any Wait(name) waiters and, if a breakpoint is armed for name, blocks until Resume(name) - or until ctx is done, so a stuck test or a shutdown can never wedge the host goroutine forever. Waking waiters and marking the breakpoint hit happen under one lock hold, so a Wait racing the host's arrival is woken or sees hit - never lost between the two.
func (*Seamster) Enabled ¶
Enabled reports whether the seams are live. A host uses it to skip building a scoped consult (a state read, a key concatenation) that would only feed IsFault, so the setup work is also elided in production.
func (*Seamster) Inject ¶
Inject arms the named fault to fire once (additive: calling twice fires twice). Optional scope args target it, joined the same way Seamster.IsFault joins its scope.
func (*Seamster) InjectN ¶
InjectN arms the named fault to fire n more times, added to any current count. Optional scope args target it, joined the same way Seamster.IsFault joins its scope. A non-positive n is a no-op.
func (*Seamster) IsFault ¶
IsFault reports whether the named fault is armed, consuming one fire. It is the only consult entry point and is free in production: it returns on the enabled bool read before any lock or key build. Optional scope args target the fault (a task name, a URL, ...) and are joined into the key, but only once the enabled gate has passed, so a scoped consult on a disabled Seamster allocates no throwaway key. To keep a fault armed for the rest of a test (until Seamster.Withdraw), inject a large count, e.g. s.InjectN(math.MaxInt, name).
func (*Seamster) Resume ¶
Resume releases the host frozen at the named breakpoint and disarms it. A no-op if none is armed.
func (*Seamster) Visits ¶ added in v0.2.0
Visits reports how many times the host has passed the named checkpoint - each Checkpoint(name) call counts one, including a call that then blocked on a breakpoint (reaching the checkpoint is the visit; blocking comes after). It is a passive counter for assertions: it never blocks, consumes nothing, and can be read repeatedly. The count is monotonic for the Seamster's lifetime (never reset), so capture a baseline first if a test asserts on visits accrued only within a window. Zero for a checkpoint never reached, and always zero on a disabled Seamster (Checkpoint counts nothing when inert).