holger-server-lib 0.6.9

Holger server library: config, wiring, gRPC service, Rust API
//! A repository whose backend fails to instantiate (e.g. a corrupt or
//! version-incompatible znippy archive) must be *disabled*, not fatal — the
//! server still serves every other repo. Only an all-repos-failed config
//! hard-fails. Regression cover for the WISHLIST "graceful archive errors" item.

use holger_server_lib::read_ron_config;

fn load(ron: &str, tmp: &std::path::Path) -> holger_server_lib::Holger {
    let path = tmp.join("h.ron");
    std::fs::write(&path, ron).unwrap();
    read_ron_config(&path).unwrap()
}

#[test]
fn corrupt_archive_disables_only_that_repo() {
    let tmp = tempfile::tempdir().unwrap();
    // A garbage file that is NOT a valid znippy archive.
    let bad = tmp.path().join("bad.znippy");
    std::fs::write(&bad, b"this is not a znippy archive").unwrap();
    let data_dir = tmp.path().join("rust-dev");

    let ron = format!(
        r#"(
    exposed_endpoints: [ ( ron_name: "e", ron_url: "127.0.0.1:0" ) ],
    storage_endpoints: [ ( ron_name: "s", ron_storage_type: "file", ron_path: "{store}" ) ],
    repositories: [
        ( ron_name: "good", ron_repo_type: "rust", ron_upstreams: [], ron_in: None,
          ron_out: Some(( ron_storage_endpoint: "s", ron_exposed_endpoint: "e" )),
          ron_data_dir: Some("{dd}") ),
        ( ron_name: "bad", ron_repo_type: "rust", ron_upstreams: [], ron_in: None,
          ron_out: Some(( ron_storage_endpoint: "s", ron_exposed_endpoint: "e" )),
          ron_archive_path: Some("{bad}") ),
    ],
)"#,
        store = tmp.path().display(),
        dd = data_dir.display(),
        bad = bad.display(),
    );

    let mut holger = load(&ron, tmp.path());
    // Must NOT bail despite the one corrupt archive.
    holger
        .instantiate_backends()
        .expect("one corrupt archive must not fail the whole server");

    let good = holger.repositories.iter().find(|r| r.ron_name == "good").unwrap();
    let bad_repo = holger.repositories.iter().find(|r| r.ron_name == "bad").unwrap();
    assert!(good.backend_repository.is_some(), "good repo should be live");
    assert!(bad_repo.backend_repository.is_none(), "corrupt-archive repo should be disabled");
}

#[test]
fn all_repos_failing_hard_fails() {
    let tmp = tempfile::tempdir().unwrap();
    let bad = tmp.path().join("bad.znippy");
    std::fs::write(&bad, b"garbage").unwrap();

    let ron = format!(
        r#"(
    exposed_endpoints: [ ( ron_name: "e", ron_url: "127.0.0.1:0" ) ],
    storage_endpoints: [ ( ron_name: "s", ron_storage_type: "file", ron_path: "{store}" ) ],
    repositories: [
        ( ron_name: "bad", ron_repo_type: "rust", ron_upstreams: [], ron_in: None,
          ron_out: Some(( ron_storage_endpoint: "s", ron_exposed_endpoint: "e" )),
          ron_archive_path: Some("{bad}") ),
    ],
)"#,
        store = tmp.path().display(),
        bad = bad.display(),
    );

    let mut holger = load(&ron, tmp.path());
    let err = holger
        .instantiate_backends()
        .expect_err("a config where every repo fails must hard-fail");
    assert!(err.to_string().contains("nothing to serve"), "got: {err}");
}