Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Loop ¶
func Loop(ctx context.Context, opts LoopOptions) error
Loop is the watch session: one cycle per batch, until the channel closes or the context ends.
Failures are sticky, and the accounting is per test name, not per package: a cycle that runs only a subset of a package's tests can clear exactly the names it executed and nothing more. A run that never executed the broken test — because narrowing selected different tests — cannot silently declare the package healthy, and an infrastructure error keeps the entry rather than evicting it: the one failure the mechanism must never drop is the one it could not re-check.
Types ¶
type Batch ¶
Batch is one debounced set of saves. Resync means the paths are unreliable — events were dropped — and the whole dirty tree must be reconsidered from scratch.
type BinaryCache ¶
type BinaryCache struct {
// contains filtered or unexported fields
}
BinaryCache keeps one pre-linked test binary per package for the life of a watch session.
The savings this buys is the whole point of watch mode: `go test` pays flag parsing, cache probing and a relink on every invocation — around a second even when nothing changed — while a warm binary starts in milliseconds. Staleness is decided by the same fingerprint the index uses, computed over the working tree's content digests, so a binary survives exactly as long as its package's dependency closure is byte-identical.
func NewBinaryCache ¶
func NewBinaryCache() (*BinaryCache, error)
func (*BinaryCache) Close ¶
func (c *BinaryCache) Close()
func (*BinaryCache) Ensure ¶
func (c *BinaryCache) Ensure(ctx context.Context, req BuildRequest) (string, bool, error)
Ensure returns a runnable test binary for the package, building one only when the cached binary's fingerprint no longer matches the working tree. The empty path with a nil error means the package has no test binary at all.
type BuildRequest ¶
type Cycle ¶
type Cycle struct {
Runs []PlannedRun
Deferred int
Narrowed bool
Note string
}
Cycle is everything one save resolved to.
type LoopOptions ¶
type LoopOptions struct {
Planner *Planner
Binaries *BinaryCache
Batches <-chan Batch
Out io.Writer
UseColor bool
Jobs int
Timeout time.Duration
// Journal receives every attributable verdict the session produces. The
// sticky mechanism makes watch a natural flake detector: a failure re-runs
// on later cycles, and when the package's fingerprint has not moved, a pass
// on the re-run is a verdict change with no code change. Nil records
// nothing.
Journal *flake.Journal
// Quarantine labels failures of tests already known to be flaky, so a red
// cycle says "possibly not your change" where that is the documented truth.
Quarantine *flake.Quarantine
}
type PlannedRun ¶
type PlannedRun struct {
ImportPath string
Dir string
// Pattern selects the tests to run; empty means the whole package.
Pattern string
Tests []string
Reason string
// Fingerprint keys the warm binary for this package.
Fingerprint cache.Fingerprint
}
PlannedRun is one package's execution order for a cycle.
type Planner ¶
type Planner struct {
Root string
Tags []string
Env []string
Store *cache.Store
// NoIndex disables line-level narrowing, mirroring the global --no-index
// flag: plans stay at package precision even when an index exists.
NoIndex bool
// contains filtered or unexported fields
}
Planner turns "these files were just saved" into "run exactly these tests".
It reuses the whole selection pipeline — the same graph, the same narrowing, the same fail-safe rules — so watch mode can never skip a test that a CI run of `assay run` would have executed for the same dirty tree. What it adds is the delta: of everything the dirty tree affects, only the packages reachable from this save are run now.
func (*Planner) Invalidate ¶
func (p *Planner) Invalidate()
Invalidate drops every piece of memoised state. Called when filesystem events were lost: a graph whose inputs may have changed unseen cannot be trusted to stay memoised.
type RunRequest ¶
type RunResult ¶
type RunResult struct {
ImportPath string
Tests []string
// Fingerprint is the package content state this result was observed at,
// which is the identity flake evidence is keyed by.
Fingerprint cache.Fingerprint
Passed bool
Skipped bool
Output []byte
Duration time.Duration
Reused bool
Err error
}
RunResult is one package's test execution within a cycle. Skipped means no test binary exists — a package whose tests are all behind a build tag — which is a different claim from "ran and passed" and must never be counted as one.
type Watcher ¶
type Watcher struct {
// contains filtered or unexported fields
}
Watcher turns raw filesystem events into debounced batches of relevant paths.
Editors are noisy — atomic-save temp files, backup files, a write event per chunk — so events are filtered to files that can change what runs (.go and module files) and collected until the tree has been quiet for the debounce window, or until a continuous writer has stretched the wait to its cap.
A batch send never blocks the event pump: if the consumer is mid-cycle and the channel is full, the paths stay in pending and ride out with the next flush. Overflow is the one event that cannot be papered over — the kernel dropped an unknown number of changes — so it surfaces as a resync batch (nil paths), which the planner treats as "run the whole dirty plan" and the loop treats as "drop the memoised graph".