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

nordisk/holger

holger-recipe/tests/mvp_formats.rs

//! **The MVP suite serves the MVP formats, and so does `cargo install holger`**
//! (lane HOL-MVP-FORMATS, owner 2026-10-30: "holger.rs must serve every format of the MVP
//! suite, but not every format in the source").
//!
//! The MVP format set is twelve formats: raw, Rust, npm, Maven, Python, Docker/OCI, Go,
//! Helm, deb, rpm, the znippy package and the Build Thing's history. Before this, the MVP server rows (holger.rs's payload among them) carried
//! raw, Rust and npm only, while the suite's own downstream carried Maven, Python, OCI and Go:
//! an MVP downstream could serve formats its MVP upstream could not.
//!
//! Held here, over the declared rows and server/cli's manifest (no cargo process):
//!
//! * every MVP server row of the `holger` package (the open, the metered and both musl
//!   payloads, their DEV rows, and the downstream medium) serves exactly the twelve;
//! * server/cli's `default` (`cargo install holger`) serves exactly the same twelve;
//! * no such row or default names a format outside the twelve (NuGet, gems, conda,
//!   Composer) or `fmt-all`: those stay opt-in features;
//! * every MVP server row carries `sync`, and none carries `online` (the MVP is zero-egress
//!   by design, `.nornir/SUITES.md` "MVP OMITS online").

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

use holger_recipe::variants::{variants, SERVER_CLI};
use nornir_build_thing::plugin::Role;

/// The MVP format set, as server/cli's own feature names.
const MVP_FORMATS: [&str; 12] = [
    "fmt-raw",
    "fmt-rust",
    "fmt-npm",
    "fmt-maven",
    "fmt-python",
    "fmt-docker",
    "fmt-go",
    "fmt-helm",
    "fmt-deb",
    "fmt-rpm",
    "fmt-znippy",
    "fmt-build-thing",
];

/// The formats the source has and the MVP does not serve (opt-in only), and the umbrella.
const NOT_MVP: [&str; 5] = [
    "fmt-all",
    "fmt-nuget",
    "fmt-gem",
    "fmt-conda",
    "fmt-composer",
];

fn repo_root() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .parent()
        .unwrap()
        .to_path_buf()
}

fn cli_features() -> toml::value::Table {
    let p = repo_root().join("server/cli/Cargo.toml");
    let text = std::fs::read_to_string(&p).unwrap_or_else(|e| panic!("read {}: {e}", p.display()));
    let m: toml::Value =
        toml::from_str(&text).unwrap_or_else(|e| panic!("parse {}: {e}", p.display()));
    m["features"].as_table().expect("[features]").clone()
}

/// Every server/cli feature `roots` turn on, followed through the manifest. A server-lib
/// format named straight (`server-lib/fmt-maven`) counts as that format, so a row cannot
/// serve a format by going around server/cli's own feature.
fn closure(table: &toml::value::Table, roots: &[String]) -> BTreeSet<String> {
    let mut seen = BTreeSet::new();
    let mut todo: Vec<String> = roots.to_vec();
    while let Some(f) = todo.pop() {
        let f = match f.strip_prefix("server-lib/") {
            Some(s) if s.starts_with("fmt-") => s.to_string(),
            Some(_) => continue,
            None if f.contains('/') || f.starts_with("dep:") => continue,
            None => f,
        };
        if !seen.insert(f.clone()) {
            continue;
        }
        if let Some(sub) = table.get(&f).and_then(|v| v.as_array()) {
            todo.extend(sub.iter().filter_map(|v| v.as_str()).map(String::from));
        }
    }
    seen
}

fn formats(set: &BTreeSet<String>) -> BTreeSet<String> {
    set.iter()
        .filter(|f| f.starts_with("fmt-"))
        .cloned()
        .collect()
}

fn mvp() -> BTreeSet<String> {
    MVP_FORMATS.iter().map(|s| s.to_string()).collect()
}

