server/cli/tests/the_default_serves_the_mvp_formats.rs
//! **`cargo install holger` serves the twelve MVP formats**
//! (lane HOL-MVP-FORMATS, owner 2026-10-30).
//!
//! The MVP format set is raw, Rust, npm, Maven, Python, Docker/OCI, Go, Helm, deb, rpm, the
//! znippy package and the Build Thing's history. server/cli's `default` (this test's
//! `holger`) and every MVP server row carry exactly
//! those (holger-recipe `tests/mvp_formats.rs` holds the declarations). Here the real binary
//! is started:
//!
//! * a RON with one repository of each of the twelve boots, answers `/healthz`, and no
//! repository was disabled on the way (the boot log names none `DISABLED`);
//!
//! The other half, a format outside the twelve refusing the boot by name (`holger-mvp-1`), is
//! server-lib's `tests/the_mvp_build_refuses_the_formats_outside_the_mvp_set.rs`: this crate's
//! test builds link `holger-bench-scenarios` as a dev-dependency, which pins server-lib with
//! `fmt-all`, so a test binary here serves every format whatever `default` says.
use std::path::Path;
use std::process::{Command, Stdio};
use std::time::{Duration, Instant};
const BIN: &str = env!("CARGO_BIN_EXE_holger");
fn free_port() -> u16 {
std::net::TcpListener::bind("127.0.0.1:0")
.unwrap()
.local_addr()
.unwrap()
.port()
}
/// A znippy archive at `out` holding `files` (path, bytes): the read-only shape every
/// archive-backed format (Maven, Python, npm, Go, Helm, deb, rpm, znippy, Build Thing)
/// opens at boot.
fn archive(out: &Path, files: &[(&str, &[u8])]) {
let src = tempfile::tempdir().unwrap();
for (p, b) in files {
let at = src.path().join(p);
std::fs::create_dir_all(at.parent().unwrap()).unwrap();
std::fs::write(at, b).unwrap();
}
znippy_compress::compress_dir(
&src.path().to_path_buf(),
&out.to_path_buf(),
false,
None,
None,
None,
)
.expect("compress_dir");
}
/// One repository line of the RON.
fn repo(name: &str, ty: &str, extra: &str) -> String {
format!(
" (ron_name: \"{name}\", ron_repo_type: \"{ty}\", ron_upstreams: [], ron_in: None,\n\
\x20 ron_out: Some((ron_storage_endpoint: \"store\", ron_exposed_endpoint: \"door\")){extra}),\n"
)
}
fn ron(d: &Path, grpc: u16, http: u16, repos: &str) -> String {
let d = d.display();
format!(
"(\n exposed_endpoints: [ (ron_name: \"door\", ron_url: \"127.0.0.1:{grpc}\", ron_http_url: Some(\"127.0.0.1:{http}\")) ],\n\
\x20 storage_endpoints: [ (ron_name: \"store\", ron_storage_type: \"znippy\", ron_path: \"{d}/store\") ],\n\
\x20 repositories: [\n{repos} ],\n\
\x20 audit: (dir: \"{d}/audit\", enabled: true),\n\
)\n"
)
}
/// The twelve, one repository each.
fn the_twelve(d: &Path) -> String {
let a = |name: &str, files: &[(&str, &[u8])]| {
let p = d.join(format!("{name}.znippy"));
archive(&p, files);
format!(", ron_archive_path: Some(\"{}\")", p.display())
};
let dir = |name: &str| format!(", ron_data_dir: Some(\"{}\")", d.join(name).display());
let mut s = String::new();
s += &repo("raw", "raw", &dir("raw"));
s += &repo(
"crates",
"rust",
&format!(
", ron_writable_archive: Some(\"{}\")",
d.join("crates.znippy").display()
),
);
s += &repo(
"npm",
"npm",
&a("npm", &[("demo/-/demo-1.0.0.tgz", b"npm")]),
);
s += &repo(
"maven",
"maven3",
&a(
"maven",
&[("org/demo/demo-lib/1.0.0/demo-lib-1.0.0.pom", b"<project/>")],
),
);
s += &repo(
"pypi",
"pip",
&a("pypi", &[("demo_pkg-1.0.0-py3-none-any.whl", b"wheel")]),
);
s += &repo("oci", "oci", &dir("oci"));
s += &repo(
"go",
"go",
&a(
"go",
&[(
"example.com/hello/@v/v1.0.0.mod",
b"module example.com/hello\n",
)],
),
);
s += &repo(
"charts",
"helm",
&a("charts", &[("demo-1.0.0.tgz", b"chart")]),
);
s += &repo(
"apt",
"deb",
&a("apt", &[("pool/main/d/demo/demo_1.0.0_amd64.deb", b"deb")]),
);
s += &repo(
"yum",
"rpm",
&a("yum", &[("demo-1.0.0-1.x86_64.rpm", b"rpm")]),
);
s += &repo(
"packages",
"znippy",
&a("packages", &[("demo/1.0.0/demo.txt", b"znippy")]),
);
s += &repo(
"history",
"znippy-build-thing",
&a("history", &[("demo/1.0.0/attestation.json", b"{}")]),
);
s
}
/// Start `holger start --config` on `repos`; `Ok(log)` once `/healthz` answers, `Err(log)`
/// when the process exits first.
fn boot(make: impl FnOnce(&Path) -> String) -> Result<String, String> {
let dir = tempfile::tempdir().unwrap();
let (grpc, http) = (free_port(), free_port());
let repos = make(dir.path());
let cfg = dir.path().join("holger.ron");
std::fs::write(&cfg, ron(dir.path(), grpc, http, &repos)).unwrap();
let log = dir.path().join("boot.log");
let mut child = Command::new(BIN)
.args(["start", "--config"])
.arg(&cfg)
.env("RUST_LOG", "info")
.stdout(Stdio::from(std::fs::File::create(&log).unwrap()))
.stderr(Stdio::from(
std::fs::File::create(dir.path().join("boot.err")).unwrap(),
))
.spawn()
.expect("spawn holger");
let read = |d: &Path| {
format!(
"{}{}",
std::fs::read_to_string(d.join("boot.log")).unwrap_or_default(),
std::fs::read_to_string(d.join("boot.err")).unwrap_or_default()
)
};
let deadline = Instant::now() + Duration::from_secs(60);
while Instant::now() < deadline {
if let Ok(Some(_)) = child.try_wait() {
return Err(read(dir.path()));
}
if healthz(http) {
let _ = child.kill();
let _ = child.wait();
return Ok(read(dir.path()));
}
std::thread::sleep(Duration::from_millis(100));
}
let _ = child.kill();
let _ = child.wait();
panic!(
"holger neither answered /healthz nor exited in 60 s:\n{}",
read(dir.path())
);
}
fn healthz(port: u16) -> bool {
use std::io::{Read, Write};
let Ok(mut c) = std::net::TcpStream::connect(("127.0.0.1", port)) else {
return false;
};
let _ = c.set_read_timeout(Some(Duration::from_secs(5)));
if c.write_all(b"GET /healthz HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n")
.is_err()
{
return false;
}
let mut raw = Vec::new();
let _ = c.read_to_end(&mut raw);
String::from_utf8_lossy(&raw).starts_with("HTTP/1.1 200")
}
#[test]
fn a_ron_with_one_repository_of_each_mvp_format_boots() {
match boot(the_twelve) {
Err(log) => panic!("the twelve MVP formats (raw, rust, npm, maven3, pip, oci, go, helm, deb, rpm, znippy, znippy-build-thing) did not boot:\n{log}"),
Ok(log) => assert!(
!log.contains("DISABLED") && !log.contains("repositories disabled") && !log.contains("holger-mvp-1"),
"every one of the twelve repositories comes up, none disabled:\n{log}"
),
}
}