Mutare.Selector (mutare v0.1.0)

Copy Markdown View Source

Runtime selection of the active mutant.

The active mutant is constant for an entire suite run, so it is read once from the environment at boot and stashed in :persistent_term (O(1) reads, built for write-once/read-many). Every selector site in the metamutant reads this key on each execution.

This module owns both sides of that contract: Mutare.Metamutant uses its key and baseline when building selectors, while Mutare.Sandbox renders bootstrap_ast/0 into the target project's dependency-free test bootstrap.

Self-hosting: a private key for the suite-under-test

When the target is Mutare, the suite-under-test contains Mutare's own tests, many of which drive selection directly (put/1, building fixtures via Mutare.Transform) to exercise the machinery. If those tests wrote the same :persistent_term slot the harness uses to hold the mutant-under-test, they would clobber it mid-run — the active mutant would silently revert to baseline and every mutant whose killing test ran afterwards would register a false survivor (see NOTES.md, "Self-hosting").

So the runtime key is configurable: key/0 returns default_key/0 (:mutare_active, the harness key) unless override_env/0 names another, in which case the suite plays in that private slot. Mutare.Sandbox.Command sets that env var (to suite_key/0) on every sandbox mix it spawns, so the suite-under-test reads/writes :mutare_active__suite while the real metamutant — whose sites and bootstrap bake default_key/0 as literals at transform time, in the harness process where the override is unset — keeps reading :mutare_active. The two never collide. On a normal target there is no Mutare.Selector compiled in, so the env is inert.

Summary

Functions

The active mutant id for in-process execution (0 if unset).

The baseline id (no mutant active).

Dependency-free code that reads the selector environment variable and stores the active mutant id.

The harness selection key (:mutare_active) — the default key/0, env-independent.

The environment variable a runner sets to pick the active mutant.

The :persistent_term key the metamutant reads at runtime.

Env var a sandbox run sets to give the suite-under-test a private selection key.

Set the active mutant id directly for in-process execution.

The private key (override_env/0's value) the suite-under-test selects on under dogfooding.

Functions

active()

@spec active() :: non_neg_integer()

The active mutant id for in-process execution (0 if unset).

baseline()

@spec baseline() :: non_neg_integer()

The baseline id (no mutant active).

bootstrap_ast()

@spec bootstrap_ast() :: Macro.t()

Dependency-free code that reads the selector environment variable and stores the active mutant id.

Mutare.Sandbox renders this AST directly into the target project's test bootstrap, so the target does not need Mutare as a dependency.

default_key()

@spec default_key() :: atom()

The harness selection key (:mutare_active) — the default key/0, env-independent.

env_var()

@spec env_var() :: String.t()

The environment variable a runner sets to pick the active mutant.

key()

@spec key() :: atom()

The :persistent_term key the metamutant reads at runtime.

default_key/0 (:mutare_active) unless override_env/0 names another — the one knob self-hosting needs so the suite-under-test does not clobber the harness's active-mutant slot (see the moduledoc).

override_env()

@spec override_env() :: String.t()

Env var a sandbox run sets to give the suite-under-test a private selection key.

put(id)

@spec put(non_neg_integer()) :: :ok

Set the active mutant id directly for in-process execution.

suite_key()

@spec suite_key() :: String.t()

The private key (override_env/0's value) the suite-under-test selects on under dogfooding.