use std::io::BufRead;
use std::io::Read;
use std::str::FromStr;
use std::process::Command;
use sysinfo::SystemExt;
fn target_dir() -> std::path::PathBuf {
std::env::current_exe()
.ok()
.map(|mut path| {
path.pop();
if path.ends_with("deps") {
path.pop();
}
path
})
.unwrap()
}
fn cargo_bin(name: &str) -> std::path::PathBuf {
let env_var = format!("CARGO_BIN_EXE_{}", name);
std::env::var_os(&env_var)
.map(|p| p.into())
.unwrap_or_else(|| target_dir().join(format!("{}{}", name, std::env::consts::EXE_SUFFIX)))
}
fn run_curl(args: Vec<&str>) -> std::process::Output {
let mut command = Command::new("curl");
command.arg("-s");
for arg in args {
command.arg(arg);
}
command.output().unwrap()
}
#[test]
fn connection_cleanup() {
let temp_dir = tempfile::tempdir().unwrap();
let path = temp_dir.path().join("test.sock");
let path = path.to_str().unwrap();
let http_sh = cargo_bin("http-sh");
let serve = Command::new(http_sh)
.arg(path)
.arg("--")
.arg("bash")
.arg("-c")
.arg(
r#"
exec 4>&-
sleep 3600 &
SLEEPID=$!
echo $SLEEPID
trap 'kill $SLEEPID' SIGTERM
wait
"#,
)
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let mut serve = scopeguard::guard(serve, |mut serve| {
let _ = serve.kill();
});
let stdout = serve.stdout.take().unwrap();
let stdout = std::io::BufReader::new(stdout);
let mut loglines = stdout.lines();
println!("logline: {:?}", loglines.next().unwrap());
let mut curl = Command::new("curl")
.arg("-s")
.arg("--no-buffer")
.arg("--unix-socket")
.arg(path)
.arg("http://localhost/")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let curl_out = curl.stdout.take().unwrap();
let curl_out = std::io::BufReader::new(curl_out);
let mut curl_lines = curl_out.lines();
let pid = curl_lines.next().unwrap().unwrap();
let pid = sysinfo::Pid::from_str(&pid).unwrap();
let mut sys = sysinfo::System::new_all();
sys.refresh_all();
assert!(sys.process(pid).is_some());
let _ = curl.kill().unwrap();
let _ = curl.wait().unwrap();
sys.refresh_all();
assert!(sys.process(pid).is_none());
}
#[test]
fn serve_unix() {
let temp_dir = tempfile::tempdir().unwrap();
let path = temp_dir.path().join("test.sock");
let path = path.to_str().unwrap();
let http_sh = cargo_bin("http-sh");
let want = "Hello from server!";
let mut serve = Command::new(http_sh)
.arg(path)
.arg("--")
.arg("printf")
.arg(want)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = serve.stdout.take().unwrap();
let stdout = std::io::BufReader::new(stdout);
let mut loglines = stdout.lines();
let _logline = loglines.next().unwrap().unwrap();
let got = run_curl(vec![
"--http1.1",
"--unix-socket",
path,
"http://localhost:5555/",
]);
assert_eq!(want.as_bytes(), got.stdout);
let logline = loglines.next().unwrap().unwrap();
let log: http_sh::Request = serde_json::from_str(&logline).unwrap();
assert_eq!(log.proto, "HTTP/1.1");
assert_eq!(log.authority, Some("localhost:5555".to_string()));
let got = run_curl(vec![
"--http2-prior-knowledge",
"--unix-socket",
path,
"http://localhost:5555/",
]);
assert_eq!(want.as_bytes(), got.stdout);
let logline = loglines.next().unwrap().unwrap();
assert_eq!(log.authority, Some("localhost:5555".to_string()));
serve.kill().unwrap();
let _exit_status = serve.wait().unwrap();
let log: http_sh::Request = serde_json::from_str(&logline).unwrap();
assert_eq!(log.proto, "HTTP/2.0");
for line in loglines {
println!("remaining stdout: {}", line.unwrap());
}
let mut stderr = String::new();
let n = serve
.stderr
.as_mut()
.unwrap()
.read_to_string(&mut stderr)
.unwrap();
assert_eq!(0, n, "stderr is not empty: \n---\n{}---\n", stderr);
}
#[test]
fn serve_tcp() {
let http_sh = cargo_bin("http-sh");
let want = "Hello from server!";
let mut serve = Command::new(http_sh)
.arg(":0")
.arg("--")
.arg("printf")
.arg(want)
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()
.unwrap();
let stdout = serve.stdout.take().unwrap();
let mut stdout = std::io::BufReader::new(stdout);
let mut read = String::new();
stdout.read_line(&mut read).unwrap();
let log: serde_json::Value = serde_json::from_str(&read).unwrap();
let got = Command::new("curl")
.arg("-s")
.arg(log["address"].as_str().unwrap())
.output()
.unwrap();
assert_eq!(want.as_bytes(), got.stdout);
serve.kill().unwrap();
let _exit_status = serve.wait().unwrap();
stdout.read_to_string(&mut read).unwrap();
let mut stderr = String::new();
let n = serve
.stderr
.as_mut()
.unwrap()
.read_to_string(&mut stderr)
.unwrap();
assert_eq!(0, n, "stderr is not empty: \n---\n{}---\n", stderr);
}