mutate

package
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2026 License: AGPL-3.0, AGPL-3.0-or-later Imports: 21 Imported by: 0

Documentation

Overview

Package mutate implements the test-kills-mutant falsifier described by docs/specs/falsifiable-packet-v0.md. An impact packet row of kind test claims that a test file covers a changed Go file; this package mutates the changed file's top-level declarations, runs the claimed tests against each mutant on an exported copy of the revision, and requires at least one mutant to die. A surviving population falsifies the claim that the test proves anything.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HostSandbox

func HostSandbox() (string, error)

HostSandbox names the sandbox the runner would use on this host, or says why the host cannot run cited tests.

func PassthroughEnvironment

func PassthroughEnvironment(names []string) []string

PassthroughEnvironment copies the named host variables that are set.

Types

type Export

type Export struct {
	// contains filtered or unexported fields
}

Export is one exported revision that judges many claims on one copy. The runner restores the changed file after every mutant, so no claim ever sees another's mutation, and every claim shares the export's build cache.

func Open

func Open(ctx context.Context, request Request) (*Export, error)

Open exports request.Revision once; only Root, Git, Revision, and CacheDir are read. A host without a sandbox opens nothing and every later Judge reports Unsupported. Close removes the copy.

func (*Export) Close

func (exported *Export) Close()

Close removes the exported copy. It is safe to call more than once.

func (*Export) Dir

func (exported *Export) Dir() string

Dir is the directory holding the exported revision. The runner that mutates a file there must restore it after every mutant.

func (*Export) Judge

func (exported *Export) Judge(ctx context.Context, request Request) (Report, error)

Judge falsifies one claim on the exported copy. Root, Git, and Revision may be left empty; when given they must match the export.

func (*Export) JudgeGroup

func (exported *Export) JudgeGroup(ctx context.Context, changed string, lines []LineSpan, tests []string) (map[string]Report, error)

JudgeGroup falsifies every claim that one of tests covers changed, on the exported copy, with one go test per package per mutant instead of one per claim. The mutants depend on changed and lines alone, so each is written once and every package's live claims run together with -json output, from which each claim's own functions decide its verdict exactly as Judge would: a function that fails after building kills, every function passing is a survivor, a package that did not build is uncompilable. A claim is decided at its first kill and leaves later runs; the mutant loop continues while any claim is undecided. A function the package run left without an outcome (the binary died in another test, the output was cut) is re-run alone under its claim's own pattern, so no claim inherits another's crash. Budget: every claim in a run is charged the run's wall time; a claim whose charge reaches the row budget before a run is BUDGET_EXCEEDED at that mutant; a package run's go test timeout is the per-run share times the claims in it, capped at the row budget, so a group is never slower per test than a claim alone. Reports are keyed by test path; a repeated path is judged once.

func (*Export) Run

func (exported *Export) Run(ctx context.Context, timeout time.Duration, dir string, environment []string, argv ...string) (string, bool, error)

Run executes argv inside the host sandbox from dir with exactly environment, after emptying the scratch directory, and kills the run's process group afterwards whatever happened. It reports the bounded combined output, whether the per-run timeout (not the caller's context) ended the run, and the command's error.

func (*Export) Scratch

func (exported *Export) Scratch() string

Scratch is the one directory the sandbox lets a run write, emptied before every Run; a sibling runner points the interpreter's temporary files at it.

func (*Export) Unsandboxed

func (exported *Export) Unsandboxed() string

Unsandboxed is non-empty when the host has no sandbox, and says why; a sibling runner reports Unsupported with it and runs nothing.

type LineSpan

type LineSpan struct {
	Start, End int
}

LineSpan is one inclusive 1-based line range of the changed file.

type Report

type Report struct {
	Verdict  Verdict
	Mutants  int
	Killed   int
	Survived int
	// Uncompilable counts mutants that never built, which are neither killed
	// nor survivors: the test was never asked about them.
	Uncompilable int
	Skipped      int
	Operators    []string
	Elapsed      time.Duration
	Detail       string
	// Witness identifies the first behavioural kill when the runner could
	// attribute it to one named test. It is nil for every non-kill and for an
	// unattributed package failure.
	Witness *Witness
	// Survivors lists every mutant that built and passed the tests, in plan
	// order; it is complete only for a Complete run.
	Survivors []Survivor
}

Report is the falsifier's answer. Detail is one deterministic human-readable line: it carries no timings and no temporary paths.

func Run

func Run(ctx context.Context, request Request) (Report, error)

Run exports Revision, establishes a baseline, and runs the generated mutants against the tests declared in TestPath: one claim on one copy.

type Request

type Request struct {
	Root        string
	Git         string
	Revision    string
	ChangedPath string
	TestPath    string
	// Lines, when set, confines mutation to sites whose line falls inside
	// one of the spans (1-based, inclusive), so a claim about a change is
	// judged on the change and not on the rest of the file.
	Lines      []LineSpan
	MaxMutants int
	Budget     time.Duration
	// Complete runs every mutant instead of stopping at the first kill.
	Complete bool
	// CacheDir, when set, is the absolute GOCACHE every run in this request
	// writes. Callers share it across requests of one invocation and remove
	// it; it must never be the host's own build cache.
	CacheDir string
}

Request names one claim to falsify. Root is never modified: all work happens on an export of Revision under the system temporary directory.

type Survivor added in v0.7.0

type Survivor struct {
	Operator string
	Line     int
	Start    int
	End      int
}

Survivor is one mutant the tests let live: its operator, the 1-based line of the changed file it was applied at, and its zero-based, end-exclusive byte span in the original changed-file blob.

type Verdict

type Verdict string

Verdict is the falsifier's judgement about the claim. Every judgement about the code under test travels here; error is reserved for caller mistakes and infrastructure failure.

const (
	// Killed reports that at least one mutant died: the falsifier passes.
	Killed Verdict = "KILLED"
	// Survived reports that every mutant lived: the falsifier fails.
	Survived Verdict = "SURVIVED"
	// NoMutants reports that the changed file held nothing mutable.
	NoMutants Verdict = "NO_MUTANTS"
	// BudgetExceeded reports that time ran out before any mutant was killed.
	BudgetExceeded Verdict = "BUDGET_EXCEEDED"
	// Unsupported reports that the claim could not be judged at all.
	Unsupported Verdict = "UNSUPPORTED"
)

type Witness

type Witness struct {
	Operator    string
	Start       int
	End         int
	KillingTest string
}

Witness is the replayable part of one killed mutant. Start and End are a zero-based, end-exclusive byte span in the original changed-file blob.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL