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

nordisk/nornir

tests/workspace_holger.rs

//! End-to-end: load a workspace descriptor pointing at the real
//! sibling `holger` and `znippy` checkouts, build the cross-repo dep
//! graph, derive the build order, persist into a fresh
//! IcebergWarehouse, reopen the warehouse, query it back, and assert
//! the snapshot round-trips.
//!
//! Skipped automatically if the sibling clones aren't present (so CI
//! and other machines don't fail loudly).

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

use nornir::warehouse::dep_graph;
use nornir::warehouse::iceberg::IcebergWarehouse;
use nornir::workspace::WorkspaceDescriptor;

fn sibling(name: &str) -> Option<PathBuf> {
    let here = Path::new(env!("CARGO_MANIFEST_DIR"));
    let candidate = here.parent()?.join(name);
    if candidate.join("Cargo.toml").is_file() {
        Some(candidate)
    } else {
        None
    }
}

#[test]
fn holger_znippy_workspace_graph_and_persistence() {
    let Some(holger) = sibling("holger") else {
        eprintln!("[skip] ../holger not checked out next to nornir/");
        return;
    };
    let Some(znippy) = sibling("znippy") else {
        eprintln!("[skip] ../znippy not checked out next to nornir/");
        return;
    };

    let tmp = tempfile::tempdir().expect("tempdir");
    let toml = format!(
        r#"[workspace]
name = "holger-suite"

[repos.holger]
path = "{}"

[repos.znippy]
path = "{}"
"#,
        holger.display(),
        znippy.display()
    );
    let toml_path = tmp.path().join("nornir-workspace.toml");
    std::fs::write(&toml_path, toml).expect("write workspace toml");

    // ─── 1. parse + build graph ─────────────────────────────────────
    let desc = WorkspaceDescriptor::load(&toml_path).expect("load descriptor");
    let graph = dep_graph::build(&desc).expect("build graph");

    assert!(
        graph.facts.contains_key("holger") && graph.facts.contains_key("znippy"),
        "both repos must be inspected"
    );

    let holger_to_znippy = graph
        .dependencies_of("holger")
        .into_iter()
        .find(|e| e.to == "znippy")
        .expect("expected edge holger -> znippy");
    for crate_name in ["znippy-common", "znippy-compress"] {
        assert!(
            holger_to_znippy.via.contains(crate_name),
            "edge holger->znippy missing crate `{crate_name}` in via set: {:?}",
            holger_to_znippy.via
        );
    }

    assert!(
        graph
            .dependencies_of("znippy")
            .iter()
            .all(|e| e.to != "holger"),
        "found illegal reverse edge znippy -> holger"
    );

    // ─── 2. build order: deps first ────────────────────────────────
    let order = graph.build_order().expect("toposort");
    let pos_z = order
        .iter()
        .position(|n| n == "znippy")
        .expect("znippy in order");
    let pos_h = order
        .iter()
        .position(|n| n == "holger")
        .expect("holger in order");
    assert!(
        pos_z < pos_h,
        "build order must put znippy before holger; got {order:?}"
    );

    // ─── 3. persist into warehouse ─────────────────────────────────
    let wh_root = tmp.path().join("warehouse-root");
    let wh = IcebergWarehouse::open(&wh_root).expect("open IcebergWarehouse");
    let snap_id = wh
        .block_on(dep_graph::record_dep_graph(&wh, "holger-suite", &graph))
        .expect("record snapshot");

    // ─── 4. reopen + query ────────────────────────────────────────
    drop(wh);
    let wh2 = IcebergWarehouse::open(&wh_root).expect("reopen warehouse");
    let snaps = wh2
        .block_on(dep_graph::query_dep_graph_snapshots(
            &wh2,
            "holger-suite",
            None,
        ))
        .expect("query snapshots");
    assert_eq!(snaps.len(), 1, "expected exactly one snapshot");
    let snap = &snaps[0];
    assert_eq!(snap.snapshot_id, snap_id);
    assert_eq!(snap.workspace_name, "holger-suite");

    let persisted_edge = snap
        .edges
        .iter()
        .find(|e| e.from == "holger" && e.to == "znippy")
        .expect("persisted edge holger->znippy");
    assert!(persisted_edge.via.contains("znippy-common"));
    assert!(persisted_edge.via.contains("znippy-compress"));
}