guardmut

package
v0.71.2 Latest Latest
Warning

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

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package guardmut finds the conditional guards in a Go source file and rewrites them so they can never fire, or always fire.

It exists because of a failure this repository kept repeating: a test that names a guard, passes, and proves nothing, because the fixture it uses satisfies TWO refusal conditions at once, so removing either one alone leaves the test green. Seven such tests were found by hand across one review cycle. No static check can see it: whether a fixture reaches a particular branch is a runtime property. Breaking the guard and re-running the tests is the only detector, so this package makes that mechanical.

The rewrite is deliberately an ANNOTATION of the original expression rather than a replacement of it:

if cond {          →  if (cond) && false {     // guard never fires
if cond {          →  if (cond) || true {      // guard always fires

Every identifier in the condition is still referenced, so no local goes unused and no import is orphaned; the mutated file compiles whenever the original did. Hand-written mutations failed this way twice during the review that motivated this tool, and a mutation that fails to compile (or fails to apply) is indistinguishable from one the tests did not catch: both end the run without a test failure.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(src []byte, g Guard) ([]byte, error)

Apply returns src with g's condition rewritten. The result is guaranteed to differ from src; callers should verify that, because a mutation that did not land looks exactly like one the tests failed to catch.

Types

type Guard

type Guard struct {
	File string
	Line int
	Kind Kind
	Cond string // the condition's source text, for the report
	// contains filtered or unexported fields
}

Guard is one mutable condition in a source file.

func Find

func Find(file string, src []byte, opts Options) ([]Guard, error)

Find returns every mutable guard in src, both directions, in source order.

func (Guard) String

func (g Guard) String() string

String identifies a guard in output.

type Kind

type Kind string

Kind is the direction a guard is broken in.

const (
	// Never makes the condition false: the guard stops refusing. A surviving
	// Never mutant means no test proves the guard refuses anything.
	Never Kind = "never"
	// Always makes the condition true: the guard refuses everything. A
	// surviving Always mutant means no test proves the guard PERMITS
	// anything, the missing allow-arm that lets a too-tight gate ship.
	Always Kind = "always"
)

type Options

type Options struct {
	// SkipErrNil drops `if err != nil` conditions. Error plumbing is guarded
	// almost everywhere and tested almost nowhere, so including it buries the
	// interesting survivors under hundreds of expected ones. Off by default
	// in the CLI; set false to audit error paths deliberately.
	SkipErrNil bool
}

Options tunes which guards are collected.

Jump to

Keyboard shortcuts

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