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

mikronova/modgunn

tests/testmatrix_wiring.rs

//! L4 wiring proof for modgunn's `functional_status` introspection markers.
//!
//! The newest feature (`feat(testmatrix)`) wired [`modgunn::functional_status`]
//! markers onto modgunn's functional surfaces — Engine A's `OsvScanner` verdict,
//! Engine B's `scip` world-delta diff, the lib-level marker wrapper — so
//! `nornir test` SEES each surface. Those emits shipped with no test that proves
//! they actually LAND.
//!
//! This is that inject-and-assert proof (project LAW: real inject/assert, never
//! "didn't panic"): it DRIVES the real surfaces, then drains the process-global
//! functional buffer ([`nornir_testmatrix::drain_functional_rows`]) and asserts
//! the emitted rows carry the right component / check / verdict (a clean verdict
//! is GREEN, a blocking / drifting one is RED). Fully offline, no cargo
//! subprocess, no network.
//!
//! The whole file is `#![cfg(feature = "testmatrix")]`: without the feature the
//! emitter is a compiled-out no-op (no nornir dep in the lean `scan` build), so
//! there is nothing to prove and this test crate compiles to nothing — matching
//! the release-gating contract the markers are built on.
#![cfg(feature = "testmatrix")]

use modgunn::core::{ArtifactRef, Severity};
use modgunn::scan::{
    Advisory, AdvisoryDb, Artifact, LicensePolicy, OsvScanner, Policy, Provenance, ScanEngine,
};
use nornir_testmatrix::{drain_functional_rows, status, TestResultRow};

fn aref(ecosystem: &str, name: &str, version: &str) -> ArtifactRef {
    ArtifactRef {
        ecosystem: ecosystem.into(),
        name: name.into(),
        version: version.into(),
        blob_sha256: format!("{name}-{version}-sha"),
    }
}

/// A scanner with an allow-list license policy and one High-severity cargo
/// advisory for `openssl@0.1.0`, so a clean dep passes and the vulnerable one
/// blocks.
fn scanner() -> OsvScanner {
    let policy = Policy {
        version: "policy-wiring".into(),
        license: LicensePolicy::allowlist(["MIT", "Apache-2.0"]),
        ..Default::default()
    };
    let advisories = AdvisoryDb::new(
        "db-wiring",
        vec![
            Advisory::basic(
                "RUSTSEC-2024-0001",
                "cargo",
                "openssl",
                vec!["0.1.0".into()],
                Severity::High,
                "use-after-free in openssl",
            ),
            // A Low-severity advisory → a `Warn` gate decision (not Block): the
            // third, previously-undriven verdict branch, so `nornir test` SEES
            // Pass · Warn · Block on the matrix — not only the allow/deny extremes.
            Advisory::basic(
                "CVE-2099-LOWSEV",
                "cargo",
                "leftpad",
                vec!["1.0.0".into()],
                Severity::Low,
                "low-severity informational advisory in leftpad",
            ),
        ],
    );
    OsvScanner::new(policy, advisories)
}

/// Find the single row a surface emitted for `component` / `check`.
fn row<'a>(rows: &'a [TestResultRow], component: &str, check: &str) -> &'a TestResultRow {
    let hits: Vec<_> = rows
        .iter()
        .filter(|r| r.suite == component && r.test_name == check)
        .collect();
    assert_eq!(
        hits.len(),
        1,
        "expected exactly one `{component}` / `{check}` row, got {}: {:#?}",
        hits.len(),
        rows,
    );
    hits[0]
}

