use std::collections::HashSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cli001Verdict { Pass, Fail }
#[must_use]
pub fn verdict_from_help_responsive<S1, S2>(
registered: &HashSet<String, S1>,
responds_to_help: &HashSet<String, S2>,
) -> Cli001Verdict
where
S1: std::hash::BuildHasher,
S2: std::hash::BuildHasher,
{
if registered.is_empty() { return Cli001Verdict::Fail; }
for cmd in registered {
if !responds_to_help.contains(cmd) { return Cli001Verdict::Fail; }
}
Cli001Verdict::Pass
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cli002Verdict { Pass, Fail }
#[must_use]
pub fn verdict_from_no_undocumented_commands<S1, S2>(
apr_help_output: &HashSet<String, S1>,
registered: &HashSet<String, S2>,
) -> Cli002Verdict
where
S1: std::hash::BuildHasher,
S2: std::hash::BuildHasher,
{
if apr_help_output.is_empty() { return Cli002Verdict::Fail; }
for cmd in apr_help_output {
if !registered.contains(cmd) { return Cli002Verdict::Fail; }
}
Cli002Verdict::Pass
}
pub const AC_CLI_003_ALLOWED_EXIT_CODES: [i32; 3] = [0, 1, 2];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cli003Verdict { Pass, Fail }
#[must_use]
pub fn verdict_from_canonical_exit_code(exit_code: i32) -> Cli003Verdict {
if AC_CLI_003_ALLOWED_EXIT_CODES.contains(&exit_code) {
Cli003Verdict::Pass
} else {
Cli003Verdict::Fail
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HelpOutcome {
PrintedSuccess,
NonZeroExitNoPanic,
Panicked,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cli004Verdict { Pass, Fail }
#[must_use]
pub const fn verdict_from_help_outcome(outcome: HelpOutcome) -> Cli004Verdict {
match outcome {
HelpOutcome::PrintedSuccess | HelpOutcome::NonZeroExitNoPanic => Cli004Verdict::Pass,
HelpOutcome::Panicked => Cli004Verdict::Fail,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn s(items: &[&str]) -> HashSet<String> {
items.iter().map(|i| (*i).to_string()).collect()
}
#[test] fn cli001_pass_full_help_coverage() {
let reg = s(&["run", "serve", "validate"]);
let help = s(&["run", "serve", "validate"]);
assert_eq!(verdict_from_help_responsive(®, &help), Cli001Verdict::Pass);
}
#[test] fn cli001_pass_help_superset() {
let reg = s(&["run", "serve"]);
let help = s(&["run", "serve", "extra"]);
assert_eq!(verdict_from_help_responsive(®, &help), Cli001Verdict::Pass);
}
#[test] fn cli001_fail_missing_help() {
let reg = s(&["run", "serve", "validate"]);
let help = s(&["run", "serve"]); assert_eq!(verdict_from_help_responsive(®, &help), Cli001Verdict::Fail);
}
#[test] fn cli001_fail_empty_registry() {
let reg = HashSet::new();
let help = s(&["run"]);
assert_eq!(verdict_from_help_responsive(®, &help), Cli001Verdict::Fail);
}
#[test] fn cli002_pass_help_subset() {
let help = s(&["run", "serve"]);
let reg = s(&["run", "serve", "validate"]);
assert_eq!(verdict_from_no_undocumented_commands(&help, ®), Cli002Verdict::Pass);
}
#[test] fn cli002_fail_undocumented() {
let help = s(&["run", "serve", "secret_cmd"]);
let reg = s(&["run", "serve"]);
assert_eq!(verdict_from_no_undocumented_commands(&help, ®), Cli002Verdict::Fail);
}
#[test] fn cli002_fail_empty_help() {
let help = HashSet::new();
let reg = s(&["run"]);
assert_eq!(verdict_from_no_undocumented_commands(&help, ®), Cli002Verdict::Fail);
}
#[test] fn cli003_pass_success() { assert_eq!(verdict_from_canonical_exit_code(0), Cli003Verdict::Pass); }
#[test] fn cli003_pass_runtime_error() { assert_eq!(verdict_from_canonical_exit_code(1), Cli003Verdict::Pass); }
#[test] fn cli003_pass_usage_error() { assert_eq!(verdict_from_canonical_exit_code(2), Cli003Verdict::Pass); }
#[test] fn cli003_fail_panic_exit() {
assert_eq!(verdict_from_canonical_exit_code(101), Cli003Verdict::Fail);
}
#[test] fn cli003_fail_signal_exit() {
assert_eq!(verdict_from_canonical_exit_code(137), Cli003Verdict::Fail);
}
#[test] fn cli003_fail_negative() {
assert_eq!(verdict_from_canonical_exit_code(-1), Cli003Verdict::Fail);
}
#[test] fn cli003_fail_3() {
assert_eq!(verdict_from_canonical_exit_code(3), Cli003Verdict::Fail);
}
#[test] fn cli004_pass_printed() {
assert_eq!(verdict_from_help_outcome(HelpOutcome::PrintedSuccess), Cli004Verdict::Pass);
}
#[test] fn cli004_pass_nonzero_no_panic() {
assert_eq!(verdict_from_help_outcome(HelpOutcome::NonZeroExitNoPanic), Cli004Verdict::Pass);
}
#[test] fn cli004_fail_panicked() {
assert_eq!(verdict_from_help_outcome(HelpOutcome::Panicked), Cli004Verdict::Fail);
}
#[test] fn provenance_exit_codes() {
assert_eq!(AC_CLI_003_ALLOWED_EXIT_CODES, [0, 1, 2]);
}
}