diff --git a/tests/common/util.rs b/tests/common/util.rs index f3cdec010..a7c6e464d 100644 --- a/tests/common/util.rs +++ b/tests/common/util.rs @@ -1237,6 +1237,58 @@ pub fn expected_result(ts: &TestScenario, args: &[&str]) -> std::result::Result< )) } +/// This is a convenience wrapper to run a ucmd with root permissions. +/// This runs 'sudo -E --non-interactive target/debug/coreutils util_name args` +/// This is primarily designed to run in the CICD environment where whoami is in $path +/// and where non-interactive sudo is possible. +/// To check if i) non-interactive sudo is possible and ii) if sudo works, this runs: +/// 'sudo -E --non-interactive whoami' first. +/// +/// Example: +/// +/// ```no_run +/// use crate::common::util::*; +/// #[test] +/// fn test_xyz() { +/// let ts = TestScenario::new("whoami"); +/// let expected = "root\n".to_string(); +/// if let Ok(result) = run_ucmd_as_root(&ts, &[]) { +/// result.stdout_is(expected); +/// } else { +/// print!("TEST SKIPPED"); +/// } +/// } +///``` +#[cfg(unix)] +pub fn run_ucmd_as_root( + ts: &TestScenario, + args: &[&str], +) -> std::result::Result { + if ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg("whoami") + .run() + .stdout_str() + .trim() + != "root" + { + Err("\"sudo whoami\" didn't return \"root\"".to_string()) + } else { + Ok(ts + .cmd_keepenv("sudo") + .env("LC_ALL", "C") + .arg("-E") + .arg("--non-interactive") + .arg(&ts.bin_path) + .arg(&ts.util_name) + .args(args) + .run()) + } +} + /// Sanity checks for test utils #[cfg(test)] mod tests { @@ -1523,4 +1575,20 @@ mod tests { std::assert_eq!(host_name_for("gwho"), "gwho"); } } + + #[test] + #[cfg(unix)] + fn test_run_ucmd_as_root() { + // We need non-interactive `sudo. + // CICD environment should allow non-interactive `sudo`. + // Return early if we can't guarantee non-interactive `sudo` + if !is_ci() { + return; + } + let ts = TestScenario::new("whoami"); + std::assert_eq!( + run_ucmd_as_root(&ts, &[]).unwrap().stdout_str().trim(), + "root" + ); + } }