From 422b7c033fdc90363aac31da3bf13e2cd2beeb8a Mon Sep 17 00:00:00 2001 From: Xeonacid Date: Tue, 1 Sep 2026 16:40:04 +0200 Subject: [PATCH] cli/tests: Treat exit code 127 as "not found" `fn program_reports_version` skips optional tools such as `jq` and `jj` when they are missing. It currently only treats an error returned by `std::process::Command::status` of kind `std::io::ErrorKind::NotFound` as absence. Rust's `std::command::Command` uses glibc's `posix_spawn` on Unix. When `execve` fails after `spawn` has already returned, POSIX requires the child to exit with code 127 rather than reporting `errno` to the parent. glibc usually copies that failure back through a `CLONE_VM|CLONE_VFORK` shared-stack channel, but not every implementation preserves it. qemu-user, OpenBSD, and HPPA surface a successful `spawn` and an exit code of 127 instead. On those platforms the helper panics, so tests that are meant to skip without `jq` or `jj` fail. Treat exit status 127 the same as `NotFound`. See `man:posix_spawn(3)` and POSIX.1. Signed-off-by: Xeonacid --- crates/radicle-cli/tests/commands.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/radicle-cli/tests/commands.rs b/crates/radicle-cli/tests/commands.rs index 8807212de..47f253b7d 100644 --- a/crates/radicle-cli/tests/commands.rs +++ b/crates/radicle-cli/tests/commands.rs @@ -69,6 +69,8 @@ pub(crate) fn test<'a>( /// A utility to check that some program can be executed with a `--version` /// argument and exits successfully. /// +/// On Unix, an exit status of 127 is interpreted as "command not found". +/// /// # Panics /// /// If there is an error executing the program other than the program not being @@ -77,19 +79,24 @@ fn program_reports_version(program: &str) -> bool { use std::io::ErrorKind; use std::process::{Command, Stdio}; - match Command::new(program) + let found = match Command::new(program) .arg("--version") .stdout(Stdio::null()) .status() { - Err(e) if e.kind() == ErrorKind::NotFound => { - log::warn!(target: "test", "`{program}` not found."); - false - } + Err(e) if e.kind() == ErrorKind::NotFound => false, Err(e) => panic!("failure to execute `{program}`: {e}"), Ok(status) if status.success() => true, + #[cfg(unix)] + Ok(status) if status.code() == Some(127) => false, Ok(status) => panic!("executing `{program}` resulted in status {status}"), + }; + + if !found { + log::warn!(target: "test", "`{program}` not found."); } + + found } #[test]