#![cfg_attr(coverage_nightly, coverage(off))]
use crate::models::complexity_bound::{BigOClass, ComplexityBound, ComplexityFlags, InputVariable};
use crate::services::big_o_analyzer::{
BigOAnalysisConfig, BigOAnalysisReport, BigOAnalyzer, ComplexityDistribution,
FunctionComplexity, PatternMatch,
};
use std::path::PathBuf;
#[test]
fn test_big_o_class_notation() {
assert_eq!(BigOClass::Constant.notation(), "O(1)");
assert_eq!(BigOClass::Logarithmic.notation(), "O(log n)");
assert_eq!(BigOClass::Linear.notation(), "O(n)");
assert_eq!(BigOClass::Linearithmic.notation(), "O(n log n)");
assert_eq!(BigOClass::Quadratic.notation(), "O(n²)");
assert_eq!(BigOClass::Cubic.notation(), "O(n³)");
assert_eq!(BigOClass::Exponential.notation(), "O(2^n)");
assert_eq!(BigOClass::Factorial.notation(), "O(n!)");
assert_eq!(BigOClass::Unknown.notation(), "O(?)");
}
#[test]
fn test_big_o_class_is_better_than() {
assert!(BigOClass::Constant.is_better_than(&BigOClass::Linear));
assert!(BigOClass::Linear.is_better_than(&BigOClass::Quadratic));
assert!(BigOClass::Quadratic.is_better_than(&BigOClass::Exponential));
assert!(!BigOClass::Exponential.is_better_than(&BigOClass::Linear));
assert!(!BigOClass::Constant.is_better_than(&BigOClass::Constant));
}
#[test]
fn test_big_o_class_growth_factor() {
assert!((BigOClass::Constant.growth_factor(100.0) - 1.0).abs() < f64::EPSILON);
assert!((BigOClass::Linear.growth_factor(100.0) - 100.0).abs() < f64::EPSILON);
assert!((BigOClass::Quadratic.growth_factor(10.0) - 100.0).abs() < f64::EPSILON);
assert!(BigOClass::Logarithmic.growth_factor(8.0) > 0.0);
assert!(BigOClass::Cubic.growth_factor(5.0) > 0.0);
assert!(BigOClass::Exponential.growth_factor(3.0) > 0.0);
}
#[test]
fn test_big_o_class_growth_factor_factorial() {
let f5 = BigOClass::Factorial.growth_factor(5.0);
assert!((f5 - 120.0).abs() < f64::EPSILON);
}
#[test]
fn test_big_o_class_serde() {
let classes = vec![
BigOClass::Constant,
BigOClass::Logarithmic,
BigOClass::Linear,
BigOClass::Linearithmic,
BigOClass::Quadratic,
BigOClass::Cubic,
BigOClass::Exponential,
BigOClass::Factorial,
BigOClass::Unknown,
];
for c in &classes {
let json = serde_json::to_string(c).unwrap();
let back: BigOClass = serde_json::from_str(&json).unwrap();
assert_eq!(*c, back);
}
}
#[test]
fn test_big_o_class_copy() {
let c = BigOClass::Linear;
let copied = c;
assert_eq!(c, copied);
}
#[test]
fn test_complexity_bound_new() {
let bound = ComplexityBound::new(BigOClass::Quadratic, 1, InputVariable::N);
assert_eq!(bound.class, BigOClass::Quadratic);
assert_eq!(bound.confidence, 50); assert_eq!(bound.coefficient, 1);
assert_eq!(bound.input_var, InputVariable::N);
}
#[test]
fn test_complexity_bound_constant() {
let bound = ComplexityBound::constant();
assert_eq!(bound.class, BigOClass::Constant);
assert_eq!(bound.confidence, 100);
}
#[test]
fn test_complexity_bound_serde() {
let bound = ComplexityBound::new(BigOClass::Linear, 2, InputVariable::N);
let json = serde_json::to_string(&bound).unwrap();
let back: ComplexityBound = serde_json::from_str(&json).unwrap();
assert_eq!(back.class, BigOClass::Linear);
assert_eq!(back.coefficient, 2);
}
#[test]
fn test_complexity_bound_copy() {
let bound = ComplexityBound::new(BigOClass::Linear, 1, InputVariable::N);
let copied = bound;
assert_eq!(copied.class, BigOClass::Linear);
}
#[test]
fn test_input_variable_display() {
assert_eq!(format!("{}", InputVariable::N), "n");
assert_eq!(format!("{}", InputVariable::M), "m");
assert_eq!(format!("{}", InputVariable::K), "k");
assert_eq!(format!("{}", InputVariable::D), "d");
assert_eq!(format!("{}", InputVariable::Custom), "x");
}
#[test]
fn test_input_variable_serde() {
let vars = vec![
InputVariable::N,
InputVariable::M,
InputVariable::K,
InputVariable::D,
InputVariable::Custom,
];
for v in &vars {
let json = serde_json::to_string(v).unwrap();
let back: InputVariable = serde_json::from_str(&json).unwrap();
assert_eq!(*v, back);
}
}
#[test]
fn test_complexity_flags_new() {
let flags = ComplexityFlags::new();
assert!(!flags.has(ComplexityFlags::WORST_CASE));
assert!(!flags.has(ComplexityFlags::PROVEN));
}
#[test]
fn test_complexity_flags_with() {
let flags = ComplexityFlags::new()
.with(ComplexityFlags::WORST_CASE)
.with(ComplexityFlags::PROVEN);
assert!(flags.has(ComplexityFlags::WORST_CASE));
assert!(flags.has(ComplexityFlags::PROVEN));
assert!(!flags.has(ComplexityFlags::AMORTIZED));
}
#[test]
fn test_complexity_flags_is_worst_case() {
let wc = ComplexityFlags::new().with(ComplexityFlags::WORST_CASE);
assert!(wc.is_worst_case());
let avg = ComplexityFlags::new().with(ComplexityFlags::AVERAGE_CASE);
assert!(!avg.is_worst_case());
}
#[test]
fn test_complexity_flags_is_proven() {
let proven = ComplexityFlags::new().with(ComplexityFlags::PROVEN);
assert!(proven.is_proven());
let empirical = ComplexityFlags::new().with(ComplexityFlags::EMPIRICAL);
assert!(!empirical.is_proven());
}
#[test]
fn test_complexity_flags_all_flags() {
let all = ComplexityFlags::new()
.with(ComplexityFlags::AMORTIZED)
.with(ComplexityFlags::WORST_CASE)
.with(ComplexityFlags::AVERAGE_CASE)
.with(ComplexityFlags::BEST_CASE)
.with(ComplexityFlags::TIGHT_BOUND)
.with(ComplexityFlags::EMPIRICAL)
.with(ComplexityFlags::PROVEN)
.with(ComplexityFlags::RECURSIVE);
assert!(all.has(ComplexityFlags::AMORTIZED));
assert!(all.has(ComplexityFlags::RECURSIVE));
}
#[test]
fn test_big_o_analyzer_new() {
let _analyzer = BigOAnalyzer::new();
}
#[test]
fn test_big_o_analysis_config_clone() {
let config = BigOAnalysisConfig {
project_path: PathBuf::from("./src"),
include_patterns: vec!["*.rs".to_string()],
exclude_patterns: vec!["test_*.rs".to_string()],
confidence_threshold: 70,
analyze_space_complexity: true,
};
let cloned = config.clone();
assert_eq!(cloned.project_path, PathBuf::from("./src"));
assert_eq!(cloned.confidence_threshold, 70);
assert!(cloned.analyze_space_complexity);
}
#[test]
fn test_complexity_distribution_serde() {
let dist = ComplexityDistribution {
constant: 50,
logarithmic: 10,
linear: 30,
linearithmic: 5,
quadratic: 3,
cubic: 1,
exponential: 0,
unknown: 1,
};
let json = serde_json::to_string(&dist).unwrap();
let back: ComplexityDistribution = serde_json::from_str(&json).unwrap();
assert_eq!(back.constant, 50);
assert_eq!(back.linear, 30);
assert_eq!(back.unknown, 1);
}
#[test]
fn test_function_complexity_serde() {
let fc = FunctionComplexity {
file_path: PathBuf::from("src/main.rs"),
function_name: "process_data".to_string(),
line_number: 42,
time_complexity: ComplexityBound::new(BigOClass::Quadratic, 1, InputVariable::N)
.with_confidence(80),
space_complexity: ComplexityBound::new(BigOClass::Linear, 1, InputVariable::N)
.with_confidence(90),
confidence: 85,
notes: vec!["Consider using HashMap".to_string()],
};
let json = serde_json::to_string(&fc).unwrap();
let back: FunctionComplexity = serde_json::from_str(&json).unwrap();
assert_eq!(back.function_name, "process_data");
assert_eq!(back.line_number, 42);
assert_eq!(back.time_complexity.class, BigOClass::Quadratic);
}
#[test]
fn test_pattern_match_serde() {
let pm = PatternMatch {
pattern_name: "nested_loops".to_string(),
occurrences: 3,
typical_complexity: BigOClass::Quadratic,
};
let json = serde_json::to_string(&pm).unwrap();
let back: PatternMatch = serde_json::from_str(&json).unwrap();
assert_eq!(back.pattern_name, "nested_loops");
assert_eq!(back.occurrences, 3);
}
#[test]
fn test_big_o_analysis_report_serde() {
let report = BigOAnalysisReport {
analyzed_functions: 100,
complexity_distribution: ComplexityDistribution {
constant: 50,
logarithmic: 10,
linear: 30,
linearithmic: 5,
quadratic: 3,
cubic: 1,
exponential: 0,
unknown: 1,
},
high_complexity_functions: vec![],
pattern_matches: vec![],
recommendations: vec!["Optimize quadratic functions".to_string()],
};
let json = serde_json::to_string(&report).unwrap();
let back: BigOAnalysisReport = serde_json::from_str(&json).unwrap();
assert_eq!(back.analyzed_functions, 100);
assert_eq!(back.recommendations.len(), 1);
}
#[test]
fn test_big_o_class_display() {
assert_eq!(format!("{}", BigOClass::Constant), "O(1)");
assert_eq!(format!("{}", BigOClass::Logarithmic), "O(log n)");
assert_eq!(format!("{}", BigOClass::Linear), "O(n)");
assert_eq!(format!("{}", BigOClass::Linearithmic), "O(n log n)");
assert_eq!(format!("{}", BigOClass::Quadratic), "O(n²)");
assert_eq!(format!("{}", BigOClass::Cubic), "O(n³)");
assert_eq!(format!("{}", BigOClass::Exponential), "O(2^n)");
assert_eq!(format!("{}", BigOClass::Factorial), "O(n!)");
assert_eq!(format!("{}", BigOClass::Unknown), "O(?)");
}
#[test]
fn test_complexity_bound_display() {
let bound = ComplexityBound::new(BigOClass::Quadratic, 1, InputVariable::N).with_confidence(85);
let display = format!("{}", bound);
assert!(display.contains("O(n²)"));
assert!(display.contains("85% confidence"));
}
#[test]
fn test_complexity_bound_display_constant() {
let bound = ComplexityBound::constant();
let display = format!("{}", bound);
assert!(display.contains("O(1)"));
assert!(display.contains("100% confidence"));
}
#[test]
fn test_complexity_bound_display_various() {
let cases = vec![
(BigOClass::Linear, 75, "O(n)", "75%"),
(BigOClass::Logarithmic, 90, "O(log n)", "90%"),
(BigOClass::Exponential, 50, "O(2^n)", "50%"),
];
for (class, conf, expected_class, expected_conf) in cases {
let bound = ComplexityBound::new(class, 1, InputVariable::N).with_confidence(conf);
let display = format!("{}", bound);
assert!(
display.contains(expected_class),
"Expected {} in {}",
expected_class,
display
);
assert!(
display.contains(expected_conf),
"Expected {} in {}",
expected_conf,
display
);
}
}