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

nordisk/dwarves

dwarves-gui/tests/common/mod.rs

//! **A canned code room behind a REAL forge proxy** — the stand every code-graph
//! pane's robot test drives the SHIPPED shell on:
//!
//! ```text
//!   mock nornir (Warehouse + CodeRoom) ── dwarves warehouse-proxy (:auto) ── the shell
//! ```
//!
//! The room's answers are written here ONCE, in the reader's own shapes, and are
//! consistent with each other (one small workspace: repo `shop`, crates `shop` and
//! `shop-core`, the dependency `serde`). A test asserts that what a pane's
//! `state_json` holds IS these values — and that a refused answer leaves the state
//! and no number.
#![allow(dead_code)]

use nornir_warehouse_embed::testkit::{spawn_mock_nornir, MockCodeRoom, MockWarehouseServer};
use serde_json::{json, Value};

/// The workspace the shell selects.
pub const WS: &str = "shop-ws";
/// The room line every pane prints for an answer read from [`room_id`].
pub const ROOM_LINE: &str = "workspace shop-ws · shop@2 (0123456789) · 985 nodes · 2310 edges";
/// The sentence nornir gives for the two world-ring surfaces.
pub const COMPAT_NOTE: &str = "Coderoom.Compat: the world ring (crates.io sources of other crates, COMPATIBLE edges, semver diffs) has no v2 producer (gap P5)";
pub const BREAKS_NOTE: &str = "Coderoom.WhatBreaks: the registry versions of other crates (the world ring) are not ingested (gap P5)";
/// The sentence of a workspace nothing was consumed into.
pub const NOT_CONSUMED: &str = "code room of `shop-ws`: no repo has a consumer offset yet — nothing of this workspace was consumed";

pub fn room_id() -> Value {
    json!({
        "workspace": WS, "universe": false, "nodes": 985, "edges_total": 2310,
        "repos": [{ "repo": "shop", "seq": 2, "sha": "0123456789abcdef0123" }],
        "edges": { "CALLS": 1400, "CONTAINS": 700, "DEPENDS_ON": 3 },
    })
}

fn evidence(notes: &[&str]) -> Value {
    json!({ "missing": [], "notes": notes })
}

pub fn refusal(state: &str, note: &str) -> Value {
    json!({ "state": state, "refused": true, "note": note })
}

/// `Viz.CrateGraph`.
pub fn crate_graph() -> Value {
    json!({
        "state": "complete",
        "crates": [
            { "id": "serde@1.0.228", "name": "serde", "version": "1.0.228", "repo": null, "local": false, "nodes": 900, "symbols": 310, "fns": 200, "files": 0, "calls_inside": 0 },
            { "id": "shop-core@0.1.0", "name": "shop-core", "version": "0.1.0", "repo": "shop", "local": true, "nodes": 25, "symbols": 12, "fns": 9, "files": 2, "calls_inside": 5 },
            { "id": "shop@0.1.0", "name": "shop", "version": "0.1.0", "repo": "shop", "local": true, "nodes": 60, "symbols": 41, "fns": 30, "files": 4, "calls_inside": 22 },
        ],
        "edges": [
            { "from": "shop-core@0.1.0", "to": "serde@1.0.228", "depends_on": 1, "calls": 0, "call_sites": 0, "uses_type": 0 },
            { "from": "shop@0.1.0", "to": "serde@1.0.228", "depends_on": 1, "calls": 3, "call_sites": 4, "uses_type": 0 },
            { "from": "shop@0.1.0", "to": "shop-core@0.1.0", "depends_on": 1, "calls": 7, "call_sites": 19, "uses_type": 2 },
        ],
        "repos": [{ "repo": "shop", "seq": 2, "sha": "0123456789abcdef0123", "crates": ["shop-core@0.1.0", "shop@0.1.0"], "consumes": ["serde", "shop-core"] }],
        "repo_edges": [],
        "evidence": evidence(&["calls through operators, closures and fn pointers are not recorded: a lower bound"]),
        "room": room_id(),
    })
}

/// `Coderoom.SnapshotDiff` for `shop`.
pub fn snapshot_diff() -> Value {
    json!({
        "state": "complete", "from": "shop@1", "to": "shop@2",
        "added_nodes": 3, "removed_nodes": 1, "changed_nodes": 2,
        "by_crate": {
            "crates_added": ["log@0.4.29"], "crates_removed": [],
            "crates": [{ "crate": "shop@0.1.0", "symbols_added": 2, "symbols_removed": 1, "symbols_changed": 2, "nodes_added": 3, "nodes_removed": 1, "nodes_changed": 2 }],
        },
        "evidence": evidence(&[]),
    })
}

