holger-server-lib 0.6.5

Holger server library: config, wiring, gRPC service, Rust API
//! Unit tests for holger-server-lib config parsing and wiring.

use server_lib::{read_ron_config, wire_holger};
use std::io::Write;
use tempfile::NamedTempFile;

/// Emit one functional-status row for a real check into the `nornir test` matrix.
/// Gated behind `--features testmatrix` so the release build strips it entirely
/// (nothing is compiled — the dep is optional + the call site is `cfg`'d out).
#[cfg(feature = "testmatrix")]
fn fstatus(component: &str, check: &str, ok: bool, detail: &str) {
    nornir_testmatrix::functional_status(component, check, ok, detail);
}

const MINIMAL_CONFIG: &str = r#"(
    repositories: [
        (
            ron_name: "rust-test",
            ron_repo_type: "rust",
            ron_upstreams: [],
            ron_data_dir: Some("/tmp/holger-test-rust-data"),
            ron_in: None,
            ron_out: Some((
                ron_storage_endpoint: "test-storage",
                ron_exposed_endpoint: "test-ep",
            )),
        ),
    ],
    exposed_endpoints: [
        (
            ron_name: "test-ep",
            ron_url: "127.0.0.1:50051",
        ),
    ],
    storage_endpoints: [
        (
            ron_name: "test-storage",
            ron_storage_type: "rocksdb",
            ron_path: "/tmp/holger-test-data",
        ),
    ],
)"#;

#[test]
fn test_parse_minimal_config() {
    let mut f = NamedTempFile::new().unwrap();
    f.write_all(MINIMAL_CONFIG.as_bytes()).unwrap();

    let holger = read_ron_config(f.path()).unwrap();
    assert_eq!(holger.repositories.len(), 1);
    assert_eq!(holger.exposed_endpoints.len(), 1);
    assert_eq!(holger.storage_endpoints.len(), 1);
    assert_eq!(holger.repositories[0].ron_name, "rust-test");

    #[cfg(feature = "testmatrix")]
    fstatus(
        "config",
        "parse_minimal_config",
        holger.repositories.len() == 1
            && holger.exposed_endpoints.len() == 1
            && holger.storage_endpoints.len() == 1,
        &format!(
            "{} repos / {} exposed / {} storage; repo[0]={}",
            holger.repositories.len(),
            holger.exposed_endpoints.len(),
            holger.storage_endpoints.len(),
            holger.repositories[0].ron_name,
        ),
    );
}

#[test]
fn test_wire_holger() {
    let mut f = NamedTempFile::new().unwrap();
    f.write_all(MINIMAL_CONFIG.as_bytes()).unwrap();

    let mut holger = read_ron_config(f.path()).unwrap();
    holger.instantiate_backends().unwrap();
    wire_holger(&mut holger).unwrap();

    // Route table should be built
    let ep = &holger.exposed_endpoints[0];
    assert!(ep.aggregated_routes.is_some());

    #[cfg(feature = "testmatrix")]
    {
        let n = ep.aggregated_routes.as_ref().map(|r| r.routes.len()).unwrap_or(0);
        fstatus(
            "wire_holger",
            "routes_aggregated",
            ep.aggregated_routes.is_some(),
            &format!("exposed endpoint has {n} aggregated route(s)"),
        );
    }
}

#[test]
fn test_rust_api_fetch() {
    let mut f = NamedTempFile::new().unwrap();
    f.write_all(MINIMAL_CONFIG.as_bytes()).unwrap();

    let mut holger = read_ron_config(f.path()).unwrap();
    holger.instantiate_backends().unwrap();
    wire_holger(&mut holger).unwrap();

    // Fetch non-existent artifact returns None
    let id = traits::ArtifactId {
        namespace: None,
        name: "nonexistent".into(),
        version: "0.0.0".into(),
    };
    let result = holger.fetch("rust-test", &id).unwrap();
    assert!(result.is_none());

    #[cfg(feature = "testmatrix")]
    fstatus(
        "rust_api",
        "fetch_missing_is_none",
        result.is_none(),
        &format!("fetch(rust-test, nonexistent) -> {:?}", result.as_ref().map(|b| b.len())),
    );
}

#[test]
fn test_list_repositories() {
    let mut f = NamedTempFile::new().unwrap();
    f.write_all(MINIMAL_CONFIG.as_bytes()).unwrap();

    let mut holger = read_ron_config(f.path()).unwrap();
    holger.instantiate_backends().unwrap();
    wire_holger(&mut holger).unwrap();

    let repos = holger.list_repositories();
    assert_eq!(repos, vec!["rust-test"]);

    #[cfg(feature = "testmatrix")]
    fstatus(
        "rust_api",
        "list_repositories",
        repos == vec!["rust-test"],
        &format!("list_repositories() = {repos:?}"),
    );
}

#[test]
fn test_fetch_unknown_repo_errors() {
    let mut f = NamedTempFile::new().unwrap();
    f.write_all(MINIMAL_CONFIG.as_bytes()).unwrap();

    let mut holger = read_ron_config(f.path()).unwrap();
    holger.instantiate_backends().unwrap();
    wire_holger(&mut holger).unwrap();

    let id = traits::ArtifactId {
        namespace: None,
        name: "x".into(),
        version: "1".into(),
    };
    let res = holger.fetch("nonexistent-repo", &id);
    assert!(res.is_err());

    #[cfg(feature = "testmatrix")]
    fstatus(
        "rust_api",
        "fetch_unknown_repo_errors",
        res.is_err(),
        &format!("fetch(nonexistent-repo) is_err = {}", res.is_err()),
    );
}

#[test]
fn test_maven_config() {
    let config = r#"(
        repositories: [
            (
                ron_name: "maven-prod",
                ron_repo_type: "maven3",
                ron_upstreams: [],
                ron_archive_path: Some("/tmp/nonexistent.znippy"),
                ron_in: None,
                ron_out: Some((
                    ron_storage_endpoint: "storage",
                    ron_exposed_endpoint: "grpc-ep",
                )),
            ),
        ],
        exposed_endpoints: [
            (
                ron_name: "grpc-ep",
                ron_url: "0.0.0.0:50051",
            ),
        ],
        storage_endpoints: [
            (
                ron_name: "storage",
                ron_storage_type: "znippy",
                ron_path: "/tmp/holger-maven",
            ),
        ],
    )"#;

    let mut f = NamedTempFile::new().unwrap();
    f.write_all(config.as_bytes()).unwrap();

    let mut holger = read_ron_config(f.path()).unwrap();
    // instantiate_backends will fail because archive doesn't exist
    let result = holger.instantiate_backends();
    assert!(result.is_err());

    #[cfg(feature = "testmatrix")]
    fstatus(
        "config",
        "maven_missing_archive_errors",
        result.is_err(),
        &format!("instantiate_backends() is_err = {}", result.is_err()),
    );
}