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

nordisk/dwarves

crates/nornir-warehouse-embed/tests/roster_does_not_hang.rs

//! **A forge that ACCEPTS the connection and then never answers must not hang the UI.**
//!
//! `dwarves-gui`'s `build_native_app` calls `registered_warehouses` →
//! [`nornir_warehouse_embed::list_warehouses`] SYNCHRONOUSLY, before the window is
//! created, and its own doc comment promises *"Offline-safe: dead endpoints render each
//! pane's honest unavailable state rather than hanging on a socket."*
//!
//! That promise rested on `.connect_timeout(3s)`, which bounds the TCP connect and
//! NOTHING else. MEASURED 2026-09-06 against the live `dwarves-server` on oden (pid
//! 1122179, RSS ~50 GiB, `STAT=DLsl`): the socket was accepted instantly and the
//! `Workspaces.List` RPC never answered, so `dwarves-ui-gpu --server <oden>` sat in
//! `futex_do_wait` with 12 MB RSS, two threads, NO window and NO message — while the
//! same binary pointed at a REFUSING endpoint opened normally. A connect timeout cannot
//! see that failure, because the connect succeeded.
//!
//! The listener here is that server: accept, hold the socket, say nothing.

use std::io::Read;

#[test]
fn a_server_that_accepts_and_never_answers_does_not_hang_the_roster() {
    let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("bind probe listener");
    let addr = listener.local_addr().expect("probe addr");

    // Accept and HOLD. Never write a byte — the wedged-server shape. The accepted
    // sockets are parked in a Vec so they are not dropped (a drop would close the
    // connection and hand the client an error it must not need).
    std::thread::spawn(move || {
        let mut held = Vec::new();
        for stream in listener.incoming() {
            match stream {
                Ok(mut s) => {
                    let _ = s.set_read_timeout(Some(std::time::Duration::from_secs(1)));
                    let mut sink = [0u8; 1024];
                    let _ = s.read(&mut sink);
                    held.push(s);
                }
                Err(_) => break,
            }
        }
    });

    // The call runs on its own thread so a HANG FAILS the test instead of hanging the
    // suite: `recv_timeout` is the assertion, and an unbounded RPC never sends.
    let (tx, rx) = std::sync::mpsc::channel();
    std::thread::spawn(move || {
        let started = std::time::Instant::now();
        let r = nornir_warehouse_embed::list_warehouses(&format!("http://{addr}"), "");
        let _ = tx.send((r.is_err(), started.elapsed()));
    });

    match rx.recv_timeout(std::time::Duration::from_secs(45)) {
        Ok((is_err, took)) => {
            assert!(
                is_err,
                "a server that never answers must produce an ERROR, not a roster (took {took:?})"
            );
        }
        Err(_) => panic!(
            "`list_warehouses` never returned against a server that accepts and stays \
             silent — this is the hang that leaves `dwarves-ui-gpu` with no window: the \
             seam bounds `connect_timeout` but not the REQUEST"
        ),
    }
}