use pmat::models::debug_analysis::*;
use pmat::services::debug_formatters::{format_json, format_markdown, format_text};
use pmat::services::five_whys_analyzer::FiveWhysAnalyzer;
use serde_json::json;
use std::path::Path;
fn create_test_evidence(source: EvidenceSource, value: serde_json::Value) -> Evidence {
Evidence::new(
source,
std::path::PathBuf::from("test.rs"),
"test_metric".to_string(),
value,
"Test interpretation".to_string(),
)
}
#[tokio::test]
async fn test_01_five_whys_executes_with_default_depth() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("Stack overflow in parser", Path::new("."), 5)
.await;
assert!(result.is_ok());
let analysis = result.unwrap();
assert!(analysis.whys.len() <= 5); assert_eq!(analysis.issue, "Stack overflow in parser");
}
#[tokio::test]
async fn test_02_five_whys_supports_custom_depth() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("Memory leak", Path::new("."), 3)
.await
.unwrap();
assert!(result.whys.len() <= 3);
let result = analyzer
.analyze("API timeout", Path::new("."), 10)
.await
.unwrap();
assert!(result.whys.len() <= 10);
}
#[tokio::test]
async fn test_03_five_whys_validates_depth_range() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer.analyze("Issue", Path::new("."), 0).await;
assert!(result.is_err());
let result = analyzer.analyze("Issue", Path::new("."), 11).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_04_why_iteration_has_required_fields() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("Test issue", Path::new("."), 5)
.await
.unwrap();
for why in &result.whys {
assert!(why.depth >= 1 && why.depth <= 5);
assert!(!why.question.is_empty());
assert!(!why.hypothesis.is_empty());
assert!(why.confidence >= 0.0 && why.confidence <= 1.0);
}
}
#[tokio::test]
async fn test_05_gathers_evidence_from_services() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("High complexity", Path::new("."), 5)
.await
.unwrap();
let total_evidence: usize = result.whys.iter().map(|w| w.evidence.len()).sum();
assert!(total_evidence > 0);
}
#[tokio::test]
async fn test_06_09_evidence_gathering() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer.analyze("Issue", Path::new("."), 3).await.unwrap();
for why in &result.whys {
for evidence in &why.evidence {
assert!(!evidence.metric.is_empty());
assert!(!evidence.interpretation.is_empty());
}
}
}
#[tokio::test]
async fn test_10_confidence_increases_with_evidence() {
let analyzer = FiveWhysAnalyzer::new();
let evidence_few = vec![create_test_evidence(
EvidenceSource::Complexity,
json!({"value": 30}),
)];
let confidence_few = analyzer.calculate_confidence(&evidence_few).unwrap();
let evidence_many = vec![
create_test_evidence(EvidenceSource::Complexity, json!({"value": 30})),
create_test_evidence(EvidenceSource::SATD, json!({"count": 5})),
create_test_evidence(EvidenceSource::TDG, json!(35.0)),
];
let confidence_many = analyzer.calculate_confidence(&evidence_many).unwrap();
assert!(confidence_many >= confidence_few);
}
#[tokio::test]
async fn test_11_high_severity_increases_confidence() {
let analyzer = FiveWhysAnalyzer::new();
let evidence_low = vec![create_test_evidence(
EvidenceSource::Complexity,
json!({"value": 10, "threshold": 20}),
)];
let confidence_low = analyzer.calculate_confidence(&evidence_low).unwrap();
let evidence_high = vec![create_test_evidence(
EvidenceSource::Complexity,
json!({"value": 50, "threshold": 20}),
)];
let confidence_high = analyzer.calculate_confidence(&evidence_high).unwrap();
assert!(confidence_high >= confidence_low);
}
#[tokio::test]
async fn test_12_confidence_bounded() {
let analyzer = FiveWhysAnalyzer::new();
let confidence = analyzer.calculate_confidence(&[]).unwrap();
assert!((0.0..=1.0).contains(&confidence));
let evidence = vec![
create_test_evidence(EvidenceSource::Complexity, json!({"value": 1000})),
create_test_evidence(EvidenceSource::SATD, json!({"count": 100})),
];
let confidence = analyzer.calculate_confidence(&evidence).unwrap();
assert!((0.0..=1.0).contains(&confidence));
}
#[tokio::test]
async fn test_13_17_root_cause_and_recommendations() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer.analyze("Issue", Path::new("."), 5).await.unwrap();
assert!(result.root_cause.is_some());
assert!(!result.recommendations.is_empty());
for rec in &result.recommendations {
assert!(!rec.action.is_empty());
}
}
#[tokio::test]
async fn test_18_formats_text_output() {
let analyzer = FiveWhysAnalyzer::new();
let analysis = analyzer.analyze("Test", Path::new("."), 3).await.unwrap();
let output = format_text(&analysis).unwrap();
assert!(output.contains("PMAT Five Whys"));
assert!(output.contains("Why 1:"));
assert!(output.contains("Root Cause:"));
assert!(output.contains("Recommendations:"));
}
#[tokio::test]
async fn test_19_formats_json_output() {
let analyzer = FiveWhysAnalyzer::new();
let analysis = analyzer.analyze("Test", Path::new("."), 3).await.unwrap();
let output = format_json(&analysis).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&output).unwrap();
assert!(parsed["issue"].is_string());
assert!(parsed["whys"].is_array());
}
#[tokio::test]
async fn test_20_formats_markdown_output() {
let analyzer = FiveWhysAnalyzer::new();
let analysis = analyzer.analyze("Test", Path::new("."), 3).await.unwrap();
let output = format_markdown(&analysis).unwrap();
assert!(output.contains("# Five Whys Root Cause Analysis"));
assert!(output.contains("## Why 1:"));
assert!(output.contains("**Hypothesis**:"));
}
#[tokio::test]
async fn test_21_handles_nonexistent_path() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("Issue", Path::new("/nonexistent/path/12345"), 5)
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_22_handles_empty_issue() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer.analyze("", Path::new("."), 5).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_23_26_integration() {
let analyzer = FiveWhysAnalyzer::new();
let result = analyzer
.analyze("Real issue", Path::new("."), 5)
.await
.unwrap();
assert!(!result.issue.is_empty());
assert!(!result.whys.is_empty());
assert!(result.root_cause.is_some());
assert!(!result.recommendations.is_empty());
}