use anyhow::Result;
use std::path::PathBuf;
use crate::bootstrap::validate_security_capabilities;
use crate::commands::check_config::{check_directories, check_nats_connectivity};
use crate::config::{self, Config};
use crate::{health, isolation_tests};
pub struct SelfTestCommand;
impl SelfTestCommand {
pub async fn execute(config_path: PathBuf, comprehensive: bool) -> Result<()> {
println!("๐งช Smith Executor Self-Test");
println!("===========================");
let config = match config::load_config(&config_path) {
Ok(config) => {
println!("โ
Configuration loaded successfully");
config
}
Err(e) => {
println!("โ Configuration failed to load: {}", e);
std::process::exit(1);
}
};
let mut all_tests_passed = true;
all_tests_passed &= Self::run_platform_check().await;
all_tests_passed &= Self::run_security_check().await;
all_tests_passed &= Self::run_isolation_tests(comprehensive).await;
all_tests_passed &= Self::run_directory_validation(&config).await;
all_tests_passed &= Self::run_configuration_validation(&config).await;
Self::run_nats_connectivity_test(&config).await;
Self::print_final_results(all_tests_passed).await;
if !all_tests_passed {
Self::print_troubleshooting_tips();
std::process::exit(1);
}
println!("\nโจ Self-test completed successfully!");
if !comprehensive {
println!("๐ก For comprehensive isolation testing, run:");
println!(" smith-executor self-test --comprehensive");
}
Ok(())
}
async fn run_platform_check() -> bool {
let platform = health::PlatformInfo::detect();
println!("\n๐ฅ๏ธ Platform Information:");
println!("โโ OS: {} {}", platform.os, platform.arch);
println!(
"โโ Linux: {}",
if platform.is_linux {
"โ
Yes"
} else {
"โ No"
}
);
println!(
"โโ Root: {}",
if platform.is_root {
"โ ๏ธ Yes"
} else {
"โ
No"
}
);
true }
async fn run_security_check() -> bool {
let security = health::SecurityStatus::detect();
println!("\n๐ Security Features:");
println!(
"โโ Landlock: {}",
if security.landlock_available {
"โ
Available"
} else {
"โ Not Available"
}
);
println!(
"โโ Seccomp: {}",
if security.seccomp_available {
"โ
Available"
} else {
"โ Not Available"
}
);
println!(
"โโ Cgroups: {}",
if security.cgroups_available {
"โ
Available"
} else {
"โ Not Available"
}
);
println!(
"โโ Namespaces: {}",
if security.namespaces_available {
"โ
Available"
} else {
"โ Not Available"
}
);
true }
async fn run_isolation_tests(comprehensive: bool) -> bool {
let mut tests_passed = true;
println!("\n๐ก๏ธ Quick Isolation Check:");
match isolation_tests::quick_isolation_check().await {
Ok(isolation_ok) => {
if isolation_ok {
println!("โโ Result: โ
Isolation mechanisms appear functional");
} else {
println!("โโ Result: โ ๏ธ Some isolation mechanisms may not be working");
tests_passed = false;
}
}
Err(e) => {
println!("โโ Result: โ Isolation check failed: {}", e);
tests_passed = false;
}
}
if comprehensive {
println!("\n๐งช Comprehensive Isolation Tests:");
match isolation_tests::run_isolation_tests().await {
Ok(results) => {
isolation_tests::print_isolation_report(&results);
if !results.overall_passed() {
tests_passed = false;
}
}
Err(e) => {
println!("โ Comprehensive isolation tests failed: {}", e);
tests_passed = false;
}
}
} else {
println!("โโ Tip: Use --comprehensive for detailed isolation testing");
}
tests_passed
}
async fn run_directory_validation(config: &Config) -> bool {
println!("\n๐ Directory Validation:");
let dir_status = check_directories(config);
println!(
"โโ Work Root: {}",
if dir_status.work_root {
"โ
OK"
} else {
"โ Inaccessible"
}
);
println!(
"โโ State Dir: {}",
if dir_status.state_dir {
"โ
OK"
} else {
"โ Inaccessible"
}
);
println!(
"โโ Audit Dir: {}",
if dir_status.audit_dir {
"โ
OK"
} else {
"โ Inaccessible"
}
);
dir_status.all_valid
}
async fn run_configuration_validation(config: &Config) -> bool {
println!("\nโ๏ธ Configuration Validation:");
let default_backend = if cfg!(target_os = "linux") {
"landlock"
} else {
"gondolin"
};
match validate_security_capabilities(config, false, default_backend) {
Ok(_) => {
println!("โโ Security Configuration: โ
Valid");
true
}
Err(e) => {
println!("โโ Security Configuration: โ Invalid: {}", e);
false
}
}
}
async fn run_nats_connectivity_test(config: &Config) {
println!("\n๐ NATS Connectivity Test:");
let nats_status = check_nats_connectivity(config).await;
if nats_status.connected {
println!("โโ Connection: โ
Connected");
println!(
"โโ JetStream: {}",
if nats_status.jetstream_available {
"โ
Available"
} else {
"โ Not Available"
}
);
} else {
println!("โโ Connection: โ ๏ธ Failed (not critical for self-test)");
if let Some(ref error) = nats_status.error {
println!("โโ Error: {}", error);
}
}
}
async fn print_final_results(all_tests_passed: bool) {
let platform = health::PlatformInfo::detect();
let security = health::SecurityStatus::detect();
println!("\n๐ Self-Test Summary:");
println!(
"โโ Platform: {}",
if platform.is_linux {
"โ
Supported"
} else {
"โ ๏ธ Demo Only"
}
);
println!(
"โโ Security: {}",
if security.overall_secure {
"โ
Full"
} else {
"โ ๏ธ Partial"
}
);
println!(
"โโ Isolation: {}",
if all_tests_passed {
"โ
Working"
} else {
"โ Issues Detected"
}
);
println!(
"โโ Configuration: {}",
if all_tests_passed {
"โ
Valid"
} else {
"โ Issues Detected"
}
);
println!(
"\n๐ Final Status: {}",
if all_tests_passed {
if platform.is_linux && security.overall_secure {
"โ
READY FOR PRODUCTION"
} else {
"โ ๏ธ READY FOR DEVELOPMENT"
}
} else {
"โ CONFIGURATION ISSUES DETECTED"
}
);
}
fn print_troubleshooting_tips() {
println!("\nโ ๏ธ Issues detected during self-test:");
println!(" - Review the failed checks above");
println!(" - Fix configuration or system setup");
println!(" - Re-run self-test to verify fixes");
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_self_test_command_struct() {
let _cmd = SelfTestCommand;
assert!(std::mem::size_of::<SelfTestCommand>() == 0); }
#[test]
fn test_print_troubleshooting_tips() {
SelfTestCommand::print_troubleshooting_tips();
}
#[tokio::test]
async fn test_run_platform_check() {
let result = SelfTestCommand::run_platform_check().await;
assert!(result);
}
#[tokio::test]
async fn test_run_security_check() {
let result = SelfTestCommand::run_security_check().await;
assert!(result);
}
#[tokio::test]
async fn test_print_final_results_passed() {
SelfTestCommand::print_final_results(true).await;
}
#[tokio::test]
async fn test_print_final_results_failed() {
SelfTestCommand::print_final_results(false).await;
}
#[tokio::test]
async fn test_run_isolation_tests_quick() {
let _result = SelfTestCommand::run_isolation_tests(false).await;
}
}