#![cfg_attr(coverage_nightly, coverage(off))]
use crate::cli::analysis_utilities::{
apply_satd_filters, get_severity_icon, handle_quality_gate, QualityGateResults,
QualityViolation,
};
use crate::cli::{QualityCheckType, QualityGateOutputFormat, SatdSeverity};
use crate::services::satd_detector::{DebtCategory, Severity, TechnicalDebt};
use std::path::PathBuf;
fn create_test_debt(severity: Severity, text: &str) -> TechnicalDebt {
TechnicalDebt {
file: PathBuf::from("test.rs"),
line: 10,
column: 5,
text: text.to_string(),
category: DebtCategory::Requirement,
severity,
context_hash: [0u8; 16],
}
}
#[test]
fn test_apply_satd_filters_no_filters() {
let items = vec![
create_test_debt(Severity::Low, "Low debt"),
create_test_debt(Severity::Medium, "Medium debt"),
create_test_debt(Severity::High, "High debt"),
create_test_debt(Severity::Critical, "Critical debt"),
];
let filtered = apply_satd_filters(items, None, false);
assert_eq!(filtered.len(), 4);
}
#[test]
fn test_apply_satd_filters_severity_low() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, Some(SatdSeverity::Low), false);
assert_eq!(filtered.len(), 4); }
#[test]
fn test_apply_satd_filters_severity_medium() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, Some(SatdSeverity::Medium), false);
assert!(filtered.len() >= 3); assert!(filtered
.iter()
.all(|d| d.severity as u8 >= Severity::Medium as u8));
}
#[test]
fn test_apply_satd_filters_severity_high() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, Some(SatdSeverity::High), false);
assert!(filtered.len() >= 2); }
#[test]
fn test_apply_satd_filters_severity_critical() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, Some(SatdSeverity::Critical), false);
assert!(filtered.len() >= 1); }
#[test]
fn test_apply_satd_filters_critical_only() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, None, true);
assert!(filtered.len() >= 1);
assert!(filtered
.iter()
.all(|d| matches!(d.severity, Severity::Critical | Severity::High)));
}
#[test]
fn test_apply_satd_filters_empty() {
let items: Vec<TechnicalDebt> = vec![];
let filtered = apply_satd_filters(items, None, false);
assert!(filtered.is_empty());
}
#[test]
fn test_apply_satd_filters_combined() {
let items = vec![
create_test_debt(Severity::Low, "Low"),
create_test_debt(Severity::Medium, "Medium"),
create_test_debt(Severity::High, "High"),
create_test_debt(Severity::Critical, "Critical"),
];
let filtered = apply_satd_filters(items, Some(SatdSeverity::Medium), true);
assert!(filtered
.iter()
.all(|d| matches!(d.severity, Severity::Critical | Severity::High)));
}
#[test]
fn test_get_severity_icon_error() {
assert_eq!(get_severity_icon("error"), "🔴");
}
#[test]
fn test_get_severity_icon_warning() {
assert_eq!(get_severity_icon("warning"), "🟡");
}
#[test]
fn test_get_severity_icon_other() {
assert_eq!(get_severity_icon("info"), "🟢");
assert_eq!(get_severity_icon("unknown"), "🟢");
assert_eq!(get_severity_icon(""), "🟢");
}
#[test]
fn test_quality_gate_results_default() {
let results = QualityGateResults::default();
assert!(results.passed);
assert_eq!(results.total_violations, 0);
assert_eq!(results.complexity_violations, 0);
assert_eq!(results.dead_code_violations, 0);
assert_eq!(results.satd_violations, 0);
assert_eq!(results.entropy_violations, 0);
assert_eq!(results.security_violations, 0);
assert_eq!(results.duplicate_violations, 0);
assert_eq!(results.coverage_violations, 0);
assert_eq!(results.section_violations, 0);
assert_eq!(results.provability_violations, 0);
assert!(results.provability_score.is_none());
}
#[test]
fn test_quality_violation_construction() {
let violation = QualityViolation {
check_type: "complexity".to_string(),
severity: "error".to_string(),
file: "src/main.rs".to_string(),
line: Some(42),
message: "Function too complex".to_string(),
details: None,
};
assert_eq!(violation.check_type, "complexity");
assert_eq!(violation.severity, "error");
assert_eq!(violation.line, Some(42));
}
#[test]
fn test_quality_violation_no_line() {
let violation = QualityViolation {
check_type: "dead_code".to_string(),
severity: "warning".to_string(),
file: "src/lib.rs".to_string(),
line: None,
message: "Unused module".to_string(),
details: None,
};
assert!(violation.line.is_none());
}
#[test]
fn test_quality_violation_empty_file() {
let violation = QualityViolation {
check_type: "entropy".to_string(),
severity: "info".to_string(),
file: String::new(),
line: None,
message: "Low entropy".to_string(),
details: None,
};
assert!(violation.file.is_empty());
}
#[test]
fn test_quality_check_type_variants() {
use clap::ValueEnum;
let variants = QualityCheckType::value_variants();
assert!(variants.len() >= 8);
for v in variants {
let _ = format!("{:?}", v);
let _ = v.to_possible_value();
}
}
#[test]
fn test_quality_gate_output_format_variants() {
use clap::ValueEnum;
let variants = QualityGateOutputFormat::value_variants();
assert!(variants.len() >= 3);
for v in variants {
let _ = format!("{:?}", v);
let _ = v.to_possible_value();
}
}
#[test]
fn test_satd_severity_variants() {
use clap::ValueEnum;
let variants = SatdSeverity::value_variants();
assert_eq!(variants.len(), 4);
for v in variants {
let _ = format!("{:?}", v);
let _ = v.to_possible_value();
}
}
#[test]
fn test_quality_check_type_display() {
use crate::models::quality_gate::QualityCheckType as ModelQualityCheckType;
assert_eq!(
format!("{}", ModelQualityCheckType::Complexity),
"complexity"
);
assert_eq!(format!("{}", ModelQualityCheckType::DeadCode), "dead_code");
assert_eq!(format!("{}", ModelQualityCheckType::Satd), "satd");
assert_eq!(format!("{}", ModelQualityCheckType::Security), "security");
assert_eq!(format!("{}", ModelQualityCheckType::Entropy), "entropy");
assert_eq!(
format!("{}", ModelQualityCheckType::Duplicates),
"duplicates"
);
assert_eq!(format!("{}", ModelQualityCheckType::Coverage), "coverage");
}
#[tokio::test]
async fn test_handle_quality_gate_nonexistent_file() {
let result = handle_quality_gate(
PathBuf::from("."),
Some(PathBuf::from("/nonexistent/file.rs")),
QualityGateOutputFormat::Json,
false,
vec![QualityCheckType::Security],
15.0,
0.5,
20,
false,
None,
false,
)
.await;
assert!(result.is_ok());
}