Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

xtask/tests/fmt.rs

//! The `cargo fmt --all` landmine, and the two things that keep it defused.
//!
//! The damage was real and recent: on 2026-08-04 the writing form of
//! `cargo fmt --all`, run from this repository, rewrote 680 files in facett, 76
//! in znippy and 167 in znippy-zoomies. Everything below exists so nobody loses
//! that afternoon again, and so the pieces cannot be removed quietly.
//!
//! Two claims are asserted here, and both were seen red before being believed:
//!
//!  1. **The interception is installed.** `.cargo/config.toml` aliases `fmt` to
//!     `xtask fmt`, so `cargo fmt` inside this tree cannot reach the landmine.
//!  2. **Discovery is a filesystem walk, not the `members` list.** The list
//!     misses four package trees, and this test names all four, so a future
//!     "simplification" back to `members` goes red instead of silently dropping
//!     608 diffs' worth of files out of the format again.
//!
//! What is deliberately NOT here: an assertion that the whole tree is currently
//! formatted. That is `cargo xtask fmt` (and step one of `cargo xtask ci`), it
//! costs 21 `cargo-fmt` invocations, and putting it in the unit suite would make
//! every `cargo test --workspace` pay for it.

use std::path::{Path, PathBuf};

use xtask::fmt::{cargo_fmt_binary, package_manifests, Mode};

/// The repository root, from this test binary's own manifest.
fn root() -> PathBuf {
    // CARGO_MANIFEST_DIR is `<root>/xtask`.
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .expect("xtask has a parent")
        .to_path_buf()
}

fn rel(root: &Path, p: &Path) -> String {
    p.strip_prefix(root)
        .unwrap_or(p)
        .to_string_lossy()
        .replace('\\', "/")
}

/// The `fmt` alias is the whole interception. Without it, `cargo fmt --all`
/// from this directory rewrites five other repositories.
#[test]
fn cargo_fmt_is_intercepted_by_the_alias() {
    let cfg = root().join(".cargo").join("config.toml");
    let text =
        std::fs::read_to_string(&cfg).unwrap_or_else(|e| panic!("read {}: {e}", cfg.display()));

    let alias = text
        .lines()
        .map(str::trim)
        .find(|l| l.starts_with("fmt ") && l.contains('='))
        .unwrap_or_else(|| {
            panic!(
                "{} has no `fmt` alias.\n\
                 Without it, `cargo fmt --all` in this repository walks local path \n\
                 dependencies out through the old znippy engine crate and rewrites facett, znippy, \n\
                 znippy-zoomies, Skidbladnir and nornir — 12556 diffs, MEASURED \n\
                 2026-08-04. If you removed it because cargo made the alias a hard \n\
                 error (rust-lang/cargo#10049), the landmine is still there: replace \n\
                 the protection, do not just delete it.",
                cfg.display()
            )
        });

    assert!(
        alias.contains("xtask") && alias.contains("fmt"),
        "the `fmt` alias must route to `xtask fmt`, got: {alias}"
    );
}

/// The four package trees the root `members` list does not contain.
///
/// Each is here for its own reason, and all four hold real `.rs` files that had
/// never been formatted:
///
///  * the old znippy engine crate — in the workspace `exclude` list, because
///    znippy's path dependency is read at RESOLVE time and would break every
///    gunnar build on a machine with no sibling znippy checkout.
///  * the old znippy engine bench — a detached workspace one level deeper
///    still, inside an already-excluded crate.
///  * `bench/` — a detached workspace at the repository root.
///  * `installtest/` — simply not a member.
const NOT_IN_MEMBERS: &[&str] = &[
    // the deleted engine crate’s manifest and its nested `bench/` were the first
    // two entries here and are gone: the crate was DELETED on 2026-08-11. The
    // root manifest's `exclude` block had already recorded it as deleted on
    // 2026-08-10 while 5.0 GB of it — all build output, zero tracked files —
    // sat on disk, so `cargo xtask fmt` was still walking into it.
    //
    // Same shape as the `gunnar-znippy` deletion the floor below records. A
    // fixture that names a tree which no longer exists does not pin the gap it
    // was written for; it just fails.
    "bench/Cargo.toml",
    "installtest/Cargo.toml",
];

/// Discovery must be a filesystem walk. The `members` list is not the tree, and
/// a fmt built on it silently skipped 608 diffs across three trees.
#[test]
fn discovery_finds_the_four_trees_the_members_list_misses() {
    let root = root();
    let found: Vec<String> = package_manifests(&root)
        .iter()
        .map(|p| rel(&root, p))
        .collect();

    // First prove the fixture: `members` really does not name these.
    let manifest = std::fs::read_to_string(root.join("Cargo.toml")).expect("read root Cargo.toml");
    let members_block = {
        let a = manifest.find("members").expect("root has a members list");
        let b = manifest[a..].find(']').expect("members list closes") + a;
        &manifest[a..b]
    };
    for m in NOT_IN_MEMBERS {
        let dir = m.trim_end_matches("/Cargo.toml");
        assert!(
            !members_block.contains(&format!("\"{dir}\"")),
            "fixture is stale: `{dir}` IS in the members list now, so it no longer \
             demonstrates the gap this test exists to pin"
        );
    }

    // Now the claim.
    for m in NOT_IN_MEMBERS {
        assert!(
            found.iter().any(|f| f == m),
            "`{m}` is not in the discovered set, so `cargo xtask fmt` would skip it.\n\
             The `members` list is NOT the tree. Discovery must stay a filesystem \
             walk.\nFound: {found:#?}"
        );
    }
}

