pub const OK: i32 = 0;
pub const ERROR: i32 = 1;
pub const USAGE: i32 = 64;
pub const CONFIG: i32 = 78;
pub const NEEDS_SETUP: i32 = 100;
pub const DAEMON_DOWN: i32 = 101;
pub const NO_WORKERS: i32 = 102;
pub const ALREADY_CURRENT: i32 = 103;
pub const LOCKED: i32 = 104;
pub const NEEDS_MIGRATION: i32 = 105;
pub fn message(code: i32) -> &'static str {
match code {
OK => "Success",
ERROR => "General error",
USAGE => "Invalid command line usage",
CONFIG => "Configuration error",
NEEDS_SETUP => "RCH needs initial setup (run: rch setup)",
DAEMON_DOWN => "RCH daemon is not running (run: rchd start)",
NO_WORKERS => "No workers configured (run: rch setup workers)",
ALREADY_CURRENT => "Already at requested version",
LOCKED => "Operation locked by another process",
NEEDS_MIGRATION => "Config needs migration (run: rch config migrate)",
_ => "Unknown error",
}
}
pub fn is_success(code: i32) -> bool {
code == OK
}
pub fn is_setup_required(code: i32) -> bool {
matches!(code, NEEDS_SETUP | NO_WORKERS | NEEDS_MIGRATION)
}
#[cfg(test)]
mod tests {
use super::*;
use tracing::info;
fn log_test_start(name: &str) {
info!("TEST START: {}", name);
}
fn log_test_pass(name: &str) {
info!("TEST PASS: {}", name);
}
#[test]
fn test_exit_code_values() {
log_test_start("test_exit_code_values");
assert_eq!(OK, 0);
assert_eq!(ERROR, 1);
assert_eq!(USAGE, 64);
assert_eq!(CONFIG, 78);
assert_eq!(NEEDS_SETUP, 100);
assert_eq!(DAEMON_DOWN, 101);
assert_eq!(NO_WORKERS, 102);
assert_eq!(ALREADY_CURRENT, 103);
assert_eq!(LOCKED, 104);
assert_eq!(NEEDS_MIGRATION, 105);
log_test_pass("test_exit_code_values");
}
#[test]
fn test_message() {
log_test_start("test_message");
assert_eq!(message(OK), "Success");
assert!(message(NEEDS_SETUP).contains("setup"));
assert!(message(DAEMON_DOWN).contains("daemon"));
assert!(message(NO_WORKERS).contains("workers"));
assert_eq!(message(999), "Unknown error");
log_test_pass("test_message");
}
#[test]
fn test_is_success() {
log_test_start("test_is_success");
assert!(is_success(OK));
assert!(!is_success(ERROR));
assert!(!is_success(NEEDS_SETUP));
log_test_pass("test_is_success");
}
#[test]
fn test_is_setup_required() {
log_test_start("test_is_setup_required");
assert!(is_setup_required(NEEDS_SETUP));
assert!(is_setup_required(NO_WORKERS));
assert!(is_setup_required(NEEDS_MIGRATION));
assert!(!is_setup_required(OK));
assert!(!is_setup_required(ERROR));
assert!(!is_setup_required(DAEMON_DOWN));
log_test_pass("test_is_setup_required");
}
#[test]
fn test_signal_like_codes_are_failures() {
log_test_start("test_signal_like_codes_are_failures");
let signal_like_codes = [128, 130, 137];
for code in signal_like_codes {
assert!(!is_success(code));
assert!(!is_setup_required(code));
assert_eq!(message(code), "Unknown error");
}
log_test_pass("test_signal_like_codes_are_failures");
}
}