use super::*;
use crate::error::CliError;
use whyno_core::operation::{Operation, XattrNamespace};
#[test]
fn parse_cap_name_cap_dac_override() {
assert_eq!(parse_cap_name("CAP_DAC_OVERRIDE").unwrap(), 1u64 << 1);
}
#[test]
fn parse_cap_name_case_insensitive() {
assert_eq!(parse_cap_name("cap_dac_override").unwrap(), 1u64 << 1);
}
#[test]
fn parse_cap_name_unknown_returns_error() {
let err = parse_cap_name("CAP_BOGUS").unwrap_err();
assert_eq!(err, CliError::InvalidCap("CAP_BOGUS".to_string()));
}
#[test]
fn with_cap_flag_parses_multiple() {
let cli = Cli::try_parse_from([
"whyno",
"nginx",
"read",
"/path",
"--with-cap",
"CAP_DAC_OVERRIDE",
"--with-cap",
"CAP_FOWNER",
])
.unwrap();
assert_eq!(
cli.with_cap,
vec!["CAP_DAC_OVERRIDE".to_string(), "CAP_FOWNER".to_string()]
);
}
#[test]
fn parse_subject_bare_username() {
assert_eq!(
parse_subject("nginx").unwrap(),
SubjectInput::Username("nginx".to_string())
);
}
#[test]
fn parse_subject_bare_number_is_uid() {
assert_eq!(parse_subject("33").unwrap(), SubjectInput::Uid(33));
}
#[test]
fn parse_subject_bare_zero_is_uid() {
assert_eq!(parse_subject("0").unwrap(), SubjectInput::Uid(0));
}
#[test]
fn parse_subject_user_prefix() {
assert_eq!(
parse_subject("user:nginx").unwrap(),
SubjectInput::Username("nginx".to_string())
);
}
#[test]
fn parse_subject_uid_prefix() {
assert_eq!(parse_subject("uid:33").unwrap(), SubjectInput::Uid(33));
}
#[test]
fn parse_subject_pid_prefix() {
assert_eq!(parse_subject("pid:1234").unwrap(), SubjectInput::Pid(1234));
}
#[test]
fn parse_subject_svc_prefix() {
assert_eq!(
parse_subject("svc:nginx").unwrap(),
SubjectInput::Service("nginx".to_string())
);
}
#[test]
fn parse_subject_uid_non_numeric_is_error() {
let err = parse_subject("uid:abc").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("invalid uid: abc".to_string())
);
}
#[test]
fn parse_subject_pid_non_numeric_is_error() {
let err = parse_subject("pid:abc").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("invalid pid: abc".to_string())
);
}
#[test]
fn parse_subject_empty_is_error() {
let err = parse_subject("").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("subject cannot be empty".to_string())
);
}
#[test]
fn parse_subject_user_prefix_empty_name_is_error() {
let err = parse_subject("user:").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("user: prefix requires a username".to_string())
);
}
#[test]
fn parse_subject_svc_prefix_empty_name_is_error() {
let err = parse_subject("svc:").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("svc: prefix requires a service name".to_string())
);
}
#[test]
fn parse_subject_uid_negative_is_error() {
let err = parse_subject("uid:-1").unwrap_err();
assert_eq!(err, CliError::InvalidSubject("invalid uid: -1".to_string()));
}
#[test]
fn parse_subject_uid_overflow_is_error() {
let err = parse_subject("uid:99999999999").unwrap_err();
assert_eq!(
err,
CliError::InvalidSubject("invalid uid: 99999999999".to_string())
);
}
#[test]
fn parse_operation_read() {
assert_eq!(parse_operation("read").unwrap(), Operation::Read);
}
#[test]
fn parse_operation_write() {
assert_eq!(parse_operation("write").unwrap(), Operation::Write);
}
#[test]
fn parse_operation_execute() {
assert_eq!(parse_operation("execute").unwrap(), Operation::Execute);
}
#[test]
fn parse_operation_delete() {
assert_eq!(parse_operation("delete").unwrap(), Operation::Delete);
}
#[test]
fn parse_operation_create() {
assert_eq!(parse_operation("create").unwrap(), Operation::Create);
}
#[test]
fn parse_operation_stat() {
assert_eq!(parse_operation("stat").unwrap(), Operation::Stat);
}
#[test]
fn parse_operation_case_insensitive_upper() {
assert_eq!(parse_operation("READ").unwrap(), Operation::Read);
}
#[test]
fn parse_operation_case_insensitive_mixed() {
assert_eq!(parse_operation("Write").unwrap(), Operation::Write);
}
#[test]
fn parse_operation_unknown_is_error() {
let err = parse_operation("foo").unwrap_err();
assert_eq!(err, CliError::InvalidOperation("foo".to_string()));
}
#[test]
fn parse_operation_empty_is_error() {
let err = parse_operation("").unwrap_err();
assert_eq!(err, CliError::InvalidOperation(String::new()));
}
#[test]
fn parse_operation_chmod() {
assert_eq!(parse_operation("chmod").unwrap(), Operation::Chmod);
}
#[test]
fn parse_operation_chown_uid() {
assert_eq!(parse_operation("chown-uid").unwrap(), Operation::ChownUid);
}
#[test]
fn parse_operation_chown_gid() {
assert_eq!(parse_operation("chown-gid").unwrap(), Operation::ChownGid);
}
#[test]
fn xattr_key_user_prefix_parses_to_user_namespace() {
assert_eq!(
parse_xattr_namespace("user.custom").unwrap(),
XattrNamespace::User
);
}
#[test]
fn xattr_key_trusted_prefix_parses_to_trusted_namespace() {
assert_eq!(
parse_xattr_namespace("trusted.overlay").unwrap(),
XattrNamespace::Trusted
);
}
#[test]
fn xattr_key_security_prefix_parses_to_security_namespace() {
assert_eq!(
parse_xattr_namespace("security.selinux").unwrap(),
XattrNamespace::Security
);
}
#[test]
fn xattr_key_posix_acl_prefix_parses_to_system_posix_acl_namespace() {
assert_eq!(
parse_xattr_namespace("system.posix_acl_access").unwrap(),
XattrNamespace::SystemPosixAcl
);
}
#[test]
fn xattr_key_unknown_prefix_returns_error() {
let err = parse_xattr_namespace("bogus.key").unwrap_err();
assert_eq!(err, CliError::InvalidXattrKey("bogus.key".to_string()));
}
#[test]
fn new_mode_parsed_as_octal() {
assert_eq!(parse_new_mode("644").unwrap(), 0o644);
}
#[test]
fn new_mode_with_leading_zero_parsed_as_octal() {
assert_eq!(parse_new_mode("0755").unwrap(), 0o755);
}
#[test]
fn new_mode_invalid_returns_error() {
let err = parse_new_mode("999").unwrap_err();
assert_eq!(err, CliError::InvalidMode("999".to_string()));
}
#[test]
fn resolve_operation_setxattr_with_user_key() {
let op = resolve_operation("setxattr", Some("user.test")).unwrap();
assert_eq!(
op,
Operation::SetXattr {
namespace: XattrNamespace::User
}
);
}
#[test]
fn resolve_operation_setxattr_missing_key_returns_error() {
let err = resolve_operation("setxattr", None).unwrap_err();
assert_eq!(err, CliError::MissingXattrKey);
}
#[test]
fn resolve_operation_read_ignores_xattr_key() {
assert_eq!(
resolve_operation("read", Some("user.irrelevant")).unwrap(),
Operation::Read
);
}