Skip to content

Commit 404b7ac

Browse files
committed
test: standardize snapshot terminology
1 parent ac365cf commit 404b7ac

26 files changed

Lines changed: 211 additions & 206 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ jobs:
7373
cache-all-crates: "true"
7474
prefix-key: v0-rust-codegen-release
7575

76-
- name: Generate Rust fixtures
76+
- name: Generate Rust snapshot tests
7777
run: make codegen-rust
7878

7979
- name: Lint generated Rust

‎.github/workflows/stable.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ jobs:
9191
prefix-key: v0-rust-codegen
9292
save-if: ${{ github.ref == 'refs/heads/master' }}
9393

94-
- name: Generate Rust fixtures
94+
- name: Generate Rust snapshot tests
9595
run: make codegen-rust
9696

9797
- name: Lint generated Rust

‎AGENTS.md‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Two zones, one rule each:
3737

3838
## Backward compatibility
3939

40-
As Plotnik is pre-release, backward compatibility is irrelevant and must not affect design or implementation. Make breaking changes directly and update all in-tree callers, tests, fixtures, and docs. Keep existing compatibility machinery, but use it only to validate the current format and keep all internal format-version integers at `0`.
40+
As Plotnik is pre-release, backward compatibility is irrelevant and must not affect design or implementation. Make breaking changes directly and update all in-tree callers, tests, test data, snapshots, and docs. Keep existing compatibility machinery, but use it only to validate the current format and keep all internal format-version integers at `0`.
4141

4242
Do not add:
4343

@@ -49,14 +49,14 @@ Do not add:
4949

5050
# Commands
5151

52-
| Command | What it does |
53-
| ------------------------ | ----------------------------------------------------- |
54-
| `make check` | `cargo check --workspace --all-targets` |
55-
| `make clippy` | clippy with `-D warnings` |
56-
| `make test [FILTER=...]` | full test suite via native Rust test harnesses |
57-
| `make shot [FILTER=...]` | accept golden fixtures + insta snapshots, then re-run |
58-
| `make fmt` | `cargo fmt` + prettier |
59-
| `make coverage-lines` | per-file missing lines for `plotnik-lib` |
52+
| Command | What it does |
53+
| ------------------------ | ---------------------------------------------- |
54+
| `make check` | `cargo check --workspace --all-targets` |
55+
| `make clippy` | clippy with `-D warnings` |
56+
| `make test [FILTER=...]` | full test suite via native Rust test harnesses |
57+
| `make shot [FILTER=...]` | update custom + Insta snapshots, then re-run |
58+
| `make fmt` | `cargo fmt` + prettier |
59+
| `make coverage-lines` | per-file missing lines for `plotnik-lib` |
6060

6161
Check your changes: `make test`
6262
Before commit: `make fmt`
@@ -87,7 +87,7 @@ crates/
8787
src/vm/ # runtime engine, backtracking, materialization
8888
plotnik-rt/ # shared runtime engine (VM + generated matchers)
8989
plotnik-tests/
90-
tests/ # golden fixtures
90+
tests/ # snapshot tests
9191
mod.rs # test harness + docs
9292
01-lexer/
9393
02-parser/
@@ -209,15 +209,15 @@ cargo run -p plotnik-cli -- lang list # languages + aliase
209209

210210
# Testing
211211

212-
The golden fixtures have priority over Rust-based tests.
212+
The snapshot tests have priority over Rust-based tests.
213213

214214
- Run `make shot` to (re)write generated sections
215-
- Use `FILTER=<name>` with `make test` or `make shot` to run the same filtered fixture subset
216-
- Name new fixture folders after existing ones in sibling stages
215+
- Use `FILTER=<name>` with `make test` or `make shot` to run the same filtered snapshot subset
216+
- Name new snapshot folders after existing ones in sibling stages
217217
- Rust `*_tests.rs` are unit-logic only
218218
- `foo.rs` gets a sibling `foo_tests.rs`, declared as `#[cfg(test)] mod foo_tests;`
219219
- AAA sections separated by blank lines (unless all 3 are one-liners)
220220
- single-line input literal, multi-line uses `indoc!`
221-
- Don't generate data for `insta` snapshots and golden fixtures by hand:
221+
- Don't generate snapshot data by hand:
222222
- use `@""` for `insta` placeholders, then `make shot`
223-
- fill inputs only for golden snapshots
223+
- author snapshot inputs only; let `make shot` write generated sections

