Skip to content

Running campaigns

fuzztla run --how=TECHNIQUE [--corpus=DIR] [--seed=SEED] [--max-cpus=N]
Option Meaning
--how=pbt Property-based testing: generate random modules, compare the checkers, and mutate good inputs (Generations and mutation).
--how=mt Metamorphic testing: check one checker against equivalent rewrites of its input (Metamorphic testing).
--how=gbt Graph-based testing: check each checker against the verdict that a generated control graph predicts (Graph-based testing).
--corpus=DIR The corpus directory. Default: corpus.
--seed=SEED A nonnegative seed. A random seed is used when it is omitted. The seed is printed first in either case.
--max-cpus=N Maximum number of jobs that run at the same time. Default: all processors.

A run admits inputs until the corpus holds workflow.max_entries entries, then finishes the work in flight and prints a summary. See Getting started for an example.

Choosing a campaign

Goal Setup
Compare TLC and Apalache on the standard operators init, then run --how=pbt. This is the default.
Compare them on the TLA+ Community Modules Community Modules
Compare TLC's recursion with Apalache's folds Recursive operators
Generate calls to your own operators Custom operators
Test one checker against itself Metamorphic testing
Check verdicts against a predicted outcome Graph-based testing
Compare TLC with one worker against TLC with several Comparing TLC with itself

Stopping and resuming

Press Ctrl+C to stop. The run stops its workers and saves the corpus. The next run on the same corpus validates it, finishes moves that were interrupted, and continues where the last run stopped. The counters in the summary add up over all runs of a corpus.

Only one process uses a corpus at a time. run and export-db take a lock on it.

CPU use

--max-cpus limits the jobs that run at the same time across all stages. A TLC job uses workflow.tlc.workers CPUs, so with --max-cpus=8 and workers = 2, at most four TLC processes run. Apalache runs workflow.apalache.workers long-lived processes, one CPU each. Checking has priority over parsing, and parsing has priority over generation, so a slow checker does not pile up unchecked inputs.

The live display

On an interactive terminal, run redraws a flow diagram of the stages once per second. It shows the queue and verdict counters of each stage. A changed value is bold for one second and marked ↑ or ↓. After the workers stop, FINALIZING means that the corpus is being validated. Set NO_COLOR to turn off colors. When output is redirected to a file, only the final summary is printed.

Reproducibility

Every entry can be replayed exactly. Its input bytes and the corpus's generator settings determine the module, and fuzztla print regenerates it (Inspecting a corpus).

A whole run is reproducible only approximately. Each generator worker has its own random stream derived from --seed, so the same seed, configuration, starting corpus and --max-cpus produce the same candidate inputs. Which candidates become entries, however, depends on timing between workers.

Comparing TLC with itself

With checkers = ["tlc", "tlcn"] in [workflow], every input is checked by TLC with one worker and by TLC with workflow.tlcn.workers workers. The two must report the same verdict, and when both searches complete, the same number of distinct states. TLC-n can be added to a TLC and Apalache campaign as a third checker.

The triager reports a disagreement in which one TLC run finds a counterexample and the other an evaluation error as FIRST_ERROR. Multi-threaded TLC may reach either error first, so this is not a defect.

The triager reports two completed searches with different numbers of distinct states as STATE_COUNT. Rerun such an entry many times with several workers: in corpus68, one was tlc-020, a race that corrupts values shared by TLC's workers.

Older corpora

A corpus created before TLC-n existed lacks its directories. Create them with mkdir corpus/02tlcn-{inputs,pass,counterexample,fail,crash}.

When a run stops with an error

Message What to do
could not generate corpus entry … for richness cohort … The generator cannot make inputs rich enough for that cohort. Lower richness_threshold_base or richness_cohorts in [pbt], or ignore fewer categories.
parser worker did not connect within … The machine is overloaded, often by another run. Lower --max-cpus.
A generator crash with a path under .work/generator-crash/ A FuzzTLA bug. The .cbor and .stacktrace files there reproduce it, so please report them.