/// `Viz.FunctionTier`.
pub fn function_tier() -> Value {
    json!({
        "state": "complete",
        "repos": [{
            "repo": "shop",
            "crates": [
                { "crate": "shop", "version": "0.1.0", "total_fns": 3, "total_calls": 2,
                  "fns": [{ "id": "shop::checkout", "name": "checkout" }, { "id": "shop::pay::charge", "name": "charge" }, { "id": "shop::pay::audit", "name": "audit" }],
                  "calls": [[0, 1, 3], [1, 2, 2]] },
                { "crate": "shop-core", "version": "0.1.0", "total_fns": 1, "total_calls": 0, "fns": [{ "id": "shop_core::total", "name": "total" }], "calls": [] },
            ],
        }],
        "total_fns": 4, "total_calls": 2,
        "evidence": evidence(&["a lower bound"]),
        "room": room_id(),
    })
}

/// `Knowledge.Symbols`.
pub fn symbols() -> Value {
    let sym = |name: &str, line: u32, end: u32| {
        json!({
            "repo": "shop", "crate_name": "shop", "module_path": "shop::pay", "item_kind": "fn", "item_name": name, "visibility": "pub",
            "file": "src/pay.rs", "line": line, "end_line": end, "path": format!("shop::pay::{name}"), "moniker": format!("m:{name}"),
        })
    };
    json!({
        "state": "complete", "total": 53, "by_kind": { "fn": 39, "struct": 6 },
        "symbols": [sym("charge", 7, 22), sym("audit", 24, 30), sym("open", 32, 36)],
        "evidence": { "missing": [], "notes": [], "capped": { "shown": 3, "total": 53 } },
        "room": room_id(),
    })
}

/// `Viz.CallGraph`.
pub fn call_graph() -> Value {
    let node = |id: &str, m: &str| json!({ "id": id, "moniker": m, "crate": "shop", "kind": "fn", "provenance": "source_only", "file": "src/pay.rs", "line": 7 });
    json!({
        "state": "complete", "total_edges": 31,
        "nodes": [node("shop::checkout", "m:checkout"), node("shop::pay::charge", "m:charge"), node("shop::pay::audit", "m:audit")],
        "edges": [{ "from": 0, "to": 1, "sites": 3 }, { "from": 1, "to": 2, "sites": 2 }],
        "evidence": { "missing": [], "notes": ["a lower bound"], "capped": { "shown": 2, "total": 31 } },
        "room": room_id(),
    })
}

/// `Knowledge.Source` (whatever node is asked: the mock answers per surface).
pub fn source() -> Value {
    json!({
        "state": "complete",
        "node": { "path": "shop::pay::charge", "moniker": "m:charge", "kind": "fn", "crate": "shop", "repo": "shop", "file": "src/pay.rs", "line": 7, "end_line": 9, "defined": true },
        "candidates": [{ "path": "shop::pay::charge" }],
        "repo": "shop", "file": "src/pay.rs", "start_line": 7, "end_line": 9, "sha": "0123456789abcdef0123",
        "lines": ["pub fn charge(cart: &Cart) -> Receipt {", "    audit(cart);", "}"],
        "file_lines": 48, "truncated": false,
        "evidence": evidence(&[]),
        "room": room_id(),
    })
}

/// `Knowledge.TestReach`: four fns of `shop` (two reached), one test.
pub fn test_reach() -> Value {
    let f = |module: &str,
             name: &str,
             file: &str,
             line: u32,
             reachable: bool,
             fan_in: u32,
             test_code: bool| {
        json!({
            "repo": "shop", "crate_name": "shop", "module": module, "module_path": module, "item_name": name, "fqn": format!("{module}::{name}"),
            "kind": "fn", "visibility": "pub", "file": file, "line": line, "test_code": test_code, "test_reachable": reachable, "fan_in": fan_in,
        })
    };
    json!({
        "state": "complete",
        "files": [{ "repo": "shop", "file": "src/pay.rs" }, { "repo": "shop", "file": "src/lib.rs" }],
        "fns": [
            f("shop", "checkout", "src/lib.rs", 10, true, 1, false),
            f("shop::pay", "charge", "src/pay.rs", 7, true, 4, false),
            f("shop::pay", "audit", "src/pay.rs", 24, false, 2, false),
            f("shop::pay", "open", "src/pay.rs", 32, false, 0, false),
            f("shop::pay", "charges_once", "src/pay.rs", 40, false, 0, true),
        ],
        "tests": [{
            "repo": "shop", "crate_name": "shop", "module": "shop::pay", "module_path": "shop::pay", "test_name": "charges_once", "fqn": "shop::pay::charges_once",
            "file": "src/pay.rs", "line": 40, "calls_out": 1, "names": 1, "reached": 2, "files": [0, 1],
        }],
        "surface_fns": 4, "test_reachable": 2, "tests_total": 1,
        "evidence": evidence(&["calls through operators, closures and fn pointers are not recorded: a lower bound"]),
        "room": room_id(),
    })
}

