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

nordisk/gunnar

crates/gunnar-server/tests/dashboard_seam.rs

//! The device seam of the console dashboard — `GUNNAR_DASHBOARD=<path>` draws
//! on any writable file, no PID 1 needed — proven by reading the frames back.
//!
//! **Its own binary, on purpose.** The log tap's receiver is a process-global
//! one-shot (`gunnar_common::logtap::take_receiver`), and `dashboard::spawn`
//! takes it. Until 2026-09-04 this test lived in `dashboard_render.rs` beside
//! the frame test, which takes the same receiver by hand — so whichever ran
//! first in that process won, and the other took a degenerate arm. MEASURED
//! twice under the parallel workspace run: `spawn refused although the
//! receiver was free` (the frame test installed the tap a moment AFTER `spawn`
//! had looked for it), and `the tap's receiver, once`. The seam test's positive
//! path never ran at all under `--test-threads=1` (alphabetical order handed
//! the receiver to the frame test first). One integration-test file is one
//! process, so each test now owns the global it needs, and there is no
//! degenerate arm left to hide in: `spawn` MUST start here.

use std::path::PathBuf;

use gunnar_common::logtap::{self, LogLine, TapLayer};
use gunnar_server::dashboard::Facts;

#[test]
fn the_device_seam_draws_frames_into_a_file() {
    // Installing the layer is what creates the tap and its receiver; in the
    // server that happens when the tracing subscriber is built. Here nobody
    // else does it, so this test does — without it `spawn` would refuse for
    // "never installed", which is a different fact from the one under test.
    let _tap = TapLayer::new();

    let dir = tempfile::tempdir().unwrap();
    let path = dir.path().join("screen");
    std::fs::write(&path, b"").unwrap();
    std::env::set_var("GUNNAR_DASHBOARD", &path);
    let started = gunnar_server::dashboard::spawn(Facts {
        ssh_bind: "127.0.0.1:2222".parse().unwrap(),
        grpc_bind: Some("127.0.0.1:50051".parse().unwrap()),
        data_root: PathBuf::from("/"),
        build: "seam-build".into(),
        engine: None,
        replication: gunnar_server::replication_view::ReplicationView::new(),
        tenants: gunnar_server::dashboard::TenantView::new(),
        flow: gunnar_server::dashboard::FlowView::new(),
    });
    std::env::remove_var("GUNNAR_DASHBOARD");
    assert!(
        started,
        "spawn must draw in its own process: the device is a writable file and the tap's \
         receiver has not been taken by anyone else"
    );
    logtap::push(LogLine {
        level: tracing::Level::INFO,
        target: "gunnar::ssh",
        message: "publickey accepted".into(),
        fields: vec![
            ("event", "ssh.auth.accepted".into()),
            ("fingerprint", "SHA256:seam".into()),
        ],
        span_fields: vec![("peer", "1.2.3.4:5".into()), ("principal", "seam".into())],
    });
    let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
    let mut got = String::new();
    while std::time::Instant::now() < deadline {
        got = String::from_utf8_lossy(&std::fs::read(&path).unwrap()).into_owned();
        if got.contains("seam-build") && got.contains("login   seam") {
            break;
        }
        std::thread::sleep(std::time::Duration::from_millis(50));
    }
    assert!(
        got.starts_with("\x1b[?25l\x1b[2J\x1b[H"),
        "cursor hidden, cleared once, then homed"
    );
    assert!(
        got.contains("seam-build") && got.contains("login   seam  seam\u{2026}  1.2.3.4:5"),
        "{got}"
    );
}