/// The virtual root manifest must never be handed to `cargo fmt
/// --manifest-path`: it exits with a usage error rather than doing nothing,
/// which is what made an earlier scoped fmt step fail for a reason that looked
/// like a formatting failure.
#[test]
fn discovery_skips_virtual_manifests_and_the_guard_fixtures() {
    let root = root();
    let found: Vec<String> = package_manifests(&root)
        .iter()
        .map(|p| rel(&root, p))
        .collect();

    assert!(
        !found.iter().any(|f| f == "Cargo.toml"),
        "the virtual root manifest must not be in the set: {found:#?}"
    );

    // The fixture workspaces under xtask/tests/fixtures are deliberately BROKEN
    // — each is the red-first proof of a dependency-guard rule — and are in the
    // root `exclude` list for that reason. They are asserted against, not
    // styled.
    let fixtures: Vec<&String> = found
        .iter()
        .filter(|f| f.contains("tests/fixtures"))
        .collect();
    assert!(
        fixtures.is_empty(),
        "guard fixtures must not be formatted, they are asserted against: {fixtures:#?}"
    );

    // Vendored third-party source is held VERBATIM. `vendor/gix-features` is
    // gix-features 0.49.0 plus six lines, carried as a `[patch]` until the fix
    // lands upstream; rustfmt would rewrite the other several thousand and the
    // diff against upstream would be gone. It is edition 2024 where this repo is
    // 2021, so it would even get a different import sort -- the exact
    // cross-repository damage this whole mechanism exists to stop, reproduced
    // inside our own tree.
    let vendored: Vec<&String> = found.iter().filter(|f| f.starts_with("vendor/")).collect();
    assert!(
        vendored.is_empty(),
        "vendored third-party source must never be reformatted: {vendored:#?}"
    );

    // **Other repositories parked inside this checkout.** Local tooling keeps
    // full sibling checkouts (edda, draupnir, …) under `.idea/worktrees` and
    // `.claude/worktrees`. A walk that descends into them formats other
    // repositories from inside this one — the damage this module exists to
    // stop, and it has arrived through BOTH directories now (`.idea`
    // 2026-08-16, `.claude` 2026-09-12: the tooling moved and the skip list
    // did not follow). Asserted by directory here, above the fixture check,
    // because a sibling's fixtures are only the part that happened to be
    // noticed — its ordinary crates were being swept in too.
    let parked: Vec<&String> = found
        .iter()
        .filter(|f| f.starts_with(".idea/") || f.starts_with(".claude/"))
        .collect();
    assert!(
        parked.is_empty(),
        "these manifests belong to other repositories parked inside this checkout and must \
         never be in this repository's fmt set: {parked:#?}"
    );

    // And the set must not be trivially empty, which would make both asserts
    // above pass while covering nothing.
    //
    // The floor was 20 and went red on 2026-08-10 when `crates/gunnar-znippy`
    // was deleted (the storage engine became a
    // feature of `gunnar-server` rather than a crate of its own). One manifest
    // fewer, and this is a floor, so the deletion is what moved it — not a
    // discovery regression. It is deliberately a floor and not an equality:
    // adding a crate must not fail a test whose subject is "the walk found
    // something".
    //
    // 19 -> 17 on 2026-08-11, and for the same reason a second time:
    // the old znippy engine crate was deleted, taking its own manifest AND the
    // nested the deleted engine crate’s nested bench manifest with it. Two deletions
    // have now moved this number and both are written down, because a floor
    // nobody explains is a floor the next person raises back.
    assert!(
        found.len() >= 17,
        "expected ~17 package manifests, found {}: {found:#?}",
        found.len()
    );
}

/// `xtask fmt` shells out to `cargo-fmt`, NOT to `cargo fmt` — because
/// `cargo fmt` is now the alias that lands back here, and that loop would not
/// terminate.
#[test]
fn the_formatter_invoked_is_cargo_fmt_itself_not_the_alias() {
    let bin = cargo_fmt_binary();
    let name = bin.file_name().and_then(|n| n.to_str()).unwrap_or("");
    assert_eq!(
        name, "cargo-fmt",
        "must invoke the `cargo-fmt` binary directly; going through `cargo fmt` \
         re-enters the alias and recurses"
    );
    assert_ne!(
        name, "cargo",
        "that is the alias, and it points back at this task"
    );
}

/// Mode is an argument, not a default that happens to be right. `Check` and
/// `Write` must be distinguishable — an enum whose variants compare equal would
/// make every "did we check or did we write?" assertion vacuous.
#[test]
fn check_and_write_are_distinguishable() {
    assert_ne!(Mode::Check, Mode::Write);
}