/// Every surface the panes ask, answered.
///
/// **The red-proof knob.** `DWARVES_BREAK_FEED=<surface>[,<surface>…]` leaves those
/// surfaces UNFED — the mock then answers them as the reader answers a name it does not
/// serve (a refusal). Each `robot_*_room` test asserts the pane's VALUES, so with its
/// surface broken it must go red: that is the check that what the pane shows came from
/// the feed and from nowhere else. E.g.
/// `DWARVES_BREAK_FEED=Viz.CrateGraph cargo test -p dwarves-gui --test robot_coderoom_room`.
pub fn full_room() -> MockCodeRoom {
    let broken: Vec<String> = std::env::var("DWARVES_BREAK_FEED")
        .map(|v| v.split(',').map(|s| s.trim().to_string()).collect())
        .unwrap_or_default();
    let fed: Vec<(&str, Value)> = vec![
        ("Viz.CrateGraph", crate_graph()),
        ("Coderoom.SnapshotDiff", snapshot_diff()),
        ("Coderoom.Compat", refusal("not_wired", COMPAT_NOTE)),
        ("Coderoom.WhatBreaks", refusal("not_wired", BREAKS_NOTE)),
        ("Viz.FunctionTier", function_tier()),
        ("Knowledge.Symbols", symbols()),
        ("Viz.CallGraph", call_graph()),
        ("Knowledge.Source", source()),
        ("Knowledge.TestReach", test_reach()),
        ("Viz.Binary", binary()),
    ]
    .into_iter()
    .filter(|(s, _)| !broken.iter().any(|b| b == s))
    .collect();
    MockCodeRoom::answering(&fed)
}

/// `Viz.Binary`: the binary half of the room — the `shop` artifact, its bytes by
/// crate, its largest symbols and two releases of its ledger.
pub fn binary() -> Value {
    json!({
        "state": "complete",
        "artifacts": [
            { "artifact": "shop@x86_64-unknown-linux-gnu:release", "binary": "shop", "symbols": 3, "bytes": 5200, "imports": 2, "file_size": 91000, "text_size": 40000 },
            { "artifact": "shopctl@x86_64-unknown-linux-gnu:release", "binary": "shopctl", "symbols": 1, "bytes": 800, "imports": 1, "file_size": 21000, "text_size": 9000 },
        ],
        "artifact": "shop@x86_64-unknown-linux-gnu:release",
        "crates": [{ "crate": "shop", "bytes": 4100, "symbols": 2 }, { "crate": "serde", "bytes": 1100, "symbols": 1 }],
        "symbols": [
            { "symbol": "shop::pay::charge", "mangled": "_RNvNtCs1_4shop3pay6charge", "crate": "shop", "path": "shop::pay::charge", "role": "item", "section": ".text", "bytes": 3000 },
            { "symbol": "shop::checkout", "mangled": "_RNvCs1_4shop8checkout", "crate": "shop", "path": "shop::checkout", "role": "item", "section": ".text", "bytes": 1100 },
            { "symbol": "<serde::de::Visitor>::visit_str", "mangled": "_RNv…", "crate": "serde", "path": "serde::de::Visitor::visit_str", "role": "mono", "section": ".text", "bytes": 1100 },
        ],
        "total_symbols": 3,
        "history": [
            { "repo": "shop", "artifact": "shop@x86_64-unknown-linux-gnu:release", "rev": 1, "seq": 1, "sha": "aaaa", "status": "ok", "file_size": 88000, "text_size": 39000 },
            { "repo": "shop", "artifact": "shop@x86_64-unknown-linux-gnu:release", "rev": 2, "seq": 2, "sha": "0123456789abcdef0123", "status": "ok", "file_size": 91000, "text_size": 40000 },
        ],
        "room": room_id(),
        "evidence": evidence(&["hardening (RELRO · PIE · NX · stack canary · fortify) is not in the binary layer: mimir-binary joins symbols, it does not grade the ELF"]),
    })
}

