diff --git a/crates/tests/fixtures/harness/build.rs b/crates/tests/fixtures/harness/build.rs index aa06f731cb..b7acb31aec 100644 --- a/crates/tests/fixtures/harness/build.rs +++ b/crates/tests/fixtures/harness/build.rs @@ -1,24 +1,10 @@ -// Build script for `test_fixtures`. -// // Walks `data///` and emits one `#[test]` per fixture into -// `$OUT_DIR/generated_tests.rs`. The generated test names encode the group so -// `cargo test ::` can target a single category. -// -// Each generated test calls back into `crate::run_fixture(group, name)`, -// which lives in the integration test (`tests/fixtures.rs`); `build.rs` only -// owns discovery + codegen. -// -// The build script also emits `compile_fixtures.rs`, which `src/lib.rs` -// `include!`s. That file contains one module per fixture that has an -// `expected.rs`, each `include!`ing that golden file. The result is that -// every `expected.rs` is fed through `rustc` whenever the harness crate -// compiles — so a malformed golden (bad syntax, references a non-existent -// item, etc.) breaks the build immediately rather than going unnoticed. +// `$OUT_DIR/generated_tests.rs`. Each test calls `crate::run_fixture(group, +// name)` in `tests/fixtures.rs`. // -// Cargo runs `#[test]` functions in parallel by default, so generating one -// test per fixture preserves the parallelism of the existing roundtrip -// crates (each fixture writes scratch output into a unique `$OUT_DIR` -// subdirectory, so there is no contention on shared files). +// Also emits `$OUT_DIR/compile_fixtures.rs` (included by `src/lib.rs`) +// containing one module per fixture that has an `expected.rs`, each +// `include!`ing that golden so a malformed golden breaks the build. use std::fmt::Write as _; use std::path::{Path, PathBuf}; @@ -33,11 +19,6 @@ fn main() { let mut tests = String::new(); tests.push_str("// @generated by build.rs — do not edit by hand.\n"); - // `compile_fixtures.rs` is `include!`d from `src/lib.rs` so that every - // fixture's `expected.rs` is fed through `rustc` as part of the regular - // build, not just diffed as a string. Each fixture is wrapped in its own - // module so the `pub mod Test { ... }` blocks the various `expected.rs` - // files declare don't collide with each other. let mut compile = String::new(); compile.push_str("// @generated by build.rs — do not edit by hand.\n"); @@ -59,8 +40,6 @@ fn main() { let expected_rs = fixture_dir.join("expected.rs"); if expected_rs.is_file() { - // Use an absolute path so `include!` works regardless of - // where cargo invokes the build from. let abs = std::fs::canonicalize(&expected_rs).unwrap_or(expected_rs); writeln!( compile, @@ -70,7 +49,6 @@ fn main() { .unwrap(); } } - // Touch the group dir for change tracking even when empty. println!("cargo:rerun-if-changed={}", group_dir.display()); } diff --git a/crates/tests/fixtures/harness/data/README.md b/crates/tests/fixtures/harness/data/README.md index 34342f09b3..467ce45086 100644 --- a/crates/tests/fixtures/harness/data/README.md +++ b/crates/tests/fixtures/harness/data/README.md @@ -1,10 +1,7 @@ # Test fixture format This directory holds the data-driven fixtures consumed by the -`test_fixtures` harness (`crates/tests/fixtures/harness`). It is the -single living document for how the parser/generator test suite is -organised; older planning notes have been removed now that the -consolidation is complete. +`test_fixtures` harness (`crates/tests/fixtures/harness`). ## Layout @@ -17,16 +14,10 @@ crates/tests/fixtures/harness/data/ expected.rdl | expected.rs | expected.err ``` -`build.rs` in the harness crate enumerates every `//` -directory at compile time and emits one `#[test]` per fixture. Each -generated `#[test]` calls back into the harness's `run_fixture(group, -name)` dispatcher; nothing in `data/` is itself Rust code. - -The harness writes scratch output under -`$OUT_DIR/scratch///`, so concurrent tests never share -filesystem state and Cargo's normal parallel `#[test]` execution is -preserved (this is what keeps the suite as fast as the existing -`roundtrip/{rdl,clang,bindgen}` crates). +`build.rs` enumerates every `//` directory and emits one +`#[test]` per fixture; each test calls back into `run_fixture(group, +name)`. Scratch output goes under `$OUT_DIR/scratch///` so +parallel `#[test]` execution is preserved. ## Groups @@ -41,8 +32,8 @@ preserved (this is what keeps the suite as fast as the existing ## `fixture.toml` -A deliberately tiny key/value subset of TOML, parsed without external -dependencies. Supported keys: +A tiny key/value subset of TOML, parsed without external dependencies. +Supported keys: | key | type | applies to | meaning | |------------------|------------|------------|-------------------------------------------| @@ -53,11 +44,8 @@ dependencies. Supported keys: | `no_comment` | bool | bindgen | pass `--no-comment` to bindgen | | `specific_deps` | bool | bindgen | pass `--specific-deps` to bindgen | | `kind` | string | error | `"reader"` (default), `"reader_no_input"`, or `"writer"` — which stage must fail | -| `arch_inputs` | string[] | merge | per-input arch tagging, e.g. `["input-x86.rdl=X86", "input-x64.rdl=X64"]`. Arches are `X86`/`X64`/`Arm64` or `\|`-joined. When set, the harness uses `Merger::arch_input` so types present in only some arches get a `SupportedArchitecture` attribute. | -| `outputs` | string[] | rdl | run the writer multiple times. Each entry is `"="`; `;` separates multiple `writer.filter(...)` calls in a single invocation. When omitted, the runner falls back to one writer with `filter` (default `"Test"`) and `expected.rdl`. | - -The format is a strict subset of real TOML so a fixture written today -will keep parsing if the harness later swaps in a full TOML crate. +| `arch_inputs` | string[] | merge | per-input arch tagging, e.g. `["input-x86.rdl=X86", "input-x64.rdl=X64"]`. Arches are `X86`/`X64`/`Arm64` or `\|`-joined. | +| `outputs` | string[] | rdl | run the writer multiple times. Each entry is `"="`; `;` separates multiple `writer.filter(...)` calls. | ## Adding a fixture @@ -73,33 +61,25 @@ that the actual output matches the committed golden. ## Filtering -Each fixture is a normal `#[test]`, so you can use the standard Cargo -filter syntax: +Each fixture is a normal `#[test]`, so standard Cargo filtering works: ```sh -# everything -cargo test -p test_fixtures - -# just the bindgen group -cargo test -p test_fixtures bindgen_ - -# a single fixture -cargo test -p test_fixtures rdl_enum +cargo test -p test_fixtures # everything +cargo test -p test_fixtures bindgen_ # just the bindgen group +cargo test -p test_fixtures rdl_enum # a single fixture ``` -## What stays bespoke (and why) +## What stays bespoke -A handful of test files under `crates/tests/` deliberately do **not** use -this fixture format. They exercise things the harness doesn't model -(runtime semantics of generated bindings, direct builder/reader-API -calls, OS-level I/O failures, structural assertions on attribute -values), and forcing them through a byte-stable RDL roundtrip would lose -coverage rather than add it: +A handful of test files under `crates/tests/` deliberately do not use +this fixture format because they exercise things the harness doesn't +model (runtime semantics of generated bindings, direct builder/reader +API calls, OS-level I/O failures, structural attribute assertions): - `tests/libs/rdl/tests/{assembly_name, const-underlying, const-underlying-rdl, directory, error, exclusive-to, fn_abi, guid-derive, split, struct_fields, struct_values, writer_errors}.rs` - `tests/libs/metadata/tests/{empty, struct, attribute, class, interface, reader, load_library, assembly_name}.rs` - `tests/libs/bindgen/tests/{bool, deps, delegate_*, panic, ref_params}.rs` - `tests/{misc,winrt}/**` -If a future change makes one of these expressible as a roundtrip, -golden-Rust, or error fixture, migrate it; otherwise leave it alone. +Migrate them as future changes make them expressible as a roundtrip, +golden-Rust, or error fixture; otherwise leave them alone. diff --git a/crates/tests/fixtures/harness/src/lib.rs b/crates/tests/fixtures/harness/src/lib.rs index 47fbe24e44..68502cded4 100644 --- a/crates/tests/fixtures/harness/src/lib.rs +++ b/crates/tests/fixtures/harness/src/lib.rs @@ -1,16 +1,7 @@ -//! Compile-time validation of fixture golden Rust files. -//! -//! `build.rs` emits `compile_fixtures.rs` containing one module per fixture -//! that has an `expected.rs`, each `include!`ing the golden file. By -//! `include!`ing that generated file here, every `expected.rs` is compiled -//! as part of building this crate. That guarantees the goldens are not just -//! syntactically valid but also reference real items in the `windows-*` -//! crates they depend on — so a stale golden breaks the build. -//! -//! Gated on `cfg(windows)` for now: some goldens reference items (e.g. -//! `IMarshal`-related glue) that are not available on non-Windows targets. -//! -//! The fixture-execution test logic still lives in `tests/fixtures.rs`. +//! Compile every fixture's `expected.rs` so stale goldens break the build. +//! `build.rs` emits the include file. Test-execution logic lives in +//! `tests/fixtures.rs`. Gated on `cfg(windows)` because some goldens +//! reference Windows-only items. #[cfg(windows)] include!(concat!(env!("OUT_DIR"), "/compile_fixtures.rs")); diff --git a/crates/tests/fixtures/harness/tests/fixtures.rs b/crates/tests/fixtures/harness/tests/fixtures.rs index e1710fb16a..e6c20160a0 100644 --- a/crates/tests/fixtures/harness/tests/fixtures.rs +++ b/crates/tests/fixtures/harness/tests/fixtures.rs @@ -1,36 +1,19 @@ -//! Unified test-fixture harness. -//! -//! Each fixture lives in `crates/tests/fixtures/harness/data///` -//! and consists of a small set of input files plus golden output files. -//! `build.rs` discovers every fixture and emits one `#[test]` per fixture; -//! this file dispatches by `group` to perform the appropriate check. See -//! `data/README.md` for the fixture format and the list of supported groups. +//! Unified test-fixture harness. See `data/README.md` for the fixture format. use std::path::{Path, PathBuf}; include!(concat!(env!("OUT_DIR"), "/generated_tests.rs")); -/// The legacy `tests/roundtrip/clang` and `tests/roundtrip/rdl` crates -/// unconditionally passed this reference winmd directory to clang and to -/// every reader/writer that needed Win32 types. The harness mirrors that -/// for the `clang` group so individual clang fixtures don't have to declare -/// it; the `rdl` group still requires the explicit `references = [...]` -/// because most RDL inputs are self-contained `Test`-namespace fixtures and -/// reading the full Windows winmd into every test would slow the suite down -/// noticeably. +// Reference winmd auto-passed to the `clang` group so individual fixtures +// don't have to declare it (most C++ headers reference Win32 types). const DEFAULT_REFERENCE: &str = "../../../libs/bindgen/default"; -/// Entry point invoked by every generated `#[test]`. fn run_fixture(group: &str, name: &str) { let fixture = Fixture::new(group, name); match group { "rdl" => run_rdl(&fixture), "clang" => { - // libclang.dll on the Windows CI runner is 64-bit only; the legacy - // `tests/roundtrip/clang` crate skips the whole suite on 32-bit - // targets via `#![cfg(target_pointer_width = "64")]`. Mirror that - // here at runtime so 32-bit builds still discover/compile the - // generated tests but skip the clang group. + // libclang.dll on the Windows CI runner is 64-bit only. if cfg!(not(target_pointer_width = "64")) { eprintln!("skipping clang/{name} on non-64-bit target"); return; @@ -54,20 +37,15 @@ struct Fixture { impl Fixture { fn new(group: &str, name: &str) -> Self { - // CARGO_MANIFEST_DIR points at the harness crate root regardless of - // how cargo is invoked, so fixture lookup is location-independent. let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let dir = manifest.join("data").join(group).join(name); assert!(dir.is_dir(), "fixture directory missing: {}", dir.display()); - // OUT_DIR is the build script's per-crate output directory. Test - // binaries can read it via env! at compile time. let scratch = PathBuf::from(env!("OUT_DIR")) .join("scratch") .join(group) .join(name); - // Wipe and recreate so a previous run's leftovers can never cause - // a stale-pass on a subsequent run. + // Wipe so a previous run's leftovers can't cause a stale-pass. if scratch.exists() { std::fs::remove_dir_all(&scratch).unwrap(); } @@ -90,9 +68,6 @@ impl Fixture { } /// Panic with the harness's standard `[group/name] stage: error` framing. - /// Used by every group runner so failure messages render uniformly across - /// the suite. `stage` accepts anything `Display`-able so callers can pass - /// `format_args!("reader({path})")` etc. without an extra allocation. fn fail(&self, stage: impl std::fmt::Display, error: impl std::fmt::Display) -> ! { panic!("[{}/{}] {stage}: {error}", self.group, self.name); } @@ -109,11 +84,9 @@ impl Fixture { } } -/// A deliberately tiny key=value parser for `fixture.toml`. We only need a -/// handful of declarative knobs (filter, no_allow, no_comment, noexcept, -/// specific_deps, references); pulling in a full TOML dependency for that would be -/// disproportionate. The format is a strict subset of TOML so authors can -/// add real TOML structure later without breaking existing fixtures. +/// A tiny key=value parser for `fixture.toml`. The format is a strict subset +/// of TOML so authors can add real TOML structure later without breaking +/// existing fixtures. /// /// Supported lines: /// ```text @@ -131,34 +104,18 @@ struct FixtureConfig { noexcept: bool, specific_deps: bool, references: Vec, - /// For the `winmd_to_rdl` group: the prebuilt winmd (or directory) the - /// writer should consume. There is no `input.rdl`; the fixture is a - /// pure "filter a winmd to RDL" check used today by the legacy - /// `nested-arches`, `nested-packing` and `default-interface` tests. + /// `winmd_to_rdl` only: prebuilt winmd (or directory) to consume. winmd_input: Option, - /// For `error` fixtures: which stage is expected to fail. Defaults to - /// `"reader"` (the legacy behaviour). `"writer"` means the harness must - /// successfully compile inputs to a winmd via the reader and then assert - /// that the *writer* fails when fed that winmd back without the - /// referenced `defs-*.rdl` winmds. - /// - /// `"reader_no_input"` runs the reader with no input file; it exists for - /// the single legacy `invalid_output` test which asserts the reader - /// rejects an output path of `.`. + /// `error` only: which stage must fail. `"reader"` (default), + /// `"reader_no_input"`, or `"writer"`. kind: Option, - /// For `merge` fixtures: per-input architecture bits. Each entry is - /// `"input-.rdl="` where `` is one of `X86`, `X64`, - /// `Arm64`, or a `|`-joined combination (e.g. `"X86|X64"`). When set, - /// the harness uses `Merger::arch_input` instead of `Merger::input`, - /// so types present in only some arches are tagged with - /// `SupportedArchitecture` in the merged winmd. + /// `merge` only: per-input arch tagging, e.g. `"input-x86.rdl=X86"`. + /// Arches are `X86`/`X64`/`Arm64` or `|`-joined. When set, the harness + /// uses `Merger::arch_input` so types present in only some arches get + /// a `SupportedArchitecture` attribute. arch_inputs: Vec, - /// For `rdl` fixtures: list of additional writer invocations after the - /// reader produces the winmd. Each entry is `"="`, - /// where `` is one or more filter strings separated by `;` - /// (each becomes a `writer.filter(...)` call). When `outputs` is empty - /// the runner falls back to a single writer with `filter` (default - /// `"Test"`) and the `expected.rdl` golden. + /// `rdl` only: run the writer once per entry, each `"="`. + /// `;` separates multiple `writer.filter(...)` calls in a single invocation. outputs: Vec, } @@ -244,12 +201,9 @@ fn run_rdl(f: &Fixture) { .write() .unwrap_or_else(|e| f.fail("reader", e)); - // Build the (expected_filename, [filter, ...]) list. With no `outputs` - // declared this is a single (expected.rdl, [filter|"Test"]) entry, which - // matches the original single-writer behaviour. With `outputs` declared - // (today only the migrated `mod_recursive` fixture) we run the writer - // once per entry so a single fixture can assert several filtered slices - // of the same winmd against their own goldens. + // With no `outputs` declared, run a single writer with `filter` (default + // "Test") against `expected.rdl`. With `outputs` declared, run once per + // entry so a fixture can diff several filtered slices against own goldens. let invocations: Vec<(String, Vec)> = if cfg.outputs.is_empty() { let filter = cfg.filter.as_deref().unwrap_or("Test"); vec![("expected.rdl".to_string(), vec![filter.to_string()])] @@ -258,8 +212,6 @@ fn run_rdl(f: &Fixture) { }; for (i, (expected, filters)) in invocations.iter().enumerate() { - // Per-output scratch file so a failing fixture leaves all goldens' - // actuals on disk for inspection. let actual_rdl = f.scratch(&format!("out{i}.rdl")); let mut writer = windows_rdl::writer(); writer.input(winmd.to_str().unwrap()); @@ -278,10 +230,7 @@ fn run_rdl(f: &Fixture) { } } -/// Parse one `outputs = [...]` entry of the form `"="`, -/// where `` is one or more filter strings separated by `;`. Each -/// filter becomes a `writer.filter(...)` call; the `;` separator (rather than -/// `,`) keeps the spec readable inside the comma-separated TOML array. +/// Parse one `outputs = [...]` entry of the form `"="`. fn parse_output_spec(s: &str) -> (String, Vec) { let (expected, filters) = s.split_once('=').unwrap_or_else(|| { panic!("`outputs` entry {s:?} must be of the form \"=\"") @@ -312,12 +261,6 @@ fn run_clang(f: &Fixture) { "-fms-extensions", ]) .input(input.to_str().unwrap()) - // The legacy `tests/roundtrip/clang` crate unconditionally passed - // `default/` to every clang run. Mirror that here so individual - // fixtures don't have to declare it: most C++ headers under test - // implicitly reference Win32 types (HRESULT, GUID, ...) and the - // overhead of registering an extra reference for fixtures that - // don't is negligible. .input(DEFAULT_REFERENCE); for r in &cfg.references { clang.input(r); @@ -424,19 +367,14 @@ fn run_error_reader(f: &Fixture) { ) }); - // The Display impl rewrites paths relative to the input filename which - // varies per machine; use the raw `message`/`line`/`column` fields so - // expected.err is portable. let actual = format_error(&err, &input); diff_or_update_string(&actual, &f.input("expected.err")); } -/// `kind = "reader_no_input"`: run the reader with *no* input file, asserting -/// it fails. This is a niche shape used today by the single legacy -/// `invalid_output` test which feeds an output path of `.` to the reader and -/// expects "invalid output". The harness assumes the output target is `.` -/// (the only construction the test actually exercises) — if a future fixture -/// needs a different output, lift this to a `reader_output = "..."` knob. +/// `kind = "reader_no_input"`: run the reader with no input file. Used today +/// only by `invalid_output`, which feeds output `.` and expects "invalid +/// output". If a future fixture needs a different output target, lift this +/// to a `reader_output = "..."` knob. fn run_error_reader_no_input(f: &Fixture) { let err = windows_rdl::reader() .output(".") @@ -449,39 +387,14 @@ fn run_error_reader_no_input(f: &Fixture) { ) }); - // The Display impl includes ` --> ::` whose `` is - // the absolute output path, which differs across machines. The legacy - // test asserted only on the prefix `error: invalid output\n --> .`, so - // we drop the path/line suffix and render the message with the same - // leading-`\n` + trailing-`\n` framing that `windows_rdl::Error`'s - // `Display` impl uses for every other reader-error fixture, keeping - // expected.err visually consistent across the `error/` group. If this - // shape ever outgrows a single fixture we should reuse `format_error` - // instead. + // Drop the path/line suffix (it's machine-dependent) and reframe the + // message with the same `\nerror: ...\n` shape used elsewhere. let actual = format!("\nerror: {}\n", err.message); diff_or_update_string(&actual, &f.input("expected.err")); } -/// Writer-error layout (`kind = "writer"` in fixture.toml): -/// -/// ```text -/// data/error// -/// defs-*.rdl # one or more dependency RDLs (compiled to winmds) -/// input.rdl # uses types from the defs above -/// fixture.toml # kind = "writer" -/// expected.err # writer error (no path/line; Display = "\nerror: ") -/// ``` -/// -/// The harness: -/// 1. Compiles each `defs-*.rdl` to its own scratch winmd via the reader. -/// 2. Compiles `input.rdl` (with the def winmds as additional inputs) to a -/// scratch winmd via the reader. Both reader steps must succeed. -/// 3. Runs the *writer* on `input.rdl`'s winmd alone (no def winmds) and -/// asserts it fails. The error is matched against `expected.err`. -/// -/// This composes with future "reference-winmd" coverage and replaces the -/// bespoke `writer_errors_on_missing_enum_type` test from the now-removed -/// `tests/libs/rdl/tests/panic.rs`. +/// `kind = "writer"`: compile every `defs-*.rdl` and `input.rdl` to winmds, +/// then run the writer on `input.winmd` *alone* and assert it fails. fn run_error_writer(f: &Fixture) { let mut defs: Vec = std::fs::read_dir(&f.dir) .unwrap() @@ -500,9 +413,6 @@ fn run_error_writer(f: &Fixture) { f.name ); - // Step 1: compile each defs-*.rdl to its own winmd. Use the source file - // stem so scratch artifacts (e.g. `defs-platform.winmd`) are easy to map - // back to their inputs when debugging a failure. let mut def_winmds = Vec::with_capacity(defs.len()); for def_rdl in &defs { let stem = def_rdl @@ -518,7 +428,6 @@ fn run_error_writer(f: &Fixture) { def_winmds.push(winmd); } - // Step 2: compile input.rdl referencing the def winmds. let input = f.input("input.rdl"); let input_winmd = f.scratch("input.winmd"); let mut reader = windows_rdl::reader(); @@ -531,7 +440,6 @@ fn run_error_writer(f: &Fixture) { .write() .unwrap_or_else(|e| f.fail("reader(input)", e)); - // Step 3: run the writer on input.winmd ALONE — must fail. let actual_rdl = f.scratch("out.rdl"); let err = windows_rdl::writer() .input(input_winmd.to_str().unwrap()) @@ -545,8 +453,7 @@ fn run_error_writer(f: &Fixture) { ) }); - // Writer errors carry no file path or line info (writer_err! sets - // file_name="" and line=0), so the Display rendering is portable as-is. + // Writer errors carry no file path or line info, so Display is portable. let actual = format!("{err}"); diff_or_update_string(&actual, &f.input("expected.err")); } @@ -554,8 +461,7 @@ fn run_error_writer(f: &Fixture) { fn run_merge(f: &Fixture) { let cfg = f.config(); - // Discover input-*.rdl files in lexical order so merge ordering is - // deterministic and matches authors' intuition (input-a.rdl, input-b.rdl). + // Lexical order so merge ordering is deterministic. let mut inputs: Vec = std::fs::read_dir(&f.dir) .unwrap() .filter_map(|e| e.ok()) @@ -573,11 +479,6 @@ fn run_merge(f: &Fixture) { f.name ); - // Optional per-input arch tagging. When `arch_inputs` is declared, every - // input-*.rdl must have an entry; the harness then uses - // `Merger::arch_input` so types present in only some arches are tagged - // with `SupportedArchitecture` in the merged winmd. Otherwise we use the - // plain `Merger::input` which yields no arch attributes. let arch_map = parse_arch_inputs(&cfg.arch_inputs); let mut merger = windows_metadata::merge(); @@ -619,10 +520,8 @@ fn run_merge(f: &Fixture) { diff_or_update(&actual_rdl, &f.input("expected.rdl")); } -/// Parse `arch_inputs = ["input-x86.rdl=X86", "input-x64.rdl=X64", ...]` -/// into `(filename, arch_bits)` pairs. Names map to the bitmask -/// `windows_metadata::merge` documents (X86=1, X64=2, Arm64=4); multiple -/// arches can be `|`-joined (e.g. `"input-32.rdl=X86|Arm64"`). +/// Parse `arch_inputs = ["input-x86.rdl=X86", ...]` into `(filename, bits)` +/// pairs (X86=1, X64=2, Arm64=4; `|`-joinable). fn parse_arch_inputs(entries: &[String]) -> Vec<(String, i32)> { entries .iter() @@ -646,22 +545,8 @@ fn parse_arch_inputs(entries: &[String]) -> Vec<(String, i32)> { .collect() } -/// Writer-only "filter a prebuilt winmd to RDL" fixture. -/// -/// Layout: -/// ```text -/// data/winmd_to_rdl// -/// fixture.toml # winmd_input = ""; filter = ""; (references optional) -/// expected.rdl -/// ``` -/// -/// There is no `input.rdl` — this group exists for tests that consume a large -/// prebuilt winmd (today: `crates/libs/bindgen/default/Windows*.winmd`) and -/// want to diff a small filtered RDL slice. Replaces the bespoke -/// `nested-arches.rs`, `nested-packing.rs` and `default-interface.rs` tests. -/// -/// `winmd_input` is required; `filter` is required (a whole-winmd dump would -/// produce an unwieldy golden file and is not the point of these tests). +/// Writer-only: filter a prebuilt winmd to RDL. `winmd_input` and `filter` +/// are required; paths resolve relative to the fixture directory. fn run_winmd_to_rdl(f: &Fixture) { let cfg = f.config(); let winmd_input = cfg.winmd_input.as_deref().unwrap_or_else(|| { @@ -677,9 +562,6 @@ fn run_winmd_to_rdl(f: &Fixture) { ) }); - // `winmd_input` and `references` paths are resolved relative to the - // fixture directory so authors can use `../../../...` the same way the - // legacy roundtrip crates do. let resolved_input = f.dir.join(winmd_input); let actual_rdl = f.scratch("out.rdl"); @@ -736,10 +618,8 @@ fn diff_or_update_string(actual: &str, expected_path: &Path) { } } -/// Produce a portable rendering of a `windows_rdl::Error` for `expected.err`. -/// The default `Display` impl embeds the absolute path of the input file -/// which differs across machines; we replace that with the basename so -/// goldens are reproducible. +/// Render a `windows_rdl::Error` portably for `expected.err` by replacing the +/// machine-dependent absolute path with the input basename. fn format_error(err: &windows_rdl::Error, input: &Path) -> String { let basename = input .file_name() diff --git a/crates/tests/libs/rdl/tests/writer_errors.rs b/crates/tests/libs/rdl/tests/writer_errors.rs index f30895504b..98a0f60efe 100644 --- a/crates/tests/libs/rdl/tests/writer_errors.rs +++ b/crates/tests/libs/rdl/tests/writer_errors.rs @@ -1,14 +1,6 @@ // Tests that writer error conditions return Err instead of panicking. -// -// The four `writer_succeeds_for_*` happy-path smoke tests that previously -// lived in this file (callback / delegate / enum / interface) were removed -// during the test-fixture migration: their inline RDL inputs are strict -// subsets of the existing -// `crates/tests/fixtures/harness/data/rdl/{fn,delegate,enum,class}/` fixtures, -// which already exercise the same writer code paths via byte-stable roundtrip -// diffs (a strictly stronger check than `assert!(result.is_ok())`). The two -// `writer_returns_err_for_*` tests below remain because the harness does not -// model writer-side I/O failures (filesystem-level errors on the output path). +// Limited to OS-level I/O failures on the output path; happy-path and +// missing-dependency coverage lives in the test_fixtures harness. use std::sync::atomic::{AtomicU32, Ordering}; @@ -36,8 +28,6 @@ fn compile_rdl_to_winmd(rdl: &str) -> std::path::PathBuf { winmd } -// ── I/O failure tests ──────────────────────────────────────────────────────── - #[test] fn writer_returns_err_for_bad_output_path() { // Use an existing regular file as a "blocker": create_dir_all cannot turn @@ -63,9 +53,7 @@ fn writer_returns_err_for_bad_output_path() { #[test] fn writer_split_returns_err_for_bad_output_dir() { - // In split mode the writer creates /.rdl files; the - // parent of each such file is itself. Using an existing regular - // file as makes create_dir_all fail on both Linux and Windows. + // Same idea as above, applied to split-mode output. let winmd = compile_rdl_to_winmd( r#" #[win32] @@ -84,7 +72,6 @@ mod Test { .split(true) .write(); - // Clean up before asserting so temp files are always removed. let _ = std::fs::remove_file(&winmd); let _ = std::fs::remove_file(&blocker); @@ -98,7 +85,3 @@ mod Test { "error message should mention 'failed to'; got: {msg}" ); } - -// ── Happy-path smoke tests ──────────────────────────────────────────────────── -// -// Removed in phase 4 batch 3. See the file header for the rationale.