mod helpers;
use helpers::{current_username, run_whyno};
#[test]
fn help_flag_exits_zero() {
let output = run_whyno(&["--help"]);
assert_eq!(output.status.code(), Some(0), "expected exit 0 for --help");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("permission debugger"),
"help should contain program description"
);
}
#[test]
fn version_flag_exits_zero() {
let output = run_whyno(&["--version"]);
assert_eq!(
output.status.code(),
Some(0),
"expected exit 0 for --version"
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("whyno"),
"version output should contain binary name"
);
}
#[test]
fn caps_check_exits_zero() {
let output = run_whyno(&["caps", "check"]);
assert_eq!(
output.status.code(),
Some(0),
"expected exit 0 for caps check, stderr: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("CAP_DAC_READ_SEARCH") || stdout.contains("No capabilities"),
"caps check should report capability status, got: {stdout}"
);
}
#[test]
fn nonexistent_user_exits_two() {
let output = run_whyno(&["user:__nonexistent_whyno_test_user__", "read", "/tmp"]);
assert_eq!(
output.status.code(),
Some(2),
"expected exit 2 for nonexistent user, got stdout: {}",
String::from_utf8_lossy(&output.stdout)
);
}
#[test]
fn invalid_operation_exits_two() {
let output = run_whyno(&[¤t_username(), "foobar", "/tmp"]);
assert_eq!(
output.status.code(),
Some(2),
"expected exit 2 for invalid operation"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("unknown operation"),
"error message should mention unknown operation, got: {stderr}"
);
}
#[test]
fn missing_arguments_exits_cleanly() {
let output = run_whyno(&[]);
let code = output.status.code().expect("should have exit code");
assert!(
code == 0 || code == 2,
"expected exit 0 or 2 for no arguments, got {code}"
);
}
#[test]
fn relative_path_exits_two() {
let output = run_whyno(&[¤t_username(), "read", "relative/path"]);
assert_eq!(
output.status.code(),
Some(2),
"expected exit 2 for relative path"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("not absolute"),
"error should mention non-absolute path, got: {stderr}"
);
}
#[test]
fn json_and_explain_conflict_exits_two() {
let output = run_whyno(&[¤t_username(), "read", "/tmp", "--json", "--explain"]);
assert_eq!(
output.status.code(),
Some(2),
"expected exit 2 for conflicting flags"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("mutually exclusive"),
"should report flag conflict, got: {stderr}"
);
}