#![allow(dead_code)]
use std::io::{Read, Write};
use std::net::TcpStream;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::OnceLock;
pub fn fixture() -> &'static Path {
static PATH: OnceLock<PathBuf> = OnceLock::new();
PATH.get_or_init(|| {
let exe = std::env::current_exe().unwrap();
let dir = exe.parent().unwrap().parent().unwrap();
match std::env::var("NEXTEST_RUN_ID") {
Ok(run) => build_fixture_once(dir, &run),
Err(_) => build_fixture(),
}
dir.join("fixture-app")
})
}
fn build_fixture() {
let status = Command::new(env!("CARGO"))
.args(["build", "--quiet", "-p", "fixture-app"])
.status()
.expect("cargo build fixture-app");
assert!(status.success());
}
fn build_fixture_once(dir: &Path, run: &str) {
let lock = std::fs::File::create(dir.join("fixture-app.lock")).unwrap();
lock.lock().unwrap();
let built = dir.join("fixture-app.run");
if std::fs::read_to_string(&built).ok().as_deref() != Some(run) {
build_fixture();
std::fs::write(&built, run).unwrap();
}
}
pub fn lifeline() -> String {
std::env::var("FIXTURE_LIFELINE_PID").unwrap_or_else(|_| std::process::id().to_string())
}
pub fn guard(pid: u32) {
let mut guard = Command::new(fixture())
.env_clear()
.env("FIXTURE_LIFELINE_PID", lifeline())
.env("FIXTURE_GUARD_PID", pid.to_string())
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.expect("spawn guard");
std::thread::spawn(move || guard.wait());
}
pub fn git(dir: &Path, args: &[&str]) {
let status = Command::new("git")
.args(args)
.current_dir(dir)
.env("GIT_AUTHOR_NAME", "carte")
.env("GIT_AUTHOR_EMAIL", "carte@example.com")
.env("GIT_COMMITTER_NAME", "carte")
.env("GIT_COMMITTER_EMAIL", "carte@example.com")
.status()
.unwrap();
assert!(status.success(), "git {args:?}");
}
pub fn repo(dir: &Path, procfile: &str) {
std::fs::create_dir_all(dir).unwrap();
git(dir, &["init", "-q", "-b", "main"]);
std::fs::write(dir.join("Procfile.dev"), procfile).unwrap();
git(dir, &["add", "."]);
git(dir, &["commit", "-q", "-m", "init"]);
}
pub fn http_get(port: u16, path: &str) -> String {
let mut stream = TcpStream::connect(("127.0.0.1", port))
.or_else(|_| TcpStream::connect(("::1", port)))
.unwrap();
write!(stream, "GET {path} HTTP/1.0\r\nHost: localhost\r\n\r\n").unwrap();
let mut response = String::new();
stream.read_to_string(&mut response).unwrap();
response
.split_once("\r\n\r\n")
.map(|(_, body)| body.to_string())
.unwrap_or_default()
}