/// A room nothing was consumed into: every surface that needs a room refuses
/// `not_consumed`; the two world-ring surfaces stay `not_wired`.
pub fn unconsumed_room() -> MockCodeRoom {
    let room = MockCodeRoom::default();
    for s in [
        "Viz.CrateGraph",
        "Coderoom.SnapshotDiff",
        "Viz.FunctionTier",
        "Knowledge.Symbols",
        "Viz.CallGraph",
        "Knowledge.Source",
        "Knowledge.TestReach",
        "Viz.Binary",
    ] {
        room.set(s, refusal("not_consumed", NOT_CONSUMED));
    }
    room.set("Coderoom.Compat", refusal("not_wired", COMPAT_NOTE));
    room.set("Coderoom.WhatBreaks", refusal("not_wired", BREAKS_NOTE));
    room
}

fn to_s(v: &[&str]) -> Vec<String> {
    v.iter().map(|s| s.to_string()).collect()
}

/// The warehouse tables the stand serves (the ones that are still tables).
pub fn tables() -> Vec<(String, Vec<String>, Vec<Vec<String>>)> {
    vec![
        (
            "git_heat_facts".to_string(),
            to_s(&["repo", "file", "commits_90d"]),
            vec![
                to_s(&["shop", "src/pay.rs", "12"]),
                to_s(&["shop", "src/lib.rs", "3"]),
            ],
        ),
        (
            "dep_graph_edges".to_string(),
            to_s(&["from_repo", "to_repo"]),
            vec![to_s(&["web", "shop"])],
        ),
        (
            "bench_runs".to_string(),
            to_s(&[
                "run_id",
                "repo",
                "ts_micros",
                "date",
                "version",
                "machine",
                "cores",
            ]),
            vec![to_s(&[
                "r1",
                "shop",
                "1784000000000000",
                "2026-07-22",
                "0.1.0",
                "oden",
                "32",
            ])],
        ),
        (
            "bench_results".to_string(),
            to_s(&["run_id", "result_name", "metric_name", "metric_value"]),
            vec![to_s(&["r1", "shop.pay_charge", "ms", "4"])],
        ),
    ]
}

/// The stand: a mock nornir, the real forge proxy in front of it, and the room handle.
pub struct Stand {
    pub room: MockCodeRoom,
    /// The forge endpoint — the ONLY address the shell is given.
    pub host: String,
    _proxy: dwarves::warehouse_proxy::ProxyServer,
    _upstream: MockWarehouseServer,
}

pub fn stand(room: MockCodeRoom) -> Stand {
    let upstream = spawn_mock_nornir(tables(), room.clone());
    let proxy = dwarves::warehouse_proxy::spawn_proxy(upstream.endpoint.clone(), String::new());
    Stand {
        room,
        host: proxy.endpoint.clone(),
        _proxy: proxy,
        _upstream: upstream,
    }
}

/// The address the shell must NEVER adopt — poisoned in the env as a booby-trap.
pub const NORNIR_POISON: &str = "http://nornir-poison.example:7878";

/// The SHIPPED shell (`build_native_app`, the builder `main` runs), given only the forge.
pub fn shell(host: &str) -> dwarves_gui::tabbed::TabbedView {
    // SAFETY: each robot file is its own test binary and holds ONE test that builds a shell.
    unsafe {
        std::env::set_var("NORNIR_SERVER", NORNIR_POISON);
        std::env::set_var("DWARVES_SERVER", host);
        std::env::set_var("DWARVES_WAREHOUSES", WS);
        std::env::set_var("NORNIR_WORKSPACE", WS);
    }
    dwarves_gui::build_native_app(
        host.to_string(),
        std::path::PathBuf::from("/nonexistent/dwarves-gui/room-stand"),
    )
}

/// Every `(workspace header, surface)` the mock was asked, in order.
pub fn asked(room: &MockCodeRoom) -> Vec<(String, String)> {
    room.asked
        .lock()
        .unwrap()
        .iter()
        .map(|a| (a.0.clone(), a.1.clone()))
        .collect()
}

/// The params the mock got for the LAST ask of `surface`.
pub fn params_of(room: &MockCodeRoom, surface: &str) -> Option<Value> {
    room.asked
        .lock()
        .unwrap()
        .iter()
        .rev()
        .find(|a| a.1 == surface)
        .and_then(|a| serde_json::from_str(&a.2).ok())
}

#[allow(unused_variables)]
pub fn matrix(check: &str, ok: bool, detail: &str) {
    #[cfg(feature = "testmatrix")]
    nornir_testmatrix::functional_status("dwarves-gui", check, ok, detail);
}