use super::*;
use crate::test_support::SkipCommandsGuard;
#[test]
fn run_run_command_succeeds_for_echo() {
let _guard = SkipCommandsGuard::set("");
let dir = std::env::temp_dir();
let result = run_run_command(
"echo",
&["alef-runcommand-ok"],
&dir,
"sample",
super::RUN_COMMAND_TIMEOUT,
);
assert!(
matches!(result, Ok(true)),
"echo should run and report Ok(true): {result:?}"
);
}
#[test]
fn run_run_command_fails_for_false() {
let _guard = SkipCommandsGuard::set("");
let dir = std::env::temp_dir();
let result = run_run_command("false", &[], &dir, "sample", super::RUN_COMMAND_TIMEOUT);
assert!(result.is_err(), "false should return Err");
let msg = format!("{:?}", result.unwrap_err());
assert!(
msg.contains("exited with status"),
"error should mention exit status: {msg}"
);
}
#[test]
fn run_run_command_honors_skip_env_var() {
let dir = std::env::temp_dir();
{
let _guard = SkipCommandsGuard::set("noop,false , another");
let skipped = run_run_command("false", &[], &dir, "sample", super::RUN_COMMAND_TIMEOUT);
assert!(
matches!(skipped, Ok(false)),
"listed command must return Ok(false) without spawning: {skipped:?}"
);
}
let _guard = SkipCommandsGuard::set("something-else");
let honored = run_run_command("false", &[], &dir, "sample", super::RUN_COMMAND_TIMEOUT);
assert!(
honored.is_err(),
"unlisted command must still spawn and surface failure"
);
}
#[test]
fn run_run_command_reports_false_when_the_tool_is_not_on_path() {
let _guard = SkipCommandsGuard::set("");
let dir = std::env::temp_dir();
let result = run_run_command(
"alef-definitely-not-a-real-binary-xyz123",
&[],
&dir,
"sample",
super::RUN_COMMAND_TIMEOUT,
);
assert!(
matches!(result, Ok(false)),
"a missing tool must be reported as skipped, not silently equivalent to success: {result:?}"
);
}
#[test]
fn run_run_command_is_killed_at_a_shorter_than_default_timeout() {
let _guard = SkipCommandsGuard::set("");
let dir = std::env::temp_dir();
let started = std::time::Instant::now();
let result = run_run_command("sleep", &["3"], &dir, "sample", std::time::Duration::from_secs(1));
let elapsed = started.elapsed();
let error = result.expect_err("a sleep 3 under a 1s ceiling must time out");
assert!(
error.to_string().contains("exceeded 1s timeout"),
"error should name the configured 1s ceiling, not the 1800s default: {error:#}"
);
assert!(
elapsed < std::time::Duration::from_secs(3),
"must be killed at the configured 1s ceiling rather than running to completion: {elapsed:?}"
);
}
#[test]
fn configured_build_command_timeout_reaches_the_post_build_run_command_step() {
let _guard = SkipCommandsGuard::set("");
let directory = tempfile::tempdir().expect("temporary project");
let mut config = crate::core::config::ResolvedCrateConfig::default();
config.build_commands.insert(
Language::Swift.to_string(),
BuildCommandConfig {
precondition: None,
dependency_precondition: None,
dependency_remediation: None,
before: None,
build: None,
build_release: None,
timeout_seconds: Some(1),
},
);
let build_config = crate::core::backend::BuildConfig {
tool: "swift",
crate_suffix: "-swift",
build_dep: crate::core::backend::BuildDependency::None,
post_build: vec![crate::core::backend::PostBuildStep::RunCommand {
cmd: "sleep",
args: vec!["3"],
}],
};
let started = std::time::Instant::now();
let result = run_post_build(Language::Swift, &build_config, &config, directory.path());
let elapsed = started.elapsed();
let error = result.expect_err("a sleep 3 post-build step under a configured 1s ceiling must fail");
let message = format!("{error:#}");
assert!(message.contains("exceeded 1s timeout"), "got: {message}");
assert!(
elapsed < std::time::Duration::from_secs(3),
"the configured 1s ceiling must fire before the sleep completes or the 1800s default \
would: {elapsed:?}"
);
}