diff --git a/tests/remote_helper_tests.rs b/tests/remote_helper_tests.rs new file mode 100644 index 0000000..4686a24 --- /dev/null +++ b/tests/remote_helper_tests.rs @@ -0,0 +1,56 @@ +//! Drives the remote helper binary the way git does: protocol on stdin/stdout. + +use std::process::Stdio; + +use tokio::io::AsyncWriteExt; + +/// Runs the helper with `commands` on stdin, returning (exit_ok, stdout, stderr). +async fn run_helper(url: &str, pds_url: &str, commands: &str) -> (bool, String, String) { + let mut child = tokio::process::Command::new(env!("CARGO_BIN_EXE_git-remote-pds")) + .args(["origin", url]) + .env("PDS_URL", pds_url) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + child + .stdin + .as_mut() + .unwrap() + .write_all(commands.as_bytes()) + .await + .unwrap(); + child.stdin.take(); + + let out = child.wait_with_output().await.unwrap(); + ( + out.status.success(), + String::from_utf8_lossy(&out.stdout).to_string(), + String::from_utf8_lossy(&out.stderr).to_string(), + ) +} + +/// Port 1 is reserved and nothing listens there — connections fail immediately. +const DEAD_PDS: &str = "http://127.0.0.1:1"; + +/// `list` must not answer "this repo has no refs" when it could not reach the PDS. +/// +/// git treats an empty ref list as an empty repository, so a clone against an +/// unreachable PDS reports success and leaves an empty repo behind. +#[tokio::test] +async fn list_fails_loudly_when_pds_is_unreachable() { + let (ok, stdout, stderr) = run_helper("pds://alice.test/some-repo", DEAD_PDS, "list\n").await; + + assert!( + !ok, + "helper exited 0 despite an unreachable PDS; stdout: {:?}", + stdout + ); + assert!( + stderr.contains("error"), + "expected an error on stderr, got: {:?}", + stderr + ); +}