#![cfg(unix)]
use std::fs;
use std::path::PathBuf;
use std::process::Command;
fn root(label: &str) -> PathBuf {
std::env::temp_dir().join(format!("arcature-script-{label}-{}", std::process::id()))
}
fn create_project(path: &std::path::Path, scripts: &str) {
fs::create_dir_all(path).expect("project should be created");
fs::write(path.join("arcature.toml"), "frontend = \"react\"\nfrontend_dir = \"frontend\"\nbackend_package = \"demo\"\nbackend_binary = \"demo\"\nbackend_port = 3000\n").expect("config should be written");
fs::write(path.join("s.script"), scripts).expect("scripts should be written");
}
#[test]
fn executes_explicit_namespaced_script_and_propagates_status() {
let project = root("status");
create_project(
&project,
"[scripts.\"release:test\"]\nprogram = \"/bin/true\"\n\n[scripts.fail]\nprogram = \"/bin/false\"\n",
);
assert!(
Command::new(env!("CARGO_BIN_EXE_arc"))
.current_dir(&project)
.args(["s", "release:test"])
.status()
.expect("arc should run")
.success()
);
assert!(
!Command::new(env!("CARGO_BIN_EXE_arc"))
.current_dir(&project)
.args(["s", "fail"])
.status()
.expect("arc should run")
.success()
);
assert!(
!Command::new(env!("CARGO_BIN_EXE_arc"))
.current_dir(&project)
.args(["s", "missing"])
.status()
.expect("arc should run")
.success()
);
fs::remove_dir_all(project).expect("project should be removed");
}
#[test]
fn forwards_metacharacters_as_argv_without_shell_execution() {
let project = root("injection");
let marker = project.join("injected");
create_project(
&project,
"[scripts.echo]\nprogram = \"/bin/echo\"\nargs = [\"fixed\"]\n",
);
let payload = format!(";touch {}", marker.display());
assert!(
Command::new(env!("CARGO_BIN_EXE_arc"))
.current_dir(&project)
.args(["s", "echo", "--", &payload])
.status()
.expect("arc should run")
.success()
);
assert!(!marker.exists());
fs::remove_dir_all(project).expect("project should be removed");
}
#[test]
fn rejects_parent_working_directory() {
let project = root("cwd");
create_project(
&project,
"[scripts.escape]\nprogram = \"/bin/true\"\ncwd = \"..\"\n",
);
assert!(
!Command::new(env!("CARGO_BIN_EXE_arc"))
.current_dir(&project)
.args(["s", "escape"])
.status()
.expect("arc should run")
.success()
);
fs::remove_dir_all(project).expect("project should be removed");
}