test-lang 0.2.0

Compiler snapshot test harness for tokens, ASTs, and errors.
Documentation

Performance First

Latest local Criterion means (cargo bench, Windows x86_64, Rust stable). The workload that matters in a test suite is the check on the matching path — the case a green suite runs on every pass:

  • Capture (per_line, 16 lines): ~0.5 µs
  • Check, matching (16 lines): ~1.2 µs
  • Check, matching (256 lines): ~19 µs

The check is a line-level diff with a common prefix/suffix fast path: identical leading and trailing lines are matched in linear time before the quadratic LCS engine runs, so a near-miss snapshot only pays for the region that actually changed.

Installation

[dependencies]
test-lang = "0.2"

no_std + alloc (drops the std::error::Error anchor, keeps everything else):

[dependencies]
test-lang = { version = "0.2", default-features = false }

Quick Start

Snapshot a token stream, one token per line, and assert it:

use test_lang::Snapshot;

// Whatever your lexer produces — here a stand-in that yields display strings.
fn lex(source: &str) -> Vec<String> {
    source.split_whitespace().map(str::to_string).collect()
}

let snapshot = Snapshot::per_line(lex("let x = 1"));
snapshot.check("let\nx\n=\n1").expect("token stream matches");

When the output drifts, the returned Mismatch shows precisely what changed:

use test_lang::Snapshot;

let snapshot = Snapshot::per_line(["let", "y", "=", "1"]);
let err = snapshot.check("let\nx\n=\n1").unwrap_err();

// `-x` was expected; `+y` was produced in its place.
assert!(err.to_string().contains("-x"));
assert!(err.to_string().contains("+y"));

Features

  • Three capture modesSnapshot::display for a Display value, Snapshot::debug for a pretty-printed Debug tree, and Snapshot::per_line for a token stream (one item per line, so the diff points at the exact token).
  • Cross-platform normalization — CRLF/CR collapse to LF, trailing whitespace is stripped, and trailing blank lines are trimmed. A snapshot written by hand in a test matches output captured on any platform.
  • Line-level diffs — a failed check returns a Mismatch whose Display is a unified -expected/+actual diff; Mismatch::diff exposes the Diff for programmatic inspection.
  • No runtime dependencies — built on core::fmt and alloc only. no_std capable.
  • No panicscheck returns Result; the test author decides whether to unwrap, expect, or propagate.

API Overview

For a complete reference with examples, see docs/API.md.

  • Snapshot — a normalized, comparable rendering of compiler output; new / display / debug / per_line / check.
  • Diff & Change — the line-level edit script, rendered as a unified diff.
  • Mismatch — the error returned by Snapshot::check, carrying the Diff.

Runnable examples: examples/tokens.rs, examples/ast.rs, examples/diagnostics.rs.

cargo run --example tokens
cargo run --example ast
cargo run --example diagnostics

Contributing

See REPS.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.