use std::collections::HashMap;
use std::time::{Duration, Instant};
pub struct CodeAnalyzer {
config: AnalyzerConfig,
history: AnalysisHistory,
baselines: HashMap<String, QualityBaseline>,
}
#[derive(Debug, Clone)]
pub struct AnalyzerConfig {
pub analysis_depth: AnalysisDepth,
pub track_trends: bool,
pub max_analysis_time: Duration,
pub thresholds: QualityThresholds,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AnalysisDepth {
Surface,
Standard,
Deep,
Exhaustive,
}
#[derive(Debug, Clone)]
pub struct QualityThresholds {
pub min_quality_score: f64,
pub max_complexity: u32,
pub min_coverage: f64,
pub max_technical_debt: f64,
}
#[derive(Debug)]
struct AnalysisHistory {
results: Vec<AnalysisResult>,
max_entries: usize,
}
#[derive(Debug, Clone)]
pub struct QualityBaseline {
pub component: String,
pub quality_score: f64,
pub complexity: u32,
pub performance: BaselinePerformance,
pub timestamp: Instant,
}
#[derive(Debug, Clone)]
pub struct BaselinePerformance {
pub avg_execution_time: Duration,
pub memory_per_operation: usize,
pub error_rate: f64,
}
#[derive(Debug, Clone)]
pub struct AnalysisReport {
pub component: String,
pub quality_assessment: QualityAssessment,
pub metrics: Vec<QualityMetric>,
pub issues: Vec<QualityIssue>,
pub performance_analysis: PerformanceAnalysis,
pub recommendations: Vec<Recommendation>,
pub trend_analysis: Option<TrendAnalysis>,
pub analysis_duration: Duration,
}
#[derive(Debug, Clone)]
pub struct QualityAssessment {
pub overall_score: f64,
pub grade: QualityGrade,
pub confidence: f64,
pub strengths: Vec<String>,
pub weaknesses: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum QualityGrade {
A,
B,
C,
D,
F,
}
impl PartialOrd for QualityGrade {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for QualityGrade {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let self_score = match self {
QualityGrade::A => 5,
QualityGrade::B => 4,
QualityGrade::C => 3,
QualityGrade::D => 2,
QualityGrade::F => 1,
};
let other_score = match other {
QualityGrade::A => 5,
QualityGrade::B => 4,
QualityGrade::C => 3,
QualityGrade::D => 2,
QualityGrade::F => 1,
};
self_score.cmp(&other_score)
}
}
impl Eq for QualityGrade {}
#[derive(Debug, Clone)]
pub struct QualityMetric {
pub name: String,
pub category: MetricCategory,
pub value: f64,
pub target: f64,
pub meets_target: bool,
pub weight: f64,
pub trend: TrendDirection,
}
#[derive(Debug, Clone, PartialEq)]
pub enum MetricCategory {
Performance,
Reliability,
Maintainability,
Security,
Efficiency,
}
#[derive(Debug, Clone)]
pub struct QualityIssue {
pub id: String,
pub title: String,
pub description: String,
pub severity: IssueSeverity,
pub category: IssueCategory,
pub location: Option<String>,
pub fix_effort: FixEffort,
pub impact: ImpactLevel,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum IssueSeverity {
Minor,
Moderate,
Major,
Critical,
Blocker,
}
#[derive(Debug, Clone, PartialEq)]
pub enum IssueCategory {
MemoryManagement,
Performance,
ThreadSafety,
ErrorHandling,
CodeStyle,
Design,
}
#[derive(Debug, Clone, PartialEq)]
pub enum FixEffort {
Trivial,
Easy,
Medium,
Hard,
VeryHard,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ImpactLevel {
Minimal,
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone)]
pub struct PerformanceAnalysis {
pub score: f64,
pub bottlenecks: Vec<PerformanceBottleneck>,
pub memory_efficiency: f64,
pub cpu_efficiency: f64,
pub scalability: ScalabilityAssessment,
}
#[derive(Debug, Clone)]
pub struct PerformanceBottleneck {
pub location: String,
pub bottleneck_type: BottleneckType,
pub severity: f64,
pub description: String,
pub optimization: String,
}
#[derive(Debug, Clone, PartialEq)]
pub enum BottleneckType {
CpuBound,
MemoryBound,
IoBound,
LockContention,
CacheMiss,
AlgorithmInefficiency,
}
#[derive(Debug, Clone)]
pub struct ScalabilityAssessment {
pub score: f64,
pub scaling_behavior: ScalingBehavior,
pub resource_scaling: ResourceScaling,
pub limitations: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ScalingBehavior {
Constant,
Linear,
Logarithmic,
Quadratic,
Exponential,
}
#[derive(Debug, Clone)]
pub struct ResourceScaling {
pub memory_factor: f64,
pub cpu_factor: f64,
pub network_factor: f64,
}
#[derive(Debug, Clone)]
pub struct Recommendation {
pub title: String,
pub description: String,
pub priority: RecommendationPriority,
pub impact: ImpactLevel,
pub effort: FixEffort,
pub related_issues: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum RecommendationPriority {
Low,
Medium,
High,
Critical,
}
#[derive(Debug, Clone)]
pub struct TrendAnalysis {
pub quality_trend: TrendDirection,
pub performance_trend: TrendDirection,
pub complexity_trend: TrendDirection,
pub confidence: f64,
pub time_period: Duration,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TrendDirection {
Improving,
Stable,
Declining,
Unknown,
}
#[derive(Debug, Clone)]
struct AnalysisResult {
component: String,
quality_score: f64,
}
impl CodeAnalyzer {
pub fn new() -> Self {
Self {
config: AnalyzerConfig::default(),
history: AnalysisHistory {
results: Vec::new(),
max_entries: 100,
},
baselines: HashMap::new(),
}
}
pub fn with_config(config: AnalyzerConfig) -> Self {
Self {
config,
history: AnalysisHistory {
results: Vec::new(),
max_entries: 100,
},
baselines: HashMap::new(),
}
}
pub fn set_baseline(&mut self, component: &str, baseline: QualityBaseline) {
self.baselines.insert(component.to_string(), baseline);
}
pub fn analyze_quality(
&mut self,
component: &str,
context: &AnalysisContext,
) -> AnalysisReport {
let start_time = Instant::now();
let metrics = self.calculate_quality_metrics(context);
let issues = self.detect_quality_issues(context);
let performance_analysis = self.analyze_performance(context);
let quality_assessment = self.assess_overall_quality(&metrics, &issues);
let recommendations = self.generate_recommendations(&issues, &performance_analysis);
let trend_analysis = if self.config.track_trends {
Some(self.analyze_trends(component))
} else {
None
};
let analysis_duration = start_time.elapsed();
self.store_analysis_result(component, &quality_assessment, &metrics);
AnalysisReport {
component: component.to_string(),
quality_assessment,
metrics,
issues,
performance_analysis,
recommendations,
trend_analysis,
analysis_duration,
}
}
fn calculate_quality_metrics(&self, context: &AnalysisContext) -> Vec<QualityMetric> {
vec![
QualityMetric {
name: "allocation_efficiency".to_string(),
category: MetricCategory::Performance,
value: context.performance_data.allocation_efficiency,
target: 0.95,
meets_target: context.performance_data.allocation_efficiency >= 0.95,
weight: 0.3,
trend: TrendDirection::Unknown,
},
QualityMetric {
name: "error_rate".to_string(),
category: MetricCategory::Reliability,
value: context.reliability_data.error_rate,
target: 0.01, meets_target: context.reliability_data.error_rate <= 0.01,
weight: 0.25,
trend: TrendDirection::Unknown,
},
QualityMetric {
name: "memory_efficiency".to_string(),
category: MetricCategory::Efficiency,
value: context.memory_data.efficiency_ratio,
target: 0.9,
meets_target: context.memory_data.efficiency_ratio >= 0.9,
weight: 0.2,
trend: TrendDirection::Unknown,
},
]
}
fn detect_quality_issues(&self, context: &AnalysisContext) -> Vec<QualityIssue> {
let mut issues = Vec::new();
if context.memory_data.growth_rate > 1024.0 * 1024.0 {
issues.push(QualityIssue {
id: "memory_leak_detected".to_string(),
title: "Potential Memory Leak".to_string(),
description: format!(
"High memory growth rate: {:.2}MB/sec",
context.memory_data.growth_rate / (1024.0 * 1024.0)
),
severity: IssueSeverity::Major,
category: IssueCategory::MemoryManagement,
location: Some("memory_tracking".to_string()),
fix_effort: FixEffort::Medium,
impact: ImpactLevel::High,
});
}
if context.performance_data.avg_latency > Duration::from_micros(100) {
issues.push(QualityIssue {
id: "high_latency".to_string(),
title: "High Operation Latency".to_string(),
description: format!(
"Average latency {:.2}µs exceeds threshold",
context.performance_data.avg_latency.as_micros()
),
severity: IssueSeverity::Moderate,
category: IssueCategory::Performance,
location: Some("allocation_tracking".to_string()),
fix_effort: FixEffort::Easy,
impact: ImpactLevel::Medium,
});
}
issues
}
fn analyze_performance(&self, context: &AnalysisContext) -> PerformanceAnalysis {
let bottlenecks = self.identify_bottlenecks(context);
let memory_efficiency = context.memory_data.efficiency_ratio;
let cpu_efficiency = 1.0 - (context.performance_data.cpu_usage / 100.0);
let scalability = ScalabilityAssessment {
score: 0.8, scaling_behavior: ScalingBehavior::Linear,
resource_scaling: ResourceScaling {
memory_factor: 1.2,
cpu_factor: 1.1,
network_factor: 1.0,
},
limitations: vec!["Memory bandwidth may become bottleneck at scale".to_string()],
};
let score = (memory_efficiency + cpu_efficiency + scalability.score) / 3.0;
PerformanceAnalysis {
score,
bottlenecks,
memory_efficiency,
cpu_efficiency,
scalability,
}
}
fn identify_bottlenecks(&self, context: &AnalysisContext) -> Vec<PerformanceBottleneck> {
let mut bottlenecks = Vec::new();
if context.performance_data.cpu_usage > 80.0 {
bottlenecks.push(PerformanceBottleneck {
location: "allocation_tracking".to_string(),
bottleneck_type: BottleneckType::CpuBound,
severity: context.performance_data.cpu_usage / 100.0,
description: "High CPU usage in allocation tracking".to_string(),
optimization: "Consider optimizing hot paths or using faster data structures"
.to_string(),
});
}
if context.memory_data.fragmentation_ratio > 0.3 {
bottlenecks.push(PerformanceBottleneck {
location: "memory_management".to_string(),
bottleneck_type: BottleneckType::MemoryBound,
severity: context.memory_data.fragmentation_ratio,
description: "High memory fragmentation".to_string(),
optimization: "Implement memory compaction or use memory pools".to_string(),
});
}
bottlenecks
}
fn assess_overall_quality(
&self,
metrics: &[QualityMetric],
issues: &[QualityIssue],
) -> QualityAssessment {
let weighted_score: f64 = metrics
.iter()
.map(|m| {
if m.meets_target {
m.weight
} else {
m.weight * (m.value / m.target)
}
})
.sum();
let total_weight: f64 = metrics.iter().map(|m| m.weight).sum();
let overall_score = if total_weight > 0.0 {
weighted_score / total_weight
} else {
0.0
};
let critical_penalty = issues
.iter()
.filter(|i| i.severity >= IssueSeverity::Critical)
.count() as f64
* 0.1;
let adjusted_score = (overall_score - critical_penalty).max(0.0);
let grade = match adjusted_score {
s if s >= 0.9 => QualityGrade::A,
s if s >= 0.8 => QualityGrade::B,
s if s >= 0.7 => QualityGrade::C,
s if s >= 0.6 => QualityGrade::D,
_ => QualityGrade::F,
};
let strengths = metrics
.iter()
.filter(|m| m.meets_target && m.value > m.target * 1.1)
.map(|m| format!("Excellent {}", m.name))
.collect();
let weaknesses = issues
.iter()
.filter(|i| i.severity >= IssueSeverity::Major)
.map(|i| i.title.clone())
.collect();
QualityAssessment {
overall_score: adjusted_score,
grade,
confidence: 0.85, strengths,
weaknesses,
}
}
fn generate_recommendations(
&self,
issues: &[QualityIssue],
performance: &PerformanceAnalysis,
) -> Vec<Recommendation> {
let mut recommendations = Vec::new();
for issue in issues {
if issue.severity >= IssueSeverity::Major {
recommendations.push(Recommendation {
title: format!("Fix {}", issue.title),
description: format!("Address {} to improve quality", issue.description),
priority: match issue.severity {
IssueSeverity::Critical | IssueSeverity::Blocker => {
RecommendationPriority::Critical
}
IssueSeverity::Major => RecommendationPriority::High,
_ => RecommendationPriority::Medium,
},
impact: issue.impact.clone(),
effort: issue.fix_effort.clone(),
related_issues: vec![issue.id.clone()],
});
}
}
if performance.score < 0.8 {
recommendations.push(Recommendation {
title: "Improve Performance".to_string(),
description: "Overall performance score is below target".to_string(),
priority: RecommendationPriority::High,
impact: ImpactLevel::High,
effort: FixEffort::Medium,
related_issues: vec![],
});
}
recommendations
}
fn analyze_trends(&self, component: &str) -> TrendAnalysis {
let recent_results: Vec<_> = self
.history
.results
.iter()
.filter(|r| r.component == component)
.rev()
.take(10)
.collect();
if recent_results.len() < 3 {
return TrendAnalysis {
quality_trend: TrendDirection::Unknown,
performance_trend: TrendDirection::Unknown,
complexity_trend: TrendDirection::Unknown,
confidence: 0.0,
time_period: Duration::ZERO,
};
}
let scores: Vec<f64> = recent_results.iter().map(|r| r.quality_score).collect();
let quality_trend = if scores.first() > scores.last() {
TrendDirection::Improving
} else if scores.first() < scores.last() {
TrendDirection::Declining
} else {
TrendDirection::Stable
};
TrendAnalysis {
quality_trend,
performance_trend: TrendDirection::Stable,
complexity_trend: TrendDirection::Stable,
confidence: 0.7,
time_period: Duration::from_secs(3600), }
}
fn store_analysis_result(
&mut self,
component: &str,
assessment: &QualityAssessment,
_metrics: &[QualityMetric],
) {
let result = AnalysisResult {
component: component.to_string(),
quality_score: assessment.overall_score,
};
self.history.results.push(result);
if self.history.results.len() > self.history.max_entries {
self.history
.results
.drain(0..self.history.results.len() - self.history.max_entries);
}
}
}
#[derive(Debug)]
pub struct AnalysisContext {
pub performance_data: PerformanceData,
pub memory_data: MemoryData,
pub reliability_data: ReliabilityData,
}
#[derive(Debug)]
pub struct PerformanceData {
pub avg_latency: Duration,
pub cpu_usage: f64,
pub allocation_efficiency: f64,
pub throughput: f64,
}
#[derive(Debug)]
pub struct MemoryData {
pub current_usage: usize,
pub growth_rate: f64,
pub efficiency_ratio: f64,
pub fragmentation_ratio: f64,
}
#[derive(Debug)]
pub struct ReliabilityData {
pub error_rate: f64,
pub success_rate: f64,
pub mtbf: Duration,
}
impl Default for AnalyzerConfig {
fn default() -> Self {
Self {
analysis_depth: AnalysisDepth::Standard,
track_trends: true,
max_analysis_time: Duration::from_secs(30),
thresholds: QualityThresholds::default(),
}
}
}
impl Default for QualityThresholds {
fn default() -> Self {
Self {
min_quality_score: 0.8,
max_complexity: 10,
min_coverage: 0.8,
max_technical_debt: 0.2,
}
}
}
impl Default for CodeAnalyzer {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_code_analyzer_creation() {
let analyzer = CodeAnalyzer::new();
assert_eq!(analyzer.config.analysis_depth, AnalysisDepth::Standard);
assert!(analyzer.config.track_trends);
}
#[test]
fn test_quality_assessment() {
let analyzer = CodeAnalyzer::new();
let metrics = vec![QualityMetric {
name: "test_metric".to_string(),
category: MetricCategory::Performance,
value: 0.9,
target: 0.8,
meets_target: true,
weight: 1.0,
trend: TrendDirection::Stable,
}];
let issues = vec![];
let assessment = analyzer.assess_overall_quality(&metrics, &issues);
assert!(assessment.overall_score >= 0.8);
assert_eq!(assessment.grade, QualityGrade::A);
}
#[test]
fn test_quality_grades() {
assert!(QualityGrade::A > QualityGrade::B);
assert!(QualityGrade::B > QualityGrade::C);
assert!(QualityGrade::F < QualityGrade::D);
}
#[test]
fn test_code_analyzer_default() {
let analyzer = CodeAnalyzer::default();
assert_eq!(analyzer.config.analysis_depth, AnalysisDepth::Standard);
}
#[test]
fn test_code_analyzer_with_config() {
let config = AnalyzerConfig {
analysis_depth: AnalysisDepth::Deep,
track_trends: false,
max_analysis_time: Duration::from_secs(60),
thresholds: QualityThresholds::default(),
};
let analyzer = CodeAnalyzer::with_config(config.clone());
assert_eq!(analyzer.config.analysis_depth, AnalysisDepth::Deep);
assert!(!analyzer.config.track_trends);
}
#[test]
fn test_analyzer_config_default() {
let config = AnalyzerConfig::default();
assert_eq!(config.analysis_depth, AnalysisDepth::Standard);
assert!(config.track_trends);
assert_eq!(config.max_analysis_time, Duration::from_secs(30));
}
#[test]
fn test_quality_thresholds_default() {
let thresholds = QualityThresholds::default();
assert!((thresholds.min_quality_score - 0.8).abs() < f64::EPSILON);
assert_eq!(thresholds.max_complexity, 10);
assert!((thresholds.min_coverage - 0.8).abs() < f64::EPSILON);
}
#[test]
fn test_analysis_depth_variants() {
let depths = vec![
AnalysisDepth::Surface,
AnalysisDepth::Standard,
AnalysisDepth::Deep,
AnalysisDepth::Exhaustive,
];
for depth in depths {
let config = AnalyzerConfig {
analysis_depth: depth.clone(),
..Default::default()
};
assert_eq!(config.analysis_depth, depth);
}
}
#[test]
fn test_metric_category_variants() {
let categories = vec![
MetricCategory::Performance,
MetricCategory::Reliability,
MetricCategory::Maintainability,
MetricCategory::Security,
MetricCategory::Efficiency,
];
for category in categories {
let metric = QualityMetric {
name: String::new(),
category: category.clone(),
value: 0.0,
target: 0.0,
meets_target: false,
weight: 0.0,
trend: TrendDirection::Unknown,
};
assert_eq!(metric.category, category);
}
}
#[test]
fn test_issue_severity_ordering() {
assert!(IssueSeverity::Blocker > IssueSeverity::Critical);
assert!(IssueSeverity::Critical > IssueSeverity::Major);
assert!(IssueSeverity::Major > IssueSeverity::Moderate);
assert!(IssueSeverity::Moderate > IssueSeverity::Minor);
}
#[test]
fn test_issue_category_variants() {
let categories = vec![
IssueCategory::MemoryManagement,
IssueCategory::Performance,
IssueCategory::ThreadSafety,
IssueCategory::ErrorHandling,
IssueCategory::CodeStyle,
IssueCategory::Design,
];
for category in categories {
let issue = QualityIssue {
id: String::new(),
title: String::new(),
description: String::new(),
severity: IssueSeverity::Minor,
category: category.clone(),
location: None,
fix_effort: FixEffort::Trivial,
impact: ImpactLevel::Minimal,
};
assert_eq!(issue.category, category);
}
}
#[test]
fn test_fix_effort_variants() {
let efforts = vec![
FixEffort::Trivial,
FixEffort::Easy,
FixEffort::Medium,
FixEffort::Hard,
FixEffort::VeryHard,
];
for effort in efforts {
let issue = QualityIssue {
id: String::new(),
title: String::new(),
description: String::new(),
severity: IssueSeverity::Minor,
category: IssueCategory::CodeStyle,
location: None,
fix_effort: effort.clone(),
impact: ImpactLevel::Minimal,
};
assert_eq!(issue.fix_effort, effort);
}
}
#[test]
fn test_impact_level_ordering() {
assert!(ImpactLevel::Critical > ImpactLevel::High);
assert!(ImpactLevel::High > ImpactLevel::Medium);
assert!(ImpactLevel::Medium > ImpactLevel::Low);
assert!(ImpactLevel::Low > ImpactLevel::Minimal);
}
#[test]
fn test_trend_direction_variants() {
let trends = vec![
TrendDirection::Improving,
TrendDirection::Stable,
TrendDirection::Declining,
TrendDirection::Unknown,
];
for trend in trends {
let metric = QualityMetric {
name: String::new(),
category: MetricCategory::Performance,
value: 0.0,
target: 0.0,
meets_target: false,
weight: 0.0,
trend: trend.clone(),
};
assert_eq!(metric.trend, trend);
}
}
#[test]
fn test_bottleneck_type_variants() {
let types = vec![
BottleneckType::CpuBound,
BottleneckType::MemoryBound,
BottleneckType::IoBound,
BottleneckType::LockContention,
BottleneckType::CacheMiss,
BottleneckType::AlgorithmInefficiency,
];
for bottleneck_type in types {
let bottleneck = PerformanceBottleneck {
location: String::new(),
bottleneck_type: bottleneck_type.clone(),
severity: 0.0,
description: String::new(),
optimization: String::new(),
};
assert_eq!(bottleneck.bottleneck_type, bottleneck_type);
}
}
#[test]
fn test_scaling_behavior_variants() {
let behaviors = vec![
ScalingBehavior::Constant,
ScalingBehavior::Linear,
ScalingBehavior::Logarithmic,
ScalingBehavior::Quadratic,
ScalingBehavior::Exponential,
];
for behavior in behaviors {
let assessment = ScalabilityAssessment {
score: 0.0,
scaling_behavior: behavior.clone(),
resource_scaling: ResourceScaling {
memory_factor: 0.0,
cpu_factor: 0.0,
network_factor: 0.0,
},
limitations: vec![],
};
assert_eq!(assessment.scaling_behavior, behavior);
}
}
#[test]
fn test_recommendation_priority_ordering() {
assert!(RecommendationPriority::Critical > RecommendationPriority::High);
assert!(RecommendationPriority::High > RecommendationPriority::Medium);
assert!(RecommendationPriority::Medium > RecommendationPriority::Low);
}
#[test]
fn test_set_baseline() {
let mut analyzer = CodeAnalyzer::new();
let baseline = QualityBaseline {
component: "test_component".to_string(),
quality_score: 0.9,
complexity: 5,
performance: BaselinePerformance {
avg_execution_time: Duration::from_millis(100),
memory_per_operation: 1024,
error_rate: 0.01,
},
timestamp: Instant::now(),
};
analyzer.set_baseline("test_component", baseline);
}
#[test]
fn test_analyze_quality_basic() {
let mut analyzer = CodeAnalyzer::new();
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(50),
cpu_usage: 50.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 100.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.1,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert_eq!(report.component, "test_component");
assert!(!report.metrics.is_empty());
assert!(report.trend_analysis.is_some());
}
#[test]
fn test_analyze_quality_no_trends() {
let config = AnalyzerConfig {
track_trends: false,
..Default::default()
};
let mut analyzer = CodeAnalyzer::with_config(config);
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(50),
cpu_usage: 50.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 100.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.1,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert!(report.trend_analysis.is_none());
}
#[test]
fn test_analyze_quality_memory_leak_detection() {
let mut analyzer = CodeAnalyzer::new();
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(50),
cpu_usage: 50.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 2.0 * 1024.0 * 1024.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.1,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert!(!report.issues.is_empty());
assert!(report.issues.iter().any(|i| i.id == "memory_leak_detected"));
}
#[test]
fn test_analyze_quality_high_latency_detection() {
let mut analyzer = CodeAnalyzer::new();
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(200),
cpu_usage: 50.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 100.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.1,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert!(!report.issues.is_empty());
assert!(report.issues.iter().any(|i| i.id == "high_latency"));
}
#[test]
fn test_analyze_quality_cpu_bottleneck() {
let mut analyzer = CodeAnalyzer::new();
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(50),
cpu_usage: 90.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 100.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.1,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert!(!report.performance_analysis.bottlenecks.is_empty());
assert!(report
.performance_analysis
.bottlenecks
.iter()
.any(|b| matches!(b.bottleneck_type, BottleneckType::CpuBound)));
}
#[test]
fn test_analyze_quality_memory_bottleneck() {
let mut analyzer = CodeAnalyzer::new();
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(50),
cpu_usage: 50.0,
allocation_efficiency: 0.95,
throughput: 1000.0,
},
memory_data: MemoryData {
current_usage: 1024 * 1024,
growth_rate: 100.0,
efficiency_ratio: 0.9,
fragmentation_ratio: 0.5,
},
reliability_data: ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(3600),
},
};
let report = analyzer.analyze_quality("test_component", &context);
assert!(!report.performance_analysis.bottlenecks.is_empty());
assert!(report
.performance_analysis
.bottlenecks
.iter()
.any(|b| matches!(b.bottleneck_type, BottleneckType::MemoryBound)));
}
#[test]
fn test_quality_metric_creation() {
let metric = QualityMetric {
name: "test_metric".to_string(),
category: MetricCategory::Performance,
value: 0.85,
target: 0.9,
meets_target: false,
weight: 0.25,
trend: TrendDirection::Improving,
};
assert_eq!(metric.name, "test_metric");
assert!(!metric.meets_target);
}
#[test]
fn test_quality_issue_creation() {
let issue = QualityIssue {
id: "ISSUE-001".to_string(),
title: "Test Issue".to_string(),
description: "Test description".to_string(),
severity: IssueSeverity::Major,
category: IssueCategory::MemoryManagement,
location: Some("src/main.rs:42".to_string()),
fix_effort: FixEffort::Medium,
impact: ImpactLevel::High,
};
assert_eq!(issue.id, "ISSUE-001");
assert!(issue.location.is_some());
}
#[test]
fn test_performance_bottleneck_creation() {
let bottleneck = PerformanceBottleneck {
location: "hot_function".to_string(),
bottleneck_type: BottleneckType::CpuBound,
severity: 0.8,
description: "High CPU usage".to_string(),
optimization: "Use caching".to_string(),
};
assert_eq!(bottleneck.location, "hot_function");
assert!((bottleneck.severity - 0.8).abs() < f64::EPSILON);
}
#[test]
fn test_recommendation_creation() {
let recommendation = Recommendation {
title: "Fix memory leak".to_string(),
description: "Address memory leak in module X".to_string(),
priority: RecommendationPriority::Critical,
impact: ImpactLevel::Critical,
effort: FixEffort::Hard,
related_issues: vec!["ISSUE-001".to_string()],
};
assert_eq!(recommendation.priority, RecommendationPriority::Critical);
assert_eq!(recommendation.related_issues.len(), 1);
}
#[test]
fn test_quality_baseline_creation() {
let baseline = QualityBaseline {
component: "module_a".to_string(),
quality_score: 0.85,
complexity: 7,
performance: BaselinePerformance {
avg_execution_time: Duration::from_millis(50),
memory_per_operation: 2048,
error_rate: 0.02,
},
timestamp: Instant::now(),
};
assert_eq!(baseline.component, "module_a");
assert!((baseline.quality_score - 0.85).abs() < f64::EPSILON);
}
#[test]
fn test_baseline_performance_creation() {
let perf = BaselinePerformance {
avg_execution_time: Duration::from_millis(100),
memory_per_operation: 4096,
error_rate: 0.01,
};
assert_eq!(perf.memory_per_operation, 4096);
assert!((perf.error_rate - 0.01).abs() < f64::EPSILON);
}
#[test]
fn test_scalability_assessment_creation() {
let assessment = ScalabilityAssessment {
score: 0.75,
scaling_behavior: ScalingBehavior::Linear,
resource_scaling: ResourceScaling {
memory_factor: 1.5,
cpu_factor: 1.2,
network_factor: 1.0,
},
limitations: vec!["Memory bandwidth".to_string()],
};
assert!((assessment.score - 0.75).abs() < f64::EPSILON);
assert_eq!(assessment.limitations.len(), 1);
}
#[test]
fn test_resource_scaling_creation() {
let scaling = ResourceScaling {
memory_factor: 2.0,
cpu_factor: 1.5,
network_factor: 1.0,
};
assert!((scaling.memory_factor - 2.0).abs() < f64::EPSILON);
}
#[test]
fn test_trend_analysis_creation() {
let trend = TrendAnalysis {
quality_trend: TrendDirection::Improving,
performance_trend: TrendDirection::Stable,
complexity_trend: TrendDirection::Declining,
confidence: 0.85,
time_period: Duration::from_secs(3600),
};
assert_eq!(trend.quality_trend, TrendDirection::Improving);
assert!((trend.confidence - 0.85).abs() < f64::EPSILON);
}
#[test]
fn test_analysis_context_creation() {
let context = AnalysisContext {
performance_data: PerformanceData {
avg_latency: Duration::from_micros(100),
cpu_usage: 60.0,
allocation_efficiency: 0.9,
throughput: 500.0,
},
memory_data: MemoryData {
current_usage: 2048,
growth_rate: 50.0,
efficiency_ratio: 0.85,
fragmentation_ratio: 0.15,
},
reliability_data: ReliabilityData {
error_rate: 0.01,
success_rate: 0.99,
mtbf: Duration::from_secs(7200),
},
};
assert!((context.performance_data.cpu_usage - 60.0).abs() < f64::EPSILON);
assert_eq!(context.memory_data.current_usage, 2048);
}
#[test]
fn test_performance_data_creation() {
let data = PerformanceData {
avg_latency: Duration::from_micros(75),
cpu_usage: 45.0,
allocation_efficiency: 0.92,
throughput: 750.0,
};
assert_eq!(data.avg_latency, Duration::from_micros(75));
}
#[test]
fn test_memory_data_creation() {
let data = MemoryData {
current_usage: 4096,
growth_rate: 100.0,
efficiency_ratio: 0.88,
fragmentation_ratio: 0.12,
};
assert_eq!(data.current_usage, 4096);
}
#[test]
fn test_reliability_data_creation() {
let data = ReliabilityData {
error_rate: 0.005,
success_rate: 0.995,
mtbf: Duration::from_secs(86400),
};
assert!((data.error_rate - 0.005).abs() < f64::EPSILON);
}
#[test]
fn test_quality_grade_equality() {
assert_eq!(QualityGrade::A, QualityGrade::A);
assert_ne!(QualityGrade::A, QualityGrade::B);
}
#[test]
fn test_quality_grade_ord() {
let grades = vec![
QualityGrade::F,
QualityGrade::D,
QualityGrade::C,
QualityGrade::B,
QualityGrade::A,
];
let mut sorted = grades.clone();
sorted.sort();
assert_eq!(
sorted,
vec![
QualityGrade::F,
QualityGrade::D,
QualityGrade::C,
QualityGrade::B,
QualityGrade::A
]
);
}
#[test]
fn test_analysis_report_creation() {
let report = AnalysisReport {
component: "test".to_string(),
quality_assessment: QualityAssessment {
overall_score: 0.85,
grade: QualityGrade::B,
confidence: 0.9,
strengths: vec!["Good performance".to_string()],
weaknesses: vec![],
},
metrics: vec![],
issues: vec![],
performance_analysis: PerformanceAnalysis {
score: 0.8,
bottlenecks: vec![],
memory_efficiency: 0.85,
cpu_efficiency: 0.75,
scalability: ScalabilityAssessment {
score: 0.7,
scaling_behavior: ScalingBehavior::Linear,
resource_scaling: ResourceScaling {
memory_factor: 1.0,
cpu_factor: 1.0,
network_factor: 1.0,
},
limitations: vec![],
},
},
recommendations: vec![],
trend_analysis: None,
analysis_duration: Duration::from_millis(100),
};
assert_eq!(report.component, "test");
}
#[test]
fn test_quality_assessment_creation() {
let assessment = QualityAssessment {
overall_score: 0.92,
grade: QualityGrade::A,
confidence: 0.95,
strengths: vec!["Fast execution".to_string(), "Low memory".to_string()],
weaknesses: vec!["Complex code".to_string()],
};
assert_eq!(assessment.strengths.len(), 2);
assert_eq!(assessment.weaknesses.len(), 1);
}
#[test]
fn test_performance_analysis_creation() {
let analysis = PerformanceAnalysis {
score: 0.88,
bottlenecks: vec![],
memory_efficiency: 0.9,
cpu_efficiency: 0.85,
scalability: ScalabilityAssessment {
score: 0.8,
scaling_behavior: ScalingBehavior::Logarithmic,
resource_scaling: ResourceScaling {
memory_factor: 1.2,
cpu_factor: 1.1,
network_factor: 1.0,
},
limitations: vec![],
},
};
assert!((analysis.score - 0.88).abs() < f64::EPSILON);
}
}