Files
boxmaker/crates/toolkit/tests/fetch.rs
T
kyleandClaude Opus 5.5 c3aaecdae2 M3b review fixes by the design model: curl --globoff, podman --pull=never
Review findings 1 and 2, both plan defects. curl gains --globoff and a
leading --disable; both podman runs gain --pull=never. The given fetch.rs and
the six golden files change with them. Checked on straylight with a rebuilt
image: a glob URL is one request, a missing image fails at once.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:25:51 -07:00

149 lines
4.2 KiB
Rust

//! `http_fetch`: the fixed `curl` arguments, and what `toolkit` makes of `curl`'s answer, against
//! fake `curl` scripts. Do not edit.
mod support;
use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf;
use std::sync::{Mutex, MutexGuard};
use proto::tools::HttpFetchArgs;
use support::TempDir;
use toolkit::Exit;
use toolkit::fetch::{curl_args, fetch_with};
const URL: &str = "https://example.com/a?b=c";
/// Every test that starts a process takes its turn. Otherwise another test's fork can hold
/// the script open for writing at the moment it is run, and running it fails with "text file
/// busy" (ETXTBSY), which has nothing to do with the code under test.
static SERIAL: Mutex<()> = Mutex::new(());
fn serial() -> MutexGuard<'static, ()> {
SERIAL.lock().unwrap_or_else(|p| p.into_inner())
}
fn fake_curl(dir: &TempDir, body: &str) -> PathBuf {
let path = dir.path().join("curl");
std::fs::write(&path, format!("#!/bin/sh\n{body}\n")).unwrap();
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755)).unwrap();
path
}
fn args() -> HttpFetchArgs {
HttpFetchArgs {
url: URL.to_string(),
}
}
#[test]
fn the_argument_list_is_fixed_and_ends_with_the_url() {
let expected: Vec<&str> = vec![
"--disable",
"--silent",
"--show-error",
"--globoff",
"--proto",
"=https",
"--proto-redir",
"=https",
"--location",
"--max-redirs",
"5",
"--max-time",
"50",
"--max-filesize",
"8388608",
"--cacert",
"/etc/ssl/certs/ca-certificates.crt",
"--proxy",
"socks5h://localhost/run/egress/egress.sock",
"--write-out",
"\n[http %{response_code}]",
"--url",
URL,
];
assert_eq!(curl_args(URL), expected);
}
#[test]
fn curl_is_given_exactly_those_arguments() {
let _serial = serial();
let dir = TempDir::new("fetch-args");
let curl = fake_curl(&dir, r#"for a in "$@"; do printf '%s|' "$a"; done"#);
let got = fetch_with(&curl, &args());
assert_eq!(got.exit, Exit::Done);
let expected: String = curl_args(URL).iter().map(|a| format!("{a}|")).collect();
assert_eq!(got.stdout, expected);
}
#[test]
fn a_successful_fetch_is_the_body_and_the_status_line() {
let _serial = serial();
let dir = TempDir::new("fetch-ok");
let curl = fake_curl(&dir, r#"printf 'hello\n\n[http 404]'"#);
let got = fetch_with(&curl, &args());
assert_eq!(
(got.exit, got.stdout.as_str()),
(Exit::Done, "hello\n\n[http 404]")
);
}
#[test]
fn a_failed_fetch_is_exit_1_with_curls_first_error_line() {
let _serial = serial();
let dir = TempDir::new("fetch-fail");
let curl = fake_curl(
&dir,
"printf 'partial'; printf '\\ncurl: (97) cannot complete SOCKS5 connection to evil.test. (2)\\nmore\\n' >&2; exit 97",
);
let got = fetch_with(&curl, &args());
assert_eq!(got.exit, Exit::ToolError);
assert_eq!(
got.stdout,
format!(
"http_fetch: {URL}: curl: (97) cannot complete SOCKS5 connection to evil.test. (2)"
)
);
}
#[test]
fn a_failure_without_a_message_names_the_exit() {
let _serial = serial();
let dir = TempDir::new("fetch-quiet");
let curl = fake_curl(&dir, "exit 28");
let got = fetch_with(&curl, &args());
assert_eq!(
(got.exit, got.stdout.as_str()),
(
Exit::ToolError,
"http_fetch: https://example.com/a?b=c: curl exited 28"
)
);
}
#[test]
fn a_curl_that_cannot_start_is_exit_1() {
let _serial = serial();
let got = fetch_with(&PathBuf::from("/no/such/curl"), &args());
assert_eq!(got.exit, Exit::ToolError);
assert!(
got.stdout
.starts_with("http_fetch: cannot start /no/such/curl: "),
"{}",
got.stdout
);
}
#[test]
fn much_output_on_both_streams_does_not_stop_curl() {
let _serial = serial();
let dir = TempDir::new("fetch-both");
let curl = fake_curl(
&dir,
"head -c 300000 /dev/zero | tr '\\0' e >&2; head -c 300000 /dev/zero | tr '\\0' o; exit 0",
);
let got = fetch_with(&curl, &args());
assert_eq!((got.exit, got.stdout.len()), (Exit::Done, 300000));
}