‎Makefile‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ test-codegen-rust:
131131

132132
shot:
133133
@# See AGENTS.md for diagnostic guidelines
134-
@# SHOT=1 accepts the golden-fixture suite (tests/0N-*); TRYBUILD=overwrite
135-
@# refreshes the macro_diagnostics .stderr goldens; cargo insta accept does the rest.
134+
@# SHOT=1 updates custom inline snapshots; TRYBUILD=overwrite updates .stderr snapshots.
135+
@# The first run also records pending Insta snapshots, which cargo insta then accepts.
136136
@SHOT=1 TRYBUILD=overwrite cargo test \
137137
--workspace \
138138
--lib \

‎crates/plotnik-lib/src/compiler/analyze/grammar/satisfiability/engine.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ enum Edge {
313313
/// Default ceiling on satisfiability work before the query is declared too complex.
314314
/// Charged for automaton state allocation and in the two quadratic solve loops
315315
/// (`closure` and a `Visible` `thread_step`) for state visits and pattern-edge scans,
316-
/// so it caps the dominant costs. The widest real fixture settles in a few thousand
316+
/// so it caps the dominant costs. The widest real snapshot settles in a few thousand
317317
/// work units, leaving roughly three orders of magnitude of headroom, while a child list
318318
/// past about a thousand wide trips it in a fraction of a second rather than running
319319
/// for tens. Tunable per query via

‎crates/plotnik-lib/src/compiler/emit/targets/rust/config.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use plotnik_rt::{Limit, RuntimeLimitSpec};
88
pub struct Config {
99
/// Rust output-type configuration shared with the type renderer.
1010
pub(crate) rust_types: RustTypesConfig,
11-
/// Whether to emit the JSON surface used by generated-code golden tests.
11+
/// Whether to emit the JSON surface used by generated-code snapshot tests.
1212
pub(crate) debug: bool,
1313
/// The limit policy compiled into the module's safe entry points.
1414
/// Chosen at generation time, never at the call site: the query is

‎crates/plotnik-lib/src/compiler/emit/targets/rust/module.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//!
99
//! Emission is deterministic — instructions render in label order, names and
1010
//! tables come from `BTreeMap`s — so the same query always produces the same
11-
//! code (golden-snapshot-able, cache-friendly).
11+
//! code (snapshot-friendly, cache-friendly).
1212
//!
1313
//! Control skeletons (`run`, `backtrack`, `match_retry`) transcribe the VM's
1414
//! `execute_with_stats` / `backtrack` handler-for-handler over the shared

‎crates/plotnik-lib/src/compiler/parse/lexer_tests.rs‎

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ use similar::TextDiff;
55

66
use super::lexer::dump_tokens;
77

8-
const FIXTURE_EXT: &str = "txt";
8+
const SNAPSHOT_EXT: &str = "txt";
99

1010
#[test]
11-
fn lexer_fixtures() {
11+
fn lexer_snapshots() {
1212
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("test_data/01-lexer");
13-
let mut fixtures = Vec::new();
14-
discover(&root, &mut fixtures);
15-
fixtures.sort();
13+
let mut snapshots = Vec::new();
14+
discover(&root, &mut snapshots);
15+
snapshots.sort();
1616
assert!(
17-
!fixtures.is_empty(),
18-
"01-lexer fixtures should be present under {}",
17+
!snapshots.is_empty(),
18+
"01-lexer snapshots should be present under {}",
1919
root.display()
2020
);
2121

2222
let mut failures = Vec::new();
23-
for path in fixtures {
23+
for path in snapshots {
2424
let raw =
2525
fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
2626
let normalized = raw.replace("\r\n", "\n");
@@ -47,21 +47,21 @@ fn lexer_fixtures() {
4747

4848
assert!(
4949
failures.is_empty(),
50-
"lexer fixtures out of date - run `make shot`:\n\n{}",
50+
"lexer snapshots out of date - run `make shot`:\n\n{}",
5151
failures.join("\n\n")
5252
);
5353
}
5454

5555
fn discover(dir: &Path, out: &mut Vec<PathBuf>) {
5656
let entries =
57-
fs::read_dir(dir).unwrap_or_else(|e| panic!("read fixture dir {}: {e}", dir.display()));
57+
fs::read_dir(dir).unwrap_or_else(|e| panic!("read snapshot dir {}: {e}", dir.display()));
5858
for entry in entries {
5959
let entry =
60-
entry.unwrap_or_else(|e| panic!("read fixture entry in {}: {e}", dir.display()));
60+
entry.unwrap_or_else(|e| panic!("read snapshot entry in {}: {e}", dir.display()));
6161
let path = entry.path();
6262
if path.is_dir() {
6363
discover(&path, out);
64-
} else if path.extension().and_then(|e| e.to_str()) == Some(FIXTURE_EXT) {
64+
} else if path.extension().and_then(|e| e.to_str()) == Some(SNAPSHOT_EXT) {
6565
out.push(path);
6666
}
6767
}
@@ -78,7 +78,7 @@ fn parse_query<'a>(raw: &'a str, path: &Path) -> &'a str {
7878
offset += line.len();
7979
}
8080
panic!(
81-
"fixture {} must contain a `TOKENS` section rule",
81+
"snapshot {} must contain a `TOKENS` section rule",
8282
path.display()
8383
)
8484
}

‎crates/plotnik-lib/src/vm/engine/value.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ enum WorkItem<'a> {
190190
/// Output depth tracks source depth for captured-recursive queries, and a high or
191191
/// `Unbounded` depth limit lets it exceed any native-stack budget — so the walk
192192
/// uses an explicit work stack. Emission is byte-identical to the equivalent
193-
/// recursive printer; the `06-vm` golden fixtures pin that.
193+
/// recursive printer; the `06-vm` snapshots pin that.
194194
fn format_value<'a>(ctx: &mut FormatCtx<'_>, value: &'a Value<'a>, indent: usize) {
195195
let mut stack = vec![WorkItem::Value(value, indent)];
196196
while let Some(item) = stack.pop() {

‎crates/plotnik-tests/build.rs‎

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn main() {
5656
println!("cargo::rerun-if-changed={grammar_path}");
5757
}
5858

59-
generate_golden_tests(&manifest_dir);
59+
generate_snapshot_tests(&manifest_dir);
6060

6161
println!("cargo::rerun-if-changed=build.rs");
6262
println!("cargo::rerun-if-changed=Cargo.toml");
@@ -66,47 +66,47 @@ fn main() {
6666
);
6767
}
6868

69-
fn generate_golden_tests(manifest_dir: &Path) {
69+
fn generate_snapshot_tests(manifest_dir: &Path) {
7070
let tests_dir = manifest_dir.join("tests");
71-
let mut fixtures = Vec::new();
72-
discover_fixtures(&tests_dir, &tests_dir, &mut fixtures);
73-
fixtures.sort();
71+
let mut snapshots = Vec::new();
72+
discover_snapshots(&tests_dir, &tests_dir, &mut snapshots);
73+
snapshots.sort();
7474

7575
let mut tests = TestModule::default();
76-
for relative in fixtures {
76+
for relative in snapshots {
7777
tests.insert(&relative);
7878
}
7979
let mut generated = String::from("// @generated by crates/plotnik-tests/build.rs\n\n");
8080
tests.render(&mut generated, 0);
8181

8282
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR must be set"));
83-
let destination = out_dir.join("golden_tests.rs");
83+
let destination = out_dir.join("snapshot_tests.rs");
8484
let unchanged = fs::read_to_string(&destination).is_ok_and(|current| current == generated);
8585
if !unchanged {
86-
fs::write(destination, generated).expect("generated golden tests must be writable");
86+
fs::write(destination, generated).expect("generated snapshot tests must be writable");
8787
}
8888
println!("cargo::rerun-if-changed={}", tests_dir.display());
8989
}
9090

91-
fn discover_fixtures(dir: &Path, root: &Path, out: &mut Vec<String>) {
91+
fn discover_snapshots(dir: &Path, root: &Path, out: &mut Vec<String>) {
9292
let entries = fs::read_dir(dir)
93-
.unwrap_or_else(|error| panic!("read fixture dir {}: {error}", dir.display()));
93+
.unwrap_or_else(|error| panic!("read snapshot dir {}: {error}", dir.display()));
9494
for entry in entries {
9595
let entry = entry
96-
.unwrap_or_else(|error| panic!("read fixture entry in {}: {error}", dir.display()));
96+
.unwrap_or_else(|error| panic!("read snapshot entry in {}: {error}", dir.display()));
9797
let path = entry.path();
9898
if path.is_dir() {
99-
discover_fixtures(&path, root, out);
99+
discover_snapshots(&path, root, out);
100100
continue;
101101
}
102102
if path.extension().and_then(|extension| extension.to_str()) != Some("txt") {
103103
continue;
104104
}
105105
let relative = path
106106
.strip_prefix(root)
107-
.expect("fixture path must be under tests/")
107+
.expect("snapshot path must be under tests/")
108108
.to_str()
109-
.unwrap_or_else(|| panic!("fixture path is not UTF-8: {}", path.display()))
109+
.unwrap_or_else(|| panic!("snapshot path is not UTF-8: {}", path.display()))
110110
.replace(std::path::MAIN_SEPARATOR, "/");
111111
let stage = relative.split('/').next().unwrap_or("");
112112
if is_stage_dir(stage) {
@@ -127,18 +127,18 @@ fn is_stage_dir(name: &str) -> bool {
127127
#[derive(Default)]
128128
struct TestModule {
129129
modules: BTreeMap<String, TestModule>,
130-
fixtures: BTreeMap<String, String>,
130+
snapshots: BTreeMap<String, String>,
131131
}
132132

133133
impl TestModule {
134134
fn insert(&mut self, relative: &str) {
135135
let mut components = relative.split('/').collect::<Vec<_>>();
136136
let file = components
137137
.pop()
138-
.expect("fixture path must have a file name");
138+
.expect("snapshot path must have a file name");
139139
let stem = file
140140
.strip_suffix(".txt")
141-
.expect("fixture path must end in .txt");
141+
.expect("snapshot path must end in .txt");
142142
require_snake_case(stem, relative);
143143

144144
let mut module = self;
@@ -154,27 +154,27 @@ impl TestModule {
154154
module = module.modules.entry(identifier).or_default();
155155
}
156156

157-
let identifier = format!("fixture_{stem}");
157+
let identifier = format!("snapshot_{stem}");
158158
if let Some(previous) = module
159-
.fixtures
159+
.snapshots
160160
.insert(identifier.clone(), relative.to_string())
161161
{
162162
panic!(
163-
"fixture paths `{previous}` and `{relative}` both register Rust test `{identifier}`"
163+
"snapshot paths `{previous}` and `{relative}` both register Rust test `{identifier}`"
164164
);
165165
}
166166
}
167167

168168
fn render(&self, generated: &mut String, depth: usize) {
169-
for (identifier, relative) in &self.fixtures {
169+
for (identifier, relative) in &self.snapshots {
170170
let indent = " ".repeat(depth);
171171
writeln!(generated, "{indent}#[test]").expect("write generated test attribute");
172172
writeln!(
173173
generated,
174174
"{indent}fn {identifier}() -> Result<(), String> {{"
175175
)
176176
.expect("write generated test declaration");
177-
writeln!(generated, "{indent} crate::run_fixture({relative:?})")
177+
writeln!(generated, "{indent} crate::run_snapshot({relative:?})")
178178
.expect("write generated test body");
179179
writeln!(generated, "{indent}}}\n").expect("write generated test close");
180180
}
@@ -196,6 +196,6 @@ fn require_snake_case(component: &str, relative: &str) {
196196
let valid_rest =
197197
bytes.all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'_');
198198
if !valid_start || !valid_rest {
199-
panic!("fixture path component `{component}` is not snake_case: {relative}");
199+
panic!("snapshot path component `{component}` is not snake_case: {relative}");
200200
}
201201
}

0 commit comments

Comments
 (0)