crates/nornir-build-thing/tests/lazy_edge.rs
//! **A lazy consumption edge** — `lazy = true` on `[build.<kind>.edges.<feature>]`.
//!
//! An open product (holger) declares one row that consumes a guest built by a
//! COMMERCIAL checkout. Every other row must load, list and build in a tree where
//! that checkout is absent. A lazy edge is type-checked against its donor when
//! the donor is beside the consumer, and left unresolved at load when it is not;
//! the build of the row that carries it is still refused by name.
use nornir_build_thing::build_dag::{BesideCheckouts, BuildDag, BuildLine, Coordinate};
use nornir_build_thing::suite_cli;
use nornir_build_thing::variant::BuildVariantSet;
const OPEN: &str = r#"
[[build.variant]]
name = "open"
package = "app"
bin = "app"
[[build.variant]]
name = "sold"
package = "app"
bin = "app-sold"
[build.variant.edges.plugin]
repo = "commercial"
variant = "guest"
typ = "wasm"
lazy = true
"#;
fn tree(donor_kind: Option<&str>) -> tempfile::TempDir {
let base = tempfile::tempdir().unwrap();
let app = base.path().join("app");
std::fs::create_dir_all(app.join(".nornir")).unwrap();
std::fs::write(app.join(".nornir/build-variants.toml"), OPEN).unwrap();
if let Some(kind) = donor_kind {
let c = base.path().join("commercial/.nornir");
std::fs::create_dir_all(&c).unwrap();
std::fs::write(
c.join("build-variants.toml"),
format!("[[build.variant]]\nname = \"guest\"\nkind = \"{kind}\"\ntarget = \"wasm32-unknown-unknown\"\n"),
)
.unwrap();
}
base
}
#[test]
fn a_lazy_edge_with_its_donor_absent_loads_and_lists() {
let t = tree(None);
let app = t.path().join("app");
let set = BuildVariantSet::discover_validated(&app)
.unwrap_or_else(|e| panic!("{e:#}"))
.expect("declared");
let edges = set.edges_of("sold").unwrap();
assert_eq!(edges.len(), 1);
assert!(edges[0].1.lazy, "the edge stays declared, marked lazy");
let lines = suite_cli::list_resolved(&app, &suite_cli::parse(&["--list"]).unwrap()).unwrap_or_else(|e| panic!("{e:#}"));
assert!(lines.iter().any(|l| l.contains("sold")), "{lines:?}");
}
#[test]
fn a_lazy_edge_with_its_donor_present_is_type_checked() {
let ok = tree(Some("wasm"));
BuildVariantSet::discover_validated(&ok.path().join("app")).unwrap_or_else(|e| panic!("{e:#}"));
let bad = tree(Some("exe"));
let e = format!("{:#}", BuildVariantSet::discover_validated(&bad.path().join("app")).unwrap_err());
assert!(e.contains("commercial"), "{e}");
}
#[test]
fn building_the_row_that_carries_a_lazy_edge_without_its_donor_is_refused_by_name() {
let t = tree(None);
let app = t.path().join("app");
let decls = BesideCheckouts::of(&app);
let target = Coordinate::new(decls.own.clone(), "sold");
let e = format!("{:#}", BuildDag::derive(&target, &BuildLine::parse("--build plugin").unwrap(), &decls).unwrap_err());
assert!(e.contains("no checkout 'commercial'"), "{e}");
}
#[test]
fn a_lazy_edge_round_trips_and_an_eager_one_stays_unspelled() {
let t = tree(None);
let set = BuildVariantSet::discover(&t.path().join("app")).unwrap().unwrap();
let text = toml::to_string(&nornir_build_thing::variant::BuildConfig::emitting(&set)).unwrap();
assert!(text.contains("lazy = true"), "{text}");
assert_eq!(text.matches("lazy").count(), 1, "{text}");
}
#[test]
fn an_eager_edge_with_its_donor_absent_is_still_refused_at_load() {
let base = tempfile::tempdir().unwrap();
let app = base.path().join("app");
std::fs::create_dir_all(app.join(".nornir")).unwrap();
std::fs::write(app.join(".nornir/build-variants.toml"), OPEN.replace("lazy = true\n", "")).unwrap();
let e = format!("{:#}", BuildVariantSet::discover_validated(&app).unwrap_err());
assert!(e.contains("no checkout 'commercial' beside"), "{e}");
}