Files
agent-sandbox/tests/e2e/cli.rs
T
2026-04-26 23:58:21 +02:00

253 lines
7.0 KiB
Rust

use crate::common::*;
#[test]
fn dry_run_prints_and_exits() {
let output = sandbox(&["--dry-run"])
.args(["--", "bash", "-c", "exit 42"])
.output()
.expect("agent-sandbox binary failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("bwrap"),
"expected bwrap command in dry-run output, got: {stdout}"
);
assert!(
output.status.success(),
"dry-run should exit 0, not 42 from the inner command"
);
}
#[test]
fn dry_run_output_is_copy_pasteable_shell() {
let dry = sandbox(&["--dry-run"])
.args(["--", "bash", "-c", "echo $HOME"])
.output()
.expect("agent-sandbox binary failed to execute");
let dry_cmd = String::from_utf8_lossy(&dry.stdout).trim().to_string();
let args = shlex::split(&dry_cmd).expect("dry-run output is not valid shell");
assert_eq!(args[0], "bwrap");
assert_eq!(args[args.len() - 1], "echo $HOME");
assert_eq!(args[args.len() - 2], "-c");
}
#[test]
fn empty_home_rejected() {
let output = sandbox(&[])
.env("HOME", "")
.args(["--", "true"])
.output()
.expect("agent-sandbox binary failed to execute");
assert!(
!output.status.success(),
"expected failure with empty HOME, but got success"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.to_lowercase().contains("home"),
"expected error mentioning HOME, got: {stderr}"
);
}
#[test]
fn config_missing_file_errors() {
let output = sandbox_withconfig(&["--config", "/nonexistent/config.toml"])
.args(["--", "true"])
.output()
.expect("failed to execute");
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("/nonexistent/config.toml"),
"expected config path in error, got: {stderr}"
);
}
#[test]
fn config_invalid_toml_errors() {
let cfg = ConfigFile::new("not valid {{{{ toml");
let output = sandbox_withconfig(&["--config", &cfg])
.args(["--", "true"])
.output()
.expect("failed to execute");
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("cannot parse"),
"expected parse error, got: {stderr}"
);
}
#[test]
fn config_unknown_key_errors() {
let cfg = ConfigFile::new("hardened = true\nbogus = \"nope\"\n");
let output = sandbox_withconfig(&["--config", &cfg])
.args(["--", "true"])
.output()
.expect("failed to execute");
assert!(!output.status.success());
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("unknown config key"),
"expected unknown key error, got: {stderr}"
);
}
#[test]
fn bwrap_arg_setenv_passes_through() {
let output = sandbox(&["--bwrap-arg", "--setenv MYVAR hello"])
.args(["--", "bash", "-c", "echo $MYVAR"])
.output()
.expect("agent-sandbox binary failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "hello",
"expected --bwrap-arg to pass --setenv through to bwrap, got: {stdout}"
);
}
#[test]
fn config_entrypoint_appends_passthrough_args() {
let cfg = ConfigFile::new(
r#"
[profiles.test]
entrypoint = ["bash", "-c"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--profile", "test"])
.args(["--", "echo entrypoint-works"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "entrypoint-works",
"expected passthrough args appended to entrypoint, got: {stdout}"
);
}
#[test]
fn config_entrypoint_falls_back_to_command_defaults() {
let cfg = ConfigFile::new(
r#"
[profiles.test]
entrypoint = ["bash", "-c"]
command = ["echo default-args"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--profile", "test"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "default-args",
"expected command defaults when no passthrough args, got: {stdout}"
);
}
#[test]
fn config_entrypoint_alone_without_command_or_passthrough() {
let cfg = ConfigFile::new(
r#"
[profiles.test]
entrypoint = ["bash", "-c", "echo entrypoint-only"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--profile", "test"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "entrypoint-only",
"expected entrypoint to run on its own, got: {stdout}"
);
}
#[test]
fn cli_entrypoint_appends_passthrough_args() {
let output = sandbox(&["--entrypoint", "bash"])
.args(["--", "-c", "echo cli-entrypoint-works"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "cli-entrypoint-works",
"expected --entrypoint to receive trailing args, got: {stdout}"
);
}
#[test]
fn cli_entrypoint_overrides_config_entrypoint() {
let cfg = ConfigFile::new(
r#"
entrypoint = ["/bin/false"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--entrypoint", "bash"])
.args(["--", "-c", "echo override-works"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "override-works",
"expected CLI --entrypoint to override config entrypoint, got: {stdout}"
);
}
#[test]
fn config_command_alone_without_passthrough() {
let cfg = ConfigFile::new(
r#"
[profiles.test]
command = ["bash", "-c", "echo command-only"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--profile", "test"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "command-only",
"expected config command to run on its own, got: {stdout}"
);
}
#[test]
fn config_command_replaced_by_passthrough() {
let cfg = ConfigFile::new(
r#"
[profiles.test]
command = ["bash", "-c", "echo should-not-see-this"]
"#,
);
let output = sandbox_withconfig(&["--config", &cfg, "--profile", "test"])
.args(["--", "bash", "-c", "echo replaced"])
.output()
.expect("failed to execute");
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string();
assert_eq!(
stdout, "replaced",
"expected passthrough to replace config command, got: {stdout}"
);
}