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

nordisk/holger

server/lib/tests/the_airgap_is_the_default.rs

//! **The airgap is the default** (Holger v2.0 H2 leftovers, B2; HCUT 2026-10-26).
//!
//! 1. A config that says no `network:` and names nothing that dials resolves to
//!    `Offline`: the started box refuses every outbound dial ([`egress`]).
//! 2. A config that names an upstream (a pull-through source with a url, a `*-remote`
//!    repository, a mirror) and says no `network:` is `Online`, and the boot says what
//!    it dials; with `network: Offline` the same config is refused by name and the
//!    refusal says how to let it dial.
//! 3. No upstream fallback: a `rust-remote` repository with no `ron_base_url` no longer
//!    reaches for crates.io; it is refused by name and the refusal says how to name one.

use std::io::Write;

use holger_server_lib::egress::NetworkMode;
use holger_server_lib::{read_ron_config, Holger};

fn load(ron: &str) -> (tempfile::NamedTempFile, Holger) {
    let mut f = tempfile::NamedTempFile::new().unwrap();
    f.write_all(ron.as_bytes()).unwrap();
    let h = read_ron_config(f.path()).expect("the config parses");
    (f, h)
}

fn config(d: &str, network: &str, repos: &str, extra: &str) -> String {
    format!(
        r#"(
    {network}
    repositories: [ {repos} ],
    exposed_endpoints: [ (ron_name: "door", ron_url: "127.0.0.1:0") ],
    storage_endpoints: [],
    audit: (dir: "{d}/audit", enabled: true),
    {extra}
)"#
    )
}

/// The default and the downstream builds: nothing named, nothing dialled.
#[cfg(not(feature = "estate"))]
#[test]
fn a_config_that_names_no_upstream_is_offline_by_default() {
    let data = tempfile::tempdir().unwrap();
    let d = data.path().display().to_string();
    let (_f, h) = load(&config(
        &d,
        "",
        r#"(ron_name: "files", ron_repo_type: "raw", ron_upstreams: [], ron_in: None, ron_out: None, ron_data_dir: Some("x"))"#,
        "",
    ));
    assert_eq!(
        h.network,
        NetworkMode::Auto,
        "no `network:` is the default, not Online"
    );
    assert!(
        h.network_needs().is_empty(),
        "nothing here dials: {:?}",
        h.network_needs()
    );
    assert_eq!(
        h.resolved_network(),
        NetworkMode::Offline,
        "the default with no upstream is the airgap"
    );
}

#[test]
fn a_config_that_names_an_upstream_is_online_and_says_what_it_dials() {
    let data = tempfile::tempdir().unwrap();
    let d = data.path().display().to_string();
    let remote = r#"(ron_name: "crates-io", ron_repo_type: "rust-remote", ron_base_url: Some("https://index.crates.io"), ron_upstreams: [], ron_in: None, ron_out: None)"#;
    let (_f, h) = load(&config(&d, "", remote, ""));
    assert_eq!(h.resolved_network(), NetworkMode::Online);
    let needs = h.network_needs();
    assert!(
        needs.iter().any(|n| n.contains("crates-io")),
        "the boot names what dials: {needs:?}"
    );

    let (_g, mut off) = load(&config(&d, "network: Offline,", remote, ""));
    let err = format!(
        "{:#}",
        off.instantiate_backends()
            .expect_err("an explicit Offline with an upstream is refused")
    );
    assert!(
        err.contains("[holger-offline-2]") && err.contains("crates-io"),
        "{err}"
    );
    assert!(
        err.contains("network: Online"),
        "the refusal says how to let it dial: {err}"
    );
}

#[test]
fn a_rust_remote_with_no_url_falls_back_to_no_upstream_and_says_how_to_name_one() {
    let data = tempfile::tempdir().unwrap();
    let d = data.path().display().to_string();
    let (_f, mut h) = load(&config(
        &d,
        "network: Online,",
        r#"(ron_name: "crates-io", ron_repo_type: "rust-remote", ron_upstreams: [], ron_in: None, ron_out: None)"#,
        "",
    ));
    assert!(
        h.instantiate_backends().is_err(),
        "a box whose one repository is refused serves nothing"
    );
    let err = format!(
        "{:#}",
        h.repositories[0]
            .backend_from_config()
            .expect_err("a remote with no url is refused")
    );
    assert!(
        err.contains("[holger-offline-3]") && err.contains("crates-io"),
        "{err}"
    );
    assert!(
        err.contains("ron_base_url: Some(\"https://index.crates.io\")"),
        "the refusal says how to name one: {err}"
    );
}

/// ★ **An estate build is online by design, and says why** (HCON-6). `estate` (which
/// `metered`, the sold product, implies) is the box of an estate: it dials its front, its twin
/// and the ONE box. The same config that is the airgap on the default build is `Online`
/// here, the boot names the estate as the reason, and an explicit `network: Offline` is
/// refused by name rather than started half-blind.
#[cfg(feature = "estate")]
#[test]
fn an_estate_build_is_online_by_design_and_says_why() {
    let data = tempfile::tempdir().unwrap();
    let d = data.path().display().to_string();
    let files = r#"(ron_name: "files", ron_repo_type: "raw", ron_upstreams: [], ron_in: None, ron_out: None, ron_data_dir: Some("x"))"#;
    let (_f, h) = load(&config(&d, "", files, ""));
    assert_eq!(h.network, NetworkMode::Auto);
    let needs = h.network_needs();
    assert_eq!(
        needs,
        vec![
            "this is an estate build: the box dials its front, its twin and the ONE box"
                .to_string()
        ],
        "the estate is the one reason"
    );
    assert_eq!(
        h.resolved_network(),
        NetworkMode::Online,
        "an estate box is online by design"
    );

    let (_g, mut off) = load(&config(&d, "network: Offline,", files, ""));
    let err = format!(
        "{:#}",
        off.instantiate_backends()
            .expect_err("an estate box told to be Offline is refused")
    );
    assert!(
        err.contains("[holger-offline-2]") && err.contains("estate build"),
        "the refusal names the estate: {err}"
    );
}