#[allow(clippy::duplicate_mod)]
#[path = "fixtures/mod.rs"]
mod fixtures;
use fixtures::{MockAccessLevel, MockHandler, TEST_TREE};
use nut_shell::shell::handler::CommandHandler;
use nut_shell::tree::{CommandKind, Node};
#[cfg(feature = "async")]
use nut_shell::error::CliError;
#[test]
fn test_metadata_matches_handler() {
let handler = MockHandler;
if let Some(Node::Command(cmd)) = TEST_TREE.find_child("help") {
assert_eq!(cmd.name, "help");
assert_eq!(cmd.kind, CommandKind::Sync);
assert!(handler.execute_sync("help", &[]).is_ok());
} else {
panic!("help command not found in TEST_TREE");
}
if let Some(Node::Command(cmd)) = TEST_TREE.find_child("echo") {
assert_eq!(cmd.name, "echo");
assert_eq!(cmd.kind, CommandKind::Sync);
assert!(handler.execute_sync("echo", &[]).is_ok());
} else {
panic!("echo command not found in TEST_TREE");
}
}
#[test]
#[cfg(feature = "async")]
fn test_async_command_metadata() {
use fixtures::CMD_ASYNC_WAIT;
assert_eq!(CMD_ASYNC_WAIT.name, "async-wait");
assert_eq!(CMD_ASYNC_WAIT.kind, CommandKind::Async);
assert_eq!(CMD_ASYNC_WAIT.min_args, 0);
assert_eq!(CMD_ASYNC_WAIT.max_args, 1);
}
#[test]
#[cfg(feature = "async")]
fn test_async_command_in_tree() {
use fixtures::DIR_SYSTEM;
let async_cmd = DIR_SYSTEM.find_child("async-wait");
assert!(async_cmd.is_some());
if let Some(Node::Command(cmd)) = async_cmd {
assert_eq!(cmd.name, "async-wait");
assert_eq!(cmd.kind, CommandKind::Async);
} else {
panic!("async-wait should be a command node");
}
}
#[cfg(feature = "async")]
#[tokio::test]
async fn test_async_command_execution() {
let handler = MockHandler;
let result = handler.execute_async("async-wait", &[]).await;
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.message.as_str().contains("Waited 100ms"));
let result = handler.execute_async("async-wait", &["250"]).await;
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.message.as_str().contains("Waited 250ms"));
let result = handler.execute_async("unknown-async", &[]).await;
assert_eq!(result, Err(CliError::CommandNotFound));
}
#[test]
fn test_node_api() {
let help_node = TEST_TREE
.find_child("help")
.expect("help command should exist");
assert!(help_node.is_command(), "help should be a command");
assert!(!help_node.is_directory(), "help should not be a directory");
assert_eq!(help_node.name(), "help", "help name should match");
assert_eq!(
help_node.access_level(),
MockAccessLevel::Guest,
"help should be Guest level"
);
let system_node = TEST_TREE
.find_child("system")
.expect("system directory should exist");
assert!(system_node.is_directory(), "system should be a directory");
assert!(!system_node.is_command(), "system should not be a command");
assert_eq!(system_node.name(), "system", "system name should match");
assert_eq!(
system_node.access_level(),
MockAccessLevel::User,
"system should be User level"
);
assert!(
TEST_TREE.find_child("help").is_some(),
"should find existing child"
);
assert!(
TEST_TREE.find_child("nonexistent").is_none(),
"should not find non-existent child"
);
if let Some(Node::Directory(system)) = TEST_TREE.find_child("system") {
assert!(
system.find_child("status").is_some(),
"should find status in system"
);
assert!(
system.find_child("reboot").is_some(),
"should find reboot in system"
);
assert!(
system.find_child("missing").is_none(),
"should not find missing child"
);
} else {
panic!("system should be a directory");
}
}
#[test]
fn test_varied_argument_counts() {
use fixtures::{CMD_ECHO, CMD_HELP, CMD_HW_LED, CMD_NET_CONFIG, CMD_NET_PING};
assert_eq!(CMD_HELP.min_args, 0);
assert_eq!(CMD_HELP.max_args, 0);
assert_eq!(CMD_ECHO.min_args, 0);
assert_eq!(CMD_ECHO.max_args, 16);
assert_eq!(CMD_NET_CONFIG.min_args, 2);
assert_eq!(CMD_NET_CONFIG.max_args, 4);
assert_eq!(CMD_NET_PING.min_args, 1);
assert_eq!(CMD_NET_PING.max_args, 2);
assert_eq!(CMD_HW_LED.min_args, 1);
assert_eq!(CMD_HW_LED.max_args, 1);
}