#[test]
fn test_risk_statistics_struct_construction() {
let stats = RiskStatistics {
high_risk: 5,
medium_risk: 10,
low_risk: 15,
};
assert_eq!(stats.high_risk, 5);
assert_eq!(stats.medium_risk, 10);
assert_eq!(stats.low_risk, 15);
}
#[test]
fn test_format_defect_summary_single_file() {
let predictions = vec![("only_file.rs".to_string(), create_high_risk_score())];
let elapsed = Duration::from_millis(50);
let result = format_defect_summary(&predictions, elapsed).unwrap();
assert!(result.contains("1 files"));
assert!(result.contains("only_file.rs"));
}
#[test]
fn test_format_with_special_characters_in_filename() {
let predictions = vec![("src/my-file_v2.0.rs".to_string(), create_high_risk_score())];
let elapsed = Duration::from_millis(50);
let result = format_defect_summary(&predictions, elapsed).unwrap();
assert!(result.contains("my-file_v2.0.rs"));
let csv = format_defect_csv(&predictions).unwrap();
assert!(csv.contains("my-file_v2.0.rs"));
}
#[test]
fn test_format_with_unicode_filename() {
let predictions = vec![(
"src/archivo_espa\u{00f1}ol.rs".to_string(),
create_medium_risk_score(),
)];
let elapsed = Duration::from_millis(50);
let result = format_defect_json(&predictions, elapsed).unwrap();
assert!(result.contains("archivo_espa\u{00f1}ol.rs"));
}
#[test]
fn test_format_with_zero_duration() {
let predictions = create_test_predictions();
let elapsed = Duration::from_millis(0);
let result = format_defect_summary(&predictions, elapsed).unwrap();
assert!(result.contains("Analysis time"));
let json = format_defect_json(&predictions, elapsed).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&json).unwrap();
assert_eq!(parsed["summary"]["analysis_time_ms"], 0);
}
#[test]
fn test_format_with_very_long_duration() {
let predictions = create_test_predictions();
let elapsed = Duration::from_secs(3600);
let result = format_defect_summary(&predictions, elapsed).unwrap();
assert!(result.contains("Analysis time"));
}
#[test]
fn test_probability_exactly_zero() {
let score = create_mock_defect_score(0.0, 0.9, RiskLevel::Low);
let predictions = vec![("zero.rs".to_string(), score)];
let stats = calculate_risk_statistics(&predictions);
assert_eq!(stats.low_risk, 1);
assert_eq!(stats.medium_risk, 0);
assert_eq!(stats.high_risk, 0);
}
#[test]
fn test_probability_exactly_one() {
let score = create_mock_defect_score(1.0, 0.9, RiskLevel::High);
let predictions = vec![("max.rs".to_string(), score)];
let stats = calculate_risk_statistics(&predictions);
assert_eq!(stats.high_risk, 1);
assert_eq!(stats.medium_risk, 0);
assert_eq!(stats.low_risk, 0);
}
#[test]
fn test_format_defect_output_all_formats_empty_predictions() {
let predictions: Vec<(String, DefectScore)> = vec![];
let elapsed = Duration::from_millis(50);
assert!(format_defect_output(
DefectPredictionOutputFormat::Summary,
&predictions,
elapsed,
false
)
.is_ok());
assert!(format_defect_output(
DefectPredictionOutputFormat::Json,
&predictions,
elapsed,
false
)
.is_ok());
assert!(format_defect_output(
DefectPredictionOutputFormat::Detailed,
&predictions,
elapsed,
true
)
.is_ok());
assert!(format_defect_output(
DefectPredictionOutputFormat::Sarif,
&predictions,
elapsed,
false
)
.is_ok());
assert!(format_defect_output(
DefectPredictionOutputFormat::Csv,
&predictions,
elapsed,
false
)
.is_ok());
}
#[test]
fn test_format_defect_detailed_empty() {
let predictions: Vec<(String, DefectScore)> = vec![];
let elapsed = Duration::from_millis(100);
let result = format_defect_detailed(&predictions, elapsed, true).unwrap();
assert!(result.contains("Detailed Report"));
assert!(result.contains("Analysis time"));
}
#[test]
fn test_format_defect_detailed_many_files() {
let predictions: Vec<_> = (0..50)
.map(|i| (format!("file{i}.rs"), create_medium_risk_score()))
.collect();
let elapsed = Duration::from_millis(500);
let result = format_defect_detailed(&predictions, elapsed, false).unwrap();
assert!(result.contains("file0.rs"));
assert!(result.contains("file49.rs"));
}
#[test]
fn test_format_defect_json_contributing_factors() {
let predictions = create_test_predictions();
let elapsed = Duration::from_millis(100);
let result = format_defect_json(&predictions, elapsed).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
let pred = &parsed["predictions"][0];
let factors = pred["contributing_factors"].as_array().unwrap();
assert_eq!(factors.len(), 4);
}
#[test]
fn test_format_defect_json_recommendations() {
let predictions = create_test_predictions();
let elapsed = Duration::from_millis(100);
let result = format_defect_json(&predictions, elapsed).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
let pred = &parsed["predictions"][0];
let recs = pred["recommendations"].as_array().unwrap();
assert_eq!(recs.len(), 2);
}
#[test]
fn test_format_defect_sarif_properties() {
let predictions = create_test_predictions();
let result = format_defect_sarif(&predictions).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
let result_item = &parsed["runs"][0]["results"][0];
let props = &result_item["properties"];
assert!(props["probability"].is_f64());
assert!(props["confidence"].is_f64());
assert!(props["contributing_factors"].is_array());
assert!(props["recommendations"].is_array());
}
#[test]
fn test_format_defect_sarif_locations() {
let predictions = create_test_predictions();
let result = format_defect_sarif(&predictions).unwrap();
let parsed: serde_json::Value = serde_json::from_str(&result).unwrap();
let result_item = &parsed["runs"][0]["results"][0];
let location = &result_item["locations"][0];
assert!(location["physicalLocation"]["artifactLocation"]["uri"].is_string());
assert_eq!(
location["physicalLocation"]["artifactLocation"]["uriBaseId"],
"%SRCROOT%"
);
}
#[test]
fn test_format_defect_csv_with_comma_in_factor() {
let mut score = create_high_risk_score();
score.contributing_factors = vec![("factor,with,commas".to_string(), 0.5)];
let predictions = vec![("test.rs".to_string(), score)];
let result = format_defect_csv(&predictions).unwrap();
let lines: Vec<&str> = result.lines().collect();
assert_eq!(lines.len(), 2);
}
#[test]
fn test_risk_statistics_with_various_probabilities() {
let predictions = vec![
(
"p_0.rs".to_string(),
create_mock_defect_score(0.0, 0.9, RiskLevel::Low),
),
(
"p_15.rs".to_string(),
create_mock_defect_score(0.15, 0.9, RiskLevel::Low),
),
(
"p_30.rs".to_string(),
create_mock_defect_score(0.30, 0.9, RiskLevel::Low),
), (
"p_35.rs".to_string(),
create_mock_defect_score(0.35, 0.9, RiskLevel::Medium),
),
(
"p_50.rs".to_string(),
create_mock_defect_score(0.50, 0.9, RiskLevel::Medium),
),
(
"p_70.rs".to_string(),
create_mock_defect_score(0.70, 0.9, RiskLevel::Medium),
), (
"p_75.rs".to_string(),
create_mock_defect_score(0.75, 0.9, RiskLevel::High),
),
(
"p_100.rs".to_string(),
create_mock_defect_score(1.0, 0.9, RiskLevel::High),
),
];
let stats = calculate_risk_statistics(&predictions);
assert_eq!(stats.high_risk, 2);
assert_eq!(stats.medium_risk, 3);
assert_eq!(stats.low_risk, 3);
}