use crate::core::doctor::{CheckResult, Doctor};
use crate::error::Result;
use crate::output::Output;
#[inline]
fn calculate_exit_code(results: &[CheckResult]) -> i32 {
if results.iter().any(|r| r.is_error()) {
2
} else if results.iter().any(|r| r.is_warning()) {
1
} else {
0
}
}
fn exit_with_result_status(results: &[CheckResult]) {
let code = calculate_exit_code(results);
if code != 0 {
std::process::exit(code);
}
}
pub fn execute(output: &Output, fix: bool) -> Result<()> {
let doctor = Doctor::new();
if fix {
output.doctor_header();
let results = doctor.run_and_fix(output);
if output.is_json() {
output.doctor_json(&results);
} else {
output.doctor_summary(&results);
}
exit_with_result_status(&results);
} else {
let results = doctor.run_all();
output.doctor_header();
for result in &results {
output.doctor_check(result);
}
if output.is_json() {
output.doctor_json(&results);
} else {
output.doctor_summary(&results);
}
exit_with_result_status(&results);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::doctor::CheckStatus;
fn make_result(status: CheckStatus) -> CheckResult {
CheckResult {
id: "test",
name: "Test Check",
status,
suggestion: None,
details: None,
}
}
#[test]
fn calculate_exit_code_all_passed_returns_zero() {
let results = vec![make_result(CheckStatus::Ok), make_result(CheckStatus::Ok)];
assert_eq!(calculate_exit_code(&results), 0);
}
#[test]
fn calculate_exit_code_empty_results_returns_zero() {
let results: Vec<CheckResult> = vec![];
assert_eq!(calculate_exit_code(&results), 0);
}
#[test]
fn calculate_exit_code_warnings_only_returns_one() {
let results = vec![
make_result(CheckStatus::Ok),
make_result(CheckStatus::Warning("something".into())),
];
assert_eq!(calculate_exit_code(&results), 1);
}
#[test]
fn calculate_exit_code_errors_only_returns_two() {
let results = vec![
make_result(CheckStatus::Ok),
make_result(CheckStatus::Error("critical".into())),
];
assert_eq!(calculate_exit_code(&results), 2);
}
#[test]
fn calculate_exit_code_mixed_errors_and_warnings_returns_two() {
let results = vec![
make_result(CheckStatus::Warning("minor".into())),
make_result(CheckStatus::Error("major".into())),
make_result(CheckStatus::Ok),
];
assert_eq!(calculate_exit_code(&results), 2);
}
#[test]
fn calculate_exit_code_multiple_warnings_returns_one() {
let results = vec![
make_result(CheckStatus::Warning("warn1".into())),
make_result(CheckStatus::Warning("warn2".into())),
];
assert_eq!(calculate_exit_code(&results), 1);
}
#[test]
fn calculate_exit_code_multiple_errors_returns_two() {
let results = vec![
make_result(CheckStatus::Error("err1".into())),
make_result(CheckStatus::Error("err2".into())),
];
assert_eq!(calculate_exit_code(&results), 2);
}
}