/// The MVP server rows of the `holger` package, with the features each one turns on.
fn mvp_server_rows() -> Vec<(String, BTreeSet<String>)> {
    let table = cli_features();
    let default: Vec<String> = table["default"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(|v| v.as_str())
        .map(String::from)
        .collect();
    variants()
        .into_iter()
        .filter(|v| {
            v.package.as_deref() == Some(SERVER_CLI)
                && v.role == Some(Role::Server)
                && v.suites.iter().any(|s| s == "MVP")
        })
        .map(|v| {
            let mut roots = v.features.clone();
            if !v.no_default_features {
                roots.extend(default.iter().cloned());
            }
            (v.name.clone(), closure(&table, &roots))
        })
        .collect()
}

#[test]
fn every_mvp_server_row_serves_exactly_the_twelve_mvp_formats() {
    let rows = mvp_server_rows();
    let names: BTreeSet<&str> = rows.iter().map(|(n, _)| n.as_str()).collect();
    // The product `holger` (its default) and the estate's builds of the server (HOL-PRODUCTS);
    // the downstream's crate is held below.
    for must in [
        "holger",
        "mvp-server-metered",
        "mvp-server-musl",
        "mvp-server-musl-metered",
    ] {
        assert!(
            names.contains(must),
            "no MVP server row `{must}` among {names:?}"
        );
    }
    let mut bad = Vec::new();
    for (name, set) in &rows {
        let got = formats(set);
        if got != mvp() {
            let want = mvp();
            let missing: Vec<&String> = want.difference(&got).collect();
            let extra: Vec<&String> = got.difference(&want).collect();
            bad.push(format!(
                "{name}: missing {missing:?}, outside the MVP set {extra:?}"
            ));
        }
        for f in NOT_MVP {
            if set.contains(f) {
                bad.push(format!("{name}: names `{f}`, which is no MVP format"));
            }
        }
    }
    assert!(
        bad.is_empty(),
        "the MVP server rows do not serve the MVP format set {MVP_FORMATS:?}:\n  {}",
        bad.join("\n  ")
    );
}

/// `cargo install holger-downstream` is the server's `downstream` (its one dependency edge),
/// and serves the same twelve.
#[test]
fn the_downstream_crate_serves_the_same_twelve_formats() {
    let table = cli_features();
    let down = closure(&table, &["downstream".to_string()]);
    assert_eq!(
        formats(&down),
        mvp(),
        "`cargo install holger-downstream` serves the MVP format set"
    );
    let m: toml::Value = toml::from_str(
        &std::fs::read_to_string(repo_root().join("holger-downstream/Cargo.toml")).unwrap(),
    )
    .unwrap();
    let edge = &m["dependencies"]["holger"];
    assert_eq!(edge["default-features"].as_bool(), Some(false));
    let feats: Vec<&str> = edge["features"]
        .as_array()
        .unwrap()
        .iter()
        .filter_map(|v| v.as_str())
        .collect();
    assert_eq!(
        feats,
        ["downstream"],
        "the product is the server's `downstream` and nothing else"
    );
}

#[test]
fn the_default_install_serves_the_same_twelve_formats() {
    let table = cli_features();
    let default = closure(&table, &["default".to_string()]);
    assert_eq!(
        formats(&default),
        mvp(),
        "`cargo install holger` (server/cli `default`) serves the MVP format set"
    );
    for f in NOT_MVP {
        assert!(
            !default.contains(f),
            "`cargo install holger` names `{f}`, which is no MVP format"
        );
    }
    assert!(!default.contains("online"), "the default stays zero-egress");
}

#[test]
fn every_mvp_server_row_carries_sync_and_never_online() {
    for (name, set) in mvp_server_rows() {
        assert!(
            set.contains("sync"),
            "{name}: the MVP server rows carry `sync` (the MVP downstream already does)"
        );
        assert!(!set.contains("online"), "{name}: the MVP is zero-egress by design (SUITES.md \"MVP OMITS online\"); `online` is no MVP feature");
    }
}

/// Each of the twelve is server/cli's own passthrough to the server-lib format of the same
/// name, so a row names `fmt-helm`, never `server-lib/fmt-helm`.
#[test]
fn each_mvp_format_is_a_server_cli_passthrough() {
    let table = cli_features();
    for f in MVP_FORMATS {
        let v: Vec<&str> = table
            .get(f)
            .unwrap_or_else(|| panic!("server/cli declares no feature `{f}`"))
            .as_array()
            .unwrap()
            .iter()
            .filter_map(|v| v.as_str())
            .collect();
        assert_eq!(
            v,
            [format!("server-lib/{f}").as_str()],
            "server/cli `{f}` is the passthrough to server-lib `{f}`"
        );
    }
    // And no feature of server/cli names a server-lib format around its passthrough.
    for (name, list) in &table {
        // `all-formats` is the opt-in of every format (its old name `fmt-all` is NOT_MVP's).
        if MVP_FORMATS.contains(&name.as_str())
            || NOT_MVP.contains(&name.as_str())
            || name == "all-formats"
        {
            continue;
        }
        for v in list
            .as_array()
            .into_iter()
            .flatten()
            .filter_map(|v| v.as_str())
        {
            if let Some(f) = v
                .strip_prefix("server-lib/")
                .filter(|f| f.starts_with("fmt-"))
            {
                assert!(
                    !MVP_FORMATS.contains(&f),
                    "server/cli `{name}` names `{v}`; name the passthrough `{f}`"
                );
            }
        }
    }
}