#![cfg_attr(coverage_nightly, coverage(off))]
use crate::models::tdg::{
RecommendationType, TDGAnalysis, TDGBucket, TDGComponents, TDGConfig, TDGDistribution,
TDGHotspot, TDGRecommendation, TDGScore, TDGSeverity, TDGSummary,
};
#[test]
fn test_tdg_severity_from_low() {
let severity = TDGSeverity::from(0.5);
assert_eq!(severity, TDGSeverity::Normal);
}
#[test]
fn test_tdg_severity_from_warning() {
let severity = TDGSeverity::from(2.0);
assert_eq!(severity, TDGSeverity::Warning);
}
#[test]
fn test_tdg_severity_from_critical() {
let severity = TDGSeverity::from(3.0);
assert_eq!(severity, TDGSeverity::Critical);
}
#[test]
fn test_tdg_severity_boundary_normal_warning() {
assert_eq!(TDGSeverity::from(1.5), TDGSeverity::Normal);
assert_eq!(TDGSeverity::from(1.501), TDGSeverity::Warning);
}
#[test]
fn test_tdg_severity_boundary_warning_critical() {
assert_eq!(TDGSeverity::from(2.5), TDGSeverity::Warning);
assert_eq!(TDGSeverity::from(2.501), TDGSeverity::Critical);
}
#[test]
fn test_tdg_severity_as_str() {
assert_eq!(TDGSeverity::Normal.as_str(), "normal");
assert_eq!(TDGSeverity::Warning.as_str(), "warning");
assert_eq!(TDGSeverity::Critical.as_str(), "critical");
}
#[test]
fn test_tdg_severity_serde() {
let severities = vec![
TDGSeverity::Normal,
TDGSeverity::Warning,
TDGSeverity::Critical,
];
for sev in &severities {
let json = serde_json::to_string(sev).unwrap();
let back: TDGSeverity = serde_json::from_str(&json).unwrap();
assert_eq!(*sev, back);
}
}
#[test]
fn test_tdg_severity_rename_all_lowercase() {
let json = serde_json::to_string(&TDGSeverity::Critical).unwrap();
assert!(json.contains("critical"));
}
#[test]
fn test_tdg_components_default() {
let comp = TDGComponents::default();
assert_eq!(comp.complexity, 0.0);
assert_eq!(comp.churn, 0.0);
assert_eq!(comp.coupling, 0.0);
assert_eq!(comp.domain_risk, 0.0);
assert_eq!(comp.duplication, 0.0);
assert_eq!(comp.dead_code, 0.0);
}
#[test]
fn test_tdg_components_serde() {
let comp = TDGComponents {
complexity: 1.5,
churn: 2.0,
coupling: 0.8,
domain_risk: 0.3,
duplication: 0.1,
dead_code: 0.5,
};
let json = serde_json::to_string(&comp).unwrap();
let back: TDGComponents = serde_json::from_str(&json).unwrap();
assert_eq!(back.complexity, 1.5);
assert_eq!(back.dead_code, 0.5);
}
#[test]
fn test_tdg_components_copy() {
let comp = TDGComponents {
complexity: 1.0,
..Default::default()
};
let copied = comp;
assert_eq!(copied.complexity, 1.0);
}
#[test]
fn test_tdg_config_default() {
let config = TDGConfig::default();
assert_eq!(config.complexity_weight, 0.25);
assert_eq!(config.churn_weight, 0.20);
assert_eq!(config.coupling_weight, 0.15);
assert_eq!(config.domain_risk_weight, 0.10);
assert_eq!(config.duplication_weight, 0.10);
assert_eq!(config.dead_code_weight, 0.20);
assert_eq!(config.critical_threshold, 2.5);
assert_eq!(config.warning_threshold, 1.5);
}
#[test]
fn test_tdg_config_weights_sum_to_one() {
let config = TDGConfig::default();
let total = config.complexity_weight
+ config.churn_weight
+ config.coupling_weight
+ config.domain_risk_weight
+ config.duplication_weight
+ config.dead_code_weight;
assert!((total - 1.0).abs() < 0.001);
}
#[test]
fn test_tdg_config_serde() {
let config = TDGConfig::default();
let json = serde_json::to_string(&config).unwrap();
let back: TDGConfig = serde_json::from_str(&json).unwrap();
assert_eq!(back.complexity_weight, config.complexity_weight);
}
#[test]
fn test_tdg_score_serde() {
let score = TDGScore {
value: 1.8,
components: TDGComponents {
complexity: 1.0,
churn: 0.5,
coupling: 0.2,
domain_risk: 0.1,
duplication: 0.0,
dead_code: 0.0,
},
severity: TDGSeverity::Warning,
percentile: 75.0,
confidence: 0.9,
};
let json = serde_json::to_string(&score).unwrap();
let back: TDGScore = serde_json::from_str(&json).unwrap();
assert_eq!(back.value, 1.8);
assert_eq!(back.severity, TDGSeverity::Warning);
}
#[test]
fn test_tdg_summary_serde() {
let summary = TDGSummary {
total_files: 100,
critical_files: 5,
warning_files: 15,
average_tdg: 1.2,
p95_tdg: 2.8,
p99_tdg: 3.5,
estimated_debt_hours: 120.0,
hotspots: vec![],
};
let json = serde_json::to_string(&summary).unwrap();
let back: TDGSummary = serde_json::from_str(&json).unwrap();
assert_eq!(back.total_files, 100);
assert_eq!(back.critical_files, 5);
}
#[test]
fn test_tdg_hotspot_serde() {
let hotspot = TDGHotspot {
path: "src/complex.rs".to_string(),
tdg_score: 3.2,
primary_factor: "complexity".to_string(),
estimated_hours: 8.0,
};
let json = serde_json::to_string(&hotspot).unwrap();
let back: TDGHotspot = serde_json::from_str(&json).unwrap();
assert_eq!(back.path, "src/complex.rs");
}
#[test]
fn test_tdg_recommendation_serde() {
let rec = TDGRecommendation {
recommendation_type: RecommendationType::ReduceComplexity,
action: "Extract method from process_data()".to_string(),
expected_reduction: 0.5,
estimated_hours: 4.0,
priority: 5,
};
let json = serde_json::to_string(&rec).unwrap();
let back: TDGRecommendation = serde_json::from_str(&json).unwrap();
assert_eq!(back.priority, 5);
}
#[test]
fn test_recommendation_type_all_variants_serde() {
let types = vec![
RecommendationType::ReduceComplexity,
RecommendationType::StabilizeChurn,
RecommendationType::ReduceCoupling,
RecommendationType::AddressDomainRisk,
RecommendationType::RemoveDuplication,
RecommendationType::SplitFile,
RecommendationType::AddTests,
];
for rt in &types {
let json = serde_json::to_string(rt).unwrap();
let back: RecommendationType = serde_json::from_str(&json).unwrap();
assert_eq!(*rt, back);
}
}
#[test]
fn test_tdg_analysis_serde() {
let analysis = TDGAnalysis {
score: TDGScore {
value: 1.0,
components: TDGComponents::default(),
severity: TDGSeverity::Normal,
percentile: 50.0,
confidence: 0.8,
},
explanation: "Low complexity".to_string(),
recommendations: vec![],
};
let json = serde_json::to_string(&analysis).unwrap();
let back: TDGAnalysis = serde_json::from_str(&json).unwrap();
assert!(back.recommendations.is_empty());
}
#[test]
fn test_tdg_distribution_serde() {
let dist = TDGDistribution {
buckets: vec![
TDGBucket {
min: 0.0,
max: 1.0,
count: 50,
percentage: 50.0,
},
TDGBucket {
min: 1.0,
max: 2.0,
count: 30,
percentage: 30.0,
},
TDGBucket {
min: 2.0,
max: 5.0,
count: 20,
percentage: 20.0,
},
],
total_files: 100,
};
let json = serde_json::to_string(&dist).unwrap();
let back: TDGDistribution = serde_json::from_str(&json).unwrap();
assert_eq!(back.total_files, 100);
assert_eq!(back.buckets.len(), 3);
}
#[test]
fn test_tdg_bucket_serde() {
let bucket = TDGBucket {
min: 0.0,
max: 1.0,
count: 42,
percentage: 42.0,
};
let json = serde_json::to_string(&bucket).unwrap();
let back: TDGBucket = serde_json::from_str(&json).unwrap();
assert_eq!(back.count, 42);
}