use std::sync::{Mutex, OnceLock};
use modcli::command::Command;
use modcli::error::ModCliError;
use modcli::loader::CommandRegistry;
static EXEC_LOG: OnceLock<Mutex<Vec<&'static str>>> = OnceLock::new();
fn log_exec(label: &'static str) {
EXEC_LOG
.get_or_init(|| Mutex::new(Vec::new()))
.lock()
.unwrap()
.push(label);
}
#[derive(Default)]
struct AliasCmd;
impl Command for AliasCmd {
fn name(&self) -> &str {
"primary"
}
fn aliases(&self) -> &[&str] {
&["alt", "p"]
}
fn help(&self) -> Option<&str> {
Some("Alias test command")
}
fn validate(&self, _args: &[String]) -> Result<(), ModCliError> {
Ok(())
}
fn execute(&self, _args: &[String]) {
log_exec("alias_executed")
}
}
#[derive(Default)]
struct InvalidCmd;
impl Command for InvalidCmd {
fn name(&self) -> &str {
"bad"
}
fn help(&self) -> Option<&str> {
Some("Always invalid")
}
fn validate(&self, _args: &[String]) -> Result<(), ModCliError> {
Err(ModCliError::InvalidUsage("invalid on purpose".into()))
}
fn execute(&self, _args: &[String]) {
panic!("execute() should NOT be called when validate() fails");
}
}
#[test]
fn alias_resolution_executes_primary_command() {
let mut reg = CommandRegistry::new();
reg.register(Box::new(AliasCmd));
reg.execute("alt", &[]);
let log = EXEC_LOG.get().unwrap().lock().unwrap();
assert!(
log.contains(&"alias_executed"),
"alias did not route to primary command"
);
}
#[test]
fn validate_error_prevents_execute() {
let mut reg = CommandRegistry::new();
reg.register(Box::new(InvalidCmd));
reg.execute("bad", &[]);
}