/// One test function drives every surface and drains once, so the shared
/// process-global buffer is never raced by a parallel sibling test.
#[test]
fn functional_status_markers_land_on_the_matrix() {
    // Start from a clean buffer (ignore any rows an earlier drive left).
    let _ = drain_functional_rows();

    let scanner = scanner();

    // ── Engine A: a clean, signed, allow-listed dep → Pass → GREEN row. ──────
    let clean = Artifact::new(
        aref("cargo", "serde", "1.0.0"),
        Some("MIT".into()),
        Provenance::signed_by("nordisk-ci"),
    );
    let v = scanner.scan(&clean);
    assert_eq!(v.decision, modgunn::core::Decision::Pass);

    // ── Engine A: a known High vuln → Block → RED row. ──────────────────────
    let vuln = Artifact::new(
        aref("cargo", "openssl", "0.1.0"),
        Some("Apache-2.0".into()),
        Provenance::signed_by("nordisk-ci"),
    );
    let v = scanner.scan(&vuln);
    assert_eq!(v.decision, modgunn::core::Decision::Block);

    // ── Engine A: a Low-severity advisory → Warn → GREEN (not blocked) row. ──
    let warn = Artifact::new(
        aref("cargo", "leftpad", "1.0.0"),
        Some("MIT".into()),
        Provenance::signed_by("nordisk-ci"),
    );
    let v = scanner.scan(&warn);
    assert_eq!(
        v.decision,
        modgunn::core::Decision::Warn,
        "a Low advisory warns, not blocks"
    );

    // ── lib-level marker wrapper: proves the `#[inline]` wrapper is a LIVE
    //    recorder under the feature (not the release no-op). ──────────────────
    modgunn::functional_status(
        "modgunn/lib-marker",
        "wrapper_records",
        true,
        "functional_status wrapper is live under --features testmatrix",
    );

    // ── Engine B (feature `scip`): a no-change diff → GREEN, a drift → RED. ──
    #[cfg(feature = "scip")]
    scip_drive();

    // ── Drain once and assert on the REAL rows the surfaces recorded. ───────
    let rows = drain_functional_rows();

    // Two scan_verdict rows were emitted (clean + vuln); assert both verdicts are
    // present with the right colour among the engine-a rows.
    let verdicts: Vec<_> = rows
        .iter()
        .filter(|r| r.suite == "modgunn/engine-a-osv-scanner" && r.test_name == "scan_verdict")
        .collect();
    assert_eq!(verdicts.len(), 3, "one row per scan: clean + vuln + warn");
    assert!(
        verdicts.iter().any(|r| status::is_green(&r.status)),
        "the clean Pass verdict emits a GREEN row: {verdicts:#?}",
    );
    assert!(
        verdicts.iter().any(|r| status::is_red(&r.status)),
        "the blocking vuln verdict emits a RED row: {verdicts:#?}",
    );
    // The detail carries the artifact + decision the field can read at a glance.
    assert!(
        verdicts
            .iter()
            .any(|r| r.message.contains("openssl") && r.message.contains("Block")),
        "the blocking row names the artifact + decision: {verdicts:#?}",
    );

    // The engine-agnostic verdict-assembly surface emits one row PER assembled
    // verdict too (Engine A's `OsvScanner::scan` routes through `Policy::assemble`).
    // Both scans above drove it, so assert the allow/deny branches both landed.
    let assembly: Vec<_> = rows
        .iter()
        .filter(|r| r.suite == "modgunn/verdict-assembly" && r.test_name == "policy_decision")
        .collect();
    assert_eq!(
        assembly.len(),
        3,
        "one verdict-assembly row per assembled verdict: clean + vuln + warn"
    );
    assert!(
        assembly.iter().any(|r| status::is_green(&r.status)),
        "the clean Pass assembly emits a GREEN (allow) row: {assembly:#?}",
    );
    assert!(
        assembly.iter().any(|r| status::is_red(&r.status)),
        "the blocking assembly emits a RED (deny) row: {assembly:#?}",
    );
    assert!(
        assembly
            .iter()
            .any(|r| r.message.contains("openssl") && r.message.contains("Block")),
        "the deny row names the artifact + decision: {assembly:#?}",
    );
    // The Warn branch: a Low advisory → Warn → not-blocked ⇒ GREEN, and the detail
    // names the decision so the field can tell a warn from a clean pass at a glance.
    assert!(
        assembly.iter().any(|r| r.message.contains("leftpad")
            && r.message.contains("Warn")
            && status::is_green(&r.status)),
        "the Warn assembly emits a GREEN row naming the Warn decision: {assembly:#?}",
    );

    let wrapper = row(&rows, "modgunn/lib-marker", "wrapper_records");
    assert!(
        status::is_green(&wrapper.status),
        "the ok=true wrapper emit lands as a GREEN row: {wrapper:#?}",
    );
    assert_eq!(
        wrapper.aspect, "functional",
        "markers ride the `functional` aspect"
    );

    #[cfg(feature = "scip")]
    {
        // Two behavior_diff rows (no-change + drift); assert both colours.
        let diffs: Vec<_> = rows
            .iter()
            .filter(|r| r.suite == "modgunn/engine-b-scip" && r.test_name == "behavior_diff")
            .collect();
        assert_eq!(diffs.len(), 2, "one row per diff: no-change + drift");
        assert!(
            diffs.iter().any(|r| status::is_green(&r.status)),
            "an identical-snapshot diff (no tripwire finding) is GREEN: {diffs:#?}",
        );
        assert!(
            diffs.iter().any(|r| status::is_red(&r.status)),
            "a newly-reachable-sink drift is RED: {diffs:#?}",
        );
    }
}

/// Drive Engine B's `scip::diff`: an identical-snapshot diff (no finding → GREEN)
/// and a diff where a vulnerable sink becomes reachable (a tripwire fires → RED).
#[cfg(feature = "scip")]
fn scip_drive() {
    use modgunn::scip::{diff, CallEdge, Capability, Symbol, VulnSink, WorldSnapshot};

    let base = || {
        let mut s = WorldSnapshot::new("snap-1");
        s.symbols = vec![
            Symbol::new("main", "app@1.0.0").entrypoint(),
            Symbol::new("mid", "midlib@1.0.0"),
            Symbol::new("net_sink", "netlib@1.0.0").with_capability(Capability::Network),
            Symbol::new("dead", "deadlib@1.0.0"),
        ];
        s.calls = vec![
            CallEdge::new("main", "mid"),
            CallEdge::new("mid", "net_sink"),
        ];
        s.vuln_sinks = vec![VulnSink {
            symbol: "dead".into(),
            advisory: "CVE-DEAD".into(),
            severity: Severity::High,
        }];
        s
    };

    // No-change diff: identical snapshots → no tripwire finding → GREEN row.
    let from = base();
    let same = base();
    let clean = diff(&from, &same);
    assert!(
        clean.findings.is_empty(),
        "identical snapshots have no delta"
    );

    // Drift diff: `dead` (a High vuln) becomes reachable from `main` → RED row.
    let mut to = base();
    to.id = "snap-2".into();
    to.calls.push(CallEdge::new("main", "dead"));
    let drifted = diff(&from, &to);
    assert!(
        !drifted.findings.is_empty(),
        "a newly-reachable sink is a delta"
    );
}