147 lines
4.2 KiB
Rust
147 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![
|
|
"--silent",
|
|
"--show-error",
|
|
"--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));
|
|
}
|