#![cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::super::helpers::{
count_parameters, count_unique_variables, estimate_nesting_depth, is_rust_keyword,
};
use super::super::types::{MutantFeatures, PredictionResult, TrainingData};
use crate::services::mutation::{Mutant, MutantStatus, MutationOperatorType, SourceLocation};
use std::collections::HashMap;
#[test]
fn test_estimate_nesting_depth_empty() {
assert_eq!(estimate_nesting_depth(""), 0);
}
#[test]
fn test_estimate_nesting_depth_no_braces() {
assert_eq!(estimate_nesting_depth("let x = 1;"), 0);
}
#[test]
fn test_estimate_nesting_depth_single() {
assert_eq!(estimate_nesting_depth("fn foo() { x }"), 1);
}
#[test]
fn test_estimate_nesting_depth_nested() {
assert_eq!(estimate_nesting_depth("fn foo() { if true { x } }"), 2);
}
#[test]
fn test_estimate_nesting_depth_deeply_nested() {
assert_eq!(estimate_nesting_depth("{ { { { x } } } }"), 4);
}
#[test]
fn test_estimate_nesting_depth_unbalanced() {
assert_eq!(estimate_nesting_depth("{{ }"), 2);
}
#[test]
fn test_count_parameters_empty() {
assert_eq!(count_parameters("fn foo()"), 0);
}
#[test]
fn test_count_parameters_none() {
assert_eq!(count_parameters("let x = 5;"), 0);
}
#[test]
fn test_count_parameters_single() {
assert_eq!(count_parameters("fn foo(x: i32)"), 1);
}
#[test]
fn test_count_parameters_multiple() {
assert_eq!(count_parameters("fn foo(x: i32, y: i32, z: i32)"), 3);
}
#[test]
fn test_count_parameters_with_generics() {
assert_eq!(count_parameters("fn foo<T>(x: T, y: T)"), 2);
}
#[test]
fn test_count_unique_variables_empty() {
assert_eq!(count_unique_variables(""), 0);
}
#[test]
fn test_count_unique_variables_simple() {
let source = "let x = y + z;";
let count = count_unique_variables(source);
assert!(count >= 1); }
#[test]
fn test_count_unique_variables_with_keywords() {
let source = "fn let mut x = 5;";
let count = count_unique_variables(source);
assert!(count >= 1);
}
#[test]
fn test_count_unique_variables_uppercase() {
let source = "let Type = MyStruct;";
let count = count_unique_variables(source);
assert!(count >= 0);
}
#[test]
fn test_is_rust_keyword_true() {
assert!(is_rust_keyword("fn"));
assert!(is_rust_keyword("let"));
assert!(is_rust_keyword("mut"));
assert!(is_rust_keyword("if"));
assert!(is_rust_keyword("else"));
assert!(is_rust_keyword("for"));
assert!(is_rust_keyword("while"));
assert!(is_rust_keyword("loop"));
assert!(is_rust_keyword("match"));
assert!(is_rust_keyword("return"));
}
#[test]
fn test_is_rust_keyword_false() {
assert!(!is_rust_keyword("variable"));
assert!(!is_rust_keyword("foo"));
assert!(!is_rust_keyword("bar"));
assert!(!is_rust_keyword("x"));
assert!(!is_rust_keyword("MyType"));
}
pub(super) fn create_test_mutant(source: &str, operator: MutationOperatorType) -> Mutant {
Mutant {
id: "test".to_string(),
original_file: std::path::PathBuf::from("test.rs"),
mutated_source: source.to_string(),
location: SourceLocation {
line: 1,
column: 1,
end_line: 1,
end_column: 10,
},
operator,
hash: "hash".to_string(),
status: MutantStatus::Pending,
}
}
#[test]
fn test_mutant_features_from_simple() {
let mutant = create_test_mutant("let x = 1;", MutationOperatorType::ArithmeticReplacement);
let features = MutantFeatures::from_mutant(&mutant);
assert!(!features.has_loops);
assert!(!features.has_conditionals);
assert_eq!(features.nesting_depth, 0);
}
#[test]
fn test_mutant_features_with_loops() {
let mutant = create_test_mutant(
"for i in 0..10 { x += 1; }",
MutationOperatorType::ArithmeticReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_loops);
assert!(features.control_flow_count >= 1);
}
#[test]
fn test_mutant_features_with_conditionals() {
let mutant = create_test_mutant(
"if x > 0 { y } else { z }",
MutationOperatorType::RelationalReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_conditionals);
}
#[test]
fn test_mutant_features_with_error_handling() {
let mutant = create_test_mutant(
"fn foo() -> Result<(), Error> { Ok(()) }",
MutationOperatorType::ReturnReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_error_handling);
}
#[test]
fn test_mutant_features_with_assertions() {
let mutant = create_test_mutant(
"assert_eq!(x, y);",
MutationOperatorType::ArithmeticReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_assertions);
}
#[test]
fn test_mutant_features_with_arithmetic() {
let mutant = create_test_mutant(
"let z = x + y;",
MutationOperatorType::ArithmeticReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_arithmetic);
}
#[test]
fn test_mutant_features_with_comparisons() {
let mutant =
create_test_mutant("if x == y { }", MutationOperatorType::RelationalReplacement);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_comparisons);
}
#[test]
fn test_mutant_features_with_logical_ops() {
let mutant = create_test_mutant(
"if a && b || !c { }",
MutationOperatorType::ConditionalReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
assert!(features.has_logical_ops);
}
#[test]
fn test_mutant_features_to_feature_vector_length() {
let mutant = create_test_mutant("let x = 1;", MutationOperatorType::ArithmeticReplacement);
let features = MutantFeatures::from_mutant(&mutant);
let vector = features.to_feature_vector();
assert_eq!(vector.len(), 18); }
#[test]
fn test_mutant_features_operator_type_numeric() {
let mutant1 = create_test_mutant("x", MutationOperatorType::ArithmeticReplacement);
let features1 = MutantFeatures::from_mutant(&mutant1);
let mutant2 = create_test_mutant("x", MutationOperatorType::RelationalReplacement);
let features2 = MutantFeatures::from_mutant(&mutant2);
let vec1 = features1.to_feature_vector();
let vec2 = features2.to_feature_vector();
assert_eq!(vec1[0], 1.0); assert_eq!(vec2[0], 2.0); }
#[test]
fn test_mutant_features_operator_none() {
let mutant = create_test_mutant("x", MutationOperatorType::None);
let features = MutantFeatures::from_mutant(&mutant);
let vector = features.to_feature_vector();
assert_eq!(vector[0], 0.0); }
#[test]
fn test_mutant_features_operator_custom() {
let mutant = create_test_mutant("x", MutationOperatorType::Custom("test".to_string()));
let features = MutantFeatures::from_mutant(&mutant);
let vector = features.to_feature_vector();
assert_eq!(vector[0], 21.0); }
#[test]
fn test_training_data_creation() {
let mutant = create_test_mutant("x + y", MutationOperatorType::ArithmeticReplacement);
let data = TrainingData {
mutant: mutant.clone(),
was_killed: true,
test_failures: vec!["test_add".to_string()],
execution_time_ms: 100,
};
assert!(data.was_killed);
assert_eq!(data.test_failures.len(), 1);
assert_eq!(data.execution_time_ms, 100);
}
#[test]
fn test_training_data_serialization() {
let mutant = create_test_mutant("x + y", MutationOperatorType::ArithmeticReplacement);
let data = TrainingData {
mutant,
was_killed: false,
test_failures: vec![],
execution_time_ms: 50,
};
let json = serde_json::to_string(&data).unwrap();
let deserialized: TrainingData = serde_json::from_str(&json).unwrap();
assert_eq!(data.was_killed, deserialized.was_killed);
assert_eq!(data.execution_time_ms, deserialized.execution_time_ms);
}
#[test]
fn test_prediction_result_creation() {
let mut contributions = HashMap::new();
contributions.insert("operator_type".to_string(), 0.5);
let result = PredictionResult {
kill_probability: 0.75,
confidence: 0.9,
feature_contributions: contributions,
};
assert!((result.kill_probability - 0.75).abs() < f64::EPSILON);
assert!((result.confidence - 0.9).abs() < f64::EPSILON);
assert_eq!(result.feature_contributions.len(), 1);
}
#[test]
fn test_prediction_result_serialization() {
let result = PredictionResult {
kill_probability: 0.5,
confidence: 0.8,
feature_contributions: HashMap::new(),
};
let json = serde_json::to_string(&result).unwrap();
let deserialized: PredictionResult = serde_json::from_str(&json).unwrap();
assert!((result.kill_probability - deserialized.kill_probability).abs() < f64::EPSILON);
}
#[test]
fn test_mutant_features_serialization() {
let mutant = create_test_mutant(
"fn foo() { for i in 0..10 { if x > 0 { y } } }",
MutationOperatorType::ArithmeticReplacement,
);
let features = MutantFeatures::from_mutant(&mutant);
let json = serde_json::to_string(&features).unwrap();
let deserialized: MutantFeatures = serde_json::from_str(&json).unwrap();
assert_eq!(features.has_loops, deserialized.has_loops);
assert_eq!(features.has_conditionals, deserialized.has_conditionals);
assert_eq!(features.nesting_depth, deserialized.nesting_depth);
}
#[test]
fn test_feature_vector_boolean_encoding() {
let mutant_with_loops = create_test_mutant(
"for i in 0..10 { }",
MutationOperatorType::ArithmeticReplacement,
);
let mutant_without_loops =
create_test_mutant("let x = 1;", MutationOperatorType::ArithmeticReplacement);
let features_with = MutantFeatures::from_mutant(&mutant_with_loops);
let features_without = MutantFeatures::from_mutant(&mutant_without_loops);
let vec_with = features_with.to_feature_vector();
let vec_without = features_without.to_feature_vector();
assert_eq!(vec_with[6], 1.0); assert_eq!(vec_without[6], 0.0); }
}