Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

You are reading the development version (master). For the latest release (v3.5.0) see the stable docs.

Trace → Regression Tests + Minimizer

Overview

The trace2tests module converts runtime execution traces into deterministic regression tests. It also provides a delta-debugging minimizer that shrinks failing traces to minimal reproducing sequences.

Trace Schema

Version 1, stable JSON format.

{
  "version": 1,
  "source_file": "path/to/app.ax",
  "source_hash": "<64 hex chars>",
  "cycles": [
    {
      "cycle": 1,
      "message": { "tag": "increment", "payload": {"Int": 0} },
      "state_before_hash": "<64 hex chars>",
      "state_after_hash": "<64 hex chars>",
      "state_after": {"Record": {"type_id": 0, "fields": [{"Int": 1}]}},
      "effects": [
        { "kind": "http_request", "payload_hash": "<64 hex chars>", "callback_tag": "on_response" }
      ],
      "ui_tree_hash": "<64 hex chars>"
    }
  ],
  "final_state_hash": "<64 hex chars>",
  "trace_hash": "<64 hex chars>"
}

Fields

FieldTypeDescription
versionu32Schema version (always 1)
source_filestringPath to source .ax file
source_hashstringSHA-256 of source text
cyclesarrayOrdered cycle records
final_state_hashstringSHA-256 of final state
trace_hashstringSHA-256 of canonical fingerprint

Hashing

All hashes are written as bare lowercase hex (64 characters, no sha256: prefix), for example "bfac1732d6113f3165fb8ef4c21230def6da9bc40af020c72e7a2461a7b1c99c". They use SHA-256 of canonical JSON serialization:

  • Values are serialized via serde (deterministic for BTreeMap)
  • The trace fingerprint concatenates all cycle data in stable format
  • Same inputs always produce identical hashes

Test Spec Format

Generated test specifications are self-contained JSON:

{
  "version": 1,
  "name": "counter_regression",
  "source_file": "examples/counter.ax",
  "source_hash": "<64 hex chars>",
  "messages": [
    { "tag": "increment", "payload": {"Int": 0} },
    { "tag": "decrement", "payload": {"Int": 0} }
  ],
  "assertions": [
    { "kind": "final_state_hash", "expected": "<64 hex chars>", "description": "..." },
    { "kind": "trace_hash", "expected": "<64 hex chars>", "description": "..." },
    { "kind": "cycle_count", "expected": "2", "description": "..." }
  ]
}

Assertion Kinds

KindDescription
final_state_hashSHA-256 of final state matches
trace_hashSHA-256 of full trace fingerprint matches
cycle_countNumber of cycles matches

Delta Debugging Minimizer

Implements the ddmin algorithm to shrink failing message sequences:

  1. Chunk removal: Split into n chunks, try removing each
  2. Granularity increase: If no chunk removal works, try finer splits
  3. 1-minimal pass: Try removing each individual message
  4. Result is guaranteed 1-minimal (removing any single message stops the failure)

Predicates

Built-in predicates:

  • panic: Failure = runtime error during message processing. This is the CLI default.
  • State mismatch: Failure = final state hash differs from expected. This one exists only in the library (trace2tests::make_state_mismatch_predicate); the CLI has no flag for it.

External predicates: Any command that receives, as its last argument, the path of a temp JSON file ({"source_file": ..., "messages": [...]}) and returns non-zero on failure.

The CLI --predicate accepts only panic or an external command. Any value other than panic is run as a command. To minimize against a state mismatch from the CLI, wrap the check in an external command.

CLI Usage

Record

boruna trace2tests record <file.ax> --messages "tag:payload,..." --out trace.json

Generate

boruna trace2tests generate --trace trace.json --out test_spec.json [--name test_name]

Run

boruna trace2tests run --spec test_spec.json [--source app.ax]

Minimize

boruna trace2tests minimize --trace trace.json --source app.ax [--predicate panic]
boruna trace2tests minimize --trace trace.json --source app.ax --predicate "my_check.sh"

Determinism Guarantees

  • Same source + same messages = identical trace hash
  • Generated tests are deterministic regression gates
  • Minimizer produces deterministic output (same input → same minimal trace)
  • All hashes use SHA-256 with canonical serialization

Integration

  • Trace files are compatible with the framework’s CycleRecord format
  • Test specs can be version-controlled alongside source
  • Minimized traces export as regression tests via generate
  • The full pipeline: record → minimize → generate → run