use super::*;
#[test]
fn test_trueno_variance_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let vals = [2.0, 4.0, 4.0, 4.0, 5.0]; trueno_variance(vals)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("variance"),
"trueno_variance should transpile to trueno_bridge::variance, got: {rust_str}"
);
}
#[test]
fn test_trueno_std_dev_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let samples = [1.0, 2.0, 3.0]; trueno_std_dev(samples)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("std_dev"),
"trueno_std_dev should transpile to trueno_bridge::std_dev, got: {rust_str}"
);
}
#[test]
fn test_trueno_dot_transpiles_correctly() {
let mut transpiler = create_transpiler();
let code = "let a = [1.0, 2.0, 3.0]; let b = [4.0, 5.0, 6.0]; trueno_dot(a, b)";
let mut parser = Parser::new(code);
let ast = parser.parse().expect("Failed to parse");
let result = transpiler
.transpile(&ast)
.expect("transpile should succeed in test");
let rust_str = result.to_string();
assert!(
rust_str.contains("trueno_bridge") && rust_str.contains("dot"),
"trueno_dot should transpile to trueno_bridge::dot, got: {rust_str}"
);
}
#[test]
fn test_transpile_if_comprehensive() {
let mut transpiler = Transpiler::new();
let code = "if x > 0 { println(\"positive\") }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
let output = result.expect("result should be Ok in test").to_string();
assert!(output.contains("if"));
}
let code = "if x > 0 { 1 } else { -1 }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
}
let code = "if x > 0 { 1 } else if x < 0 { -1 } else { 0 }";
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok());
}
}
#[test]
fn test_transpile_let_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"let x = 5",
"let mut y = 10",
"const PI = 3.15",
"let (a, b) = (1, 2)",
"let [x, y, z] = [1, 2, 3]",
"let Some(value) = opt",
"let Ok(result) = try_something()",
"let {name, age} = person",
"let x: int = 42",
"let f: fn(int) -> int = |x| x * 2",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_function_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"fn simple() { }",
"fn main() { println(\"Hello\") }",
"fn add(a: int, b: int) -> int { a + b }",
"fn generic<T>(x: T) -> T { x }",
"async fn fetch() { await get() }",
"fn* generator() { yield 1; yield 2 }",
"pub fn public() { }",
"#[test] fn test_function() { // Test passes without panic }",
"fn with_default(x = 10) { x }",
"fn recursive(n) { if n <= 0 { 0 } else { n + recursive(n-1) } }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_call_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"print(\"hello\")",
"println(\"world\")",
"eprint(\"error\")",
"eprintln(\"error line\")",
"dbg!(value)",
"sqrt(16)",
"pow(2, 8)",
"abs(-5)",
"min(3, 7)",
"max(3, 7)",
"floor(3.7)",
"ceil(3.2)",
"round(3.5)",
"sin(0)",
"cos(0)",
"tan(0)",
"log(1)",
"exp(0)",
"int(3.15)",
"float(42)",
"str(123)",
"bool(1)",
"char(65)",
"vec![1, 2, 3]",
"Vec::new()",
"HashMap::new()",
"HashSet::from([1, 2, 3])",
"input()",
"input(\"Enter: \")",
"// Test passes without panic",
"assert_eq!(1, 1)",
"assert_ne!(1, 2)",
"debug_assert!(x > 0)",
"df.select(\"col1\", \"col2\")",
"DataFrame::new()",
"custom_function(1, 2, 3)",
"object.method()",
"chain().of().calls()",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_transpile_lambda_comprehensive() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"x => x",
"x => x * 2",
"(x, y) => x + y",
"() => 42",
"(a, b, c) => a + b + c",
"x => { let y = x * 2; y + 1 }",
"async x => await fetch(x)",
"(...args) => args.length",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_is_variable_mutated_property() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
("let mut x = 0; x = 5", true),
("let mut x = 0; x += 1", true),
("let mut arr = []; arr.push(1)", true),
("let x = 5; let y = x + 1", false),
("let x = 5; println(x)", false),
];
for (code, _expected) in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_control_flow_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"while x < 10 { x += 1 }",
"for i in 0..10 { println(i) }",
"for x in array { process(x) }",
"loop { if done { break } }",
"match x { 1 => \"one\", 2 => \"two\", _ => \"other\" }",
"match opt { Some(x) => x * 2, None => 0 }",
"return",
"return 42",
"break",
"break 'label",
"continue",
"continue 'label",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_try_catch_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"try { risky() } catch(e) { handle(e) }",
"try { risky() } finally { cleanup() }",
"try { risky() } catch(e) { handle(e) } finally { cleanup() }",
"throw Error(\"message\")",
"throw CustomError { code: 500 }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_class_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"class Empty { }",
"class Point { x: int; y: int }",
"class Circle { radius: float; fn area() { 3.15 * radius * radius } }",
"class Derived extends Base { }",
"class Generic<T> { value: T }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_import_export_statements() {
let mut transpiler = Transpiler::new();
let test_cases = vec![
"import std",
"import std.io",
"from std import println",
"from math import { sin, cos, tan }",
"export fn public() { }",
"export const PI = 3.15",
"export { func1, func2 }",
];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_edge_cases() {
let mut transpiler = Transpiler::new();
let test_cases = vec!["", ";", "{ }", "( )", "let x", "fn f"];
for code in test_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let _ = transpiler.transpile(&ast);
}
}
}
#[test]
fn test_helper_functions() {
let transpiler = Transpiler::new();
assert!(transpiler.pattern_needs_slice(&Pattern::List(vec![])));
let vec_expr = Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
};
assert!(transpiler.value_creates_vec(&vec_expr));
assert!(super::super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::super::function_analysis::looks_like_numeric_function("pow"));
assert!(super::super::function_analysis::looks_like_numeric_function("abs"));
assert!(!super::super::function_analysis::looks_like_numeric_function(
"println"
));
}
#[test]
fn test_advanced_transpilation_patterns() {
let mut transpiler = Transpiler::new();
let advanced_cases = vec![
"let mut x = { let y = 5; y * 2 }",
"let (a, b, c) = (1, 2, 3)",
"let Point { x, y } = point",
"let [first, ..rest] = array",
"fn complex(x: Option<T>) -> Result<U, Error> { match x { Some(v) => Ok(transform(v)), None => Err(\"empty\") } }",
"fn generic<T: Clone + Debug>(items: Vec<T>) -> Vec<T> { items.iter().cloned().collect() }",
"fn async_complex() -> impl Future<Output = Result<String, Error>> { async { Ok(\"result\".to_string()) } }",
"match result { Ok(data) => { let processed = process(data); save(processed) }, Err(e) => log_error(e) }",
"if let Some(value) = optional { value * 2 } else { default_value() }",
"while let Some(item) = iterator.next() { process_item(item); }",
"for (index, value) in enumerated { println!(\"{}: {}\", index, value); }",
"data.filter(|x| x > 0).map(|x| x * 2).collect::<Vec<_>>()",
"async_function().await.unwrap_or_else(|e| handle_error(e))",
"object.method()?.another_method().chain().build()",
"vec![1, 2, 3].into_iter().enumerate().collect()",
"HashMap::from([(\"key1\", value1), (\"key2\", value2)])",
"BTreeSet::from_iter([1, 2, 3, 2, 1])",
"match complex_enum { Variant::A { field1, field2 } => process(field1, field2), Variant::B(data) => handle(data), _ => default() }",
"let closure = |x: i32, y: i32| -> Result<i32, String> { if x > 0 { Ok(x + y) } else { Err(\"negative\".to_string()) } }",
"items.fold(0, |acc, item| acc + item.value)",
"let complex_type: HashMap<String, Vec<Result<i32, Error>>> = HashMap::new()",
"#[derive(Debug, Clone)] #[serde(rename_all = \"camelCase\")] struct Complex { field: String }",
];
for code in advanced_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_error_path_coverage() {
let mut transpiler = Transpiler::new();
let error_cases = vec![
"let = 5",
"fn ()",
"match { }",
"if { }",
"for { }",
"while { }",
"let x: String = 42",
"let y: Vec<i32> = \"string\"",
"undefined_function()",
"some_var.nonexistent_method()",
"invalid.chain.of.calls()",
"((((((nested))))))",
"{ { { { { nested } } } } }",
"let _ = _",
"let .. = array",
"match x { .. => {} }",
"",
";",
"{ }",
"fn() {}",
"let;",
];
for code in error_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_transpiler_helper_methods_comprehensive() {
let transpiler = Transpiler::new();
assert!(super::super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(!super::super::function_analysis::looks_like_numeric_function(
"println"
));
let numeric_functions = vec![
"sin",
"cos",
"tan",
"asin",
"acos",
"atan",
"atan2",
"sinh",
"cosh",
"tanh",
"asinh",
"acosh",
"atanh",
"exp",
"exp2",
"ln",
"log",
"log2",
"log10",
"sqrt",
"cbrt",
"pow",
"powf",
"powi",
"abs",
"signum",
"copysign",
"floor",
"ceil",
"round",
"trunc",
"fract",
"min",
"max",
"clamp",
"to_degrees",
"to_radians",
];
for func in numeric_functions {
assert!(super::super::function_analysis::looks_like_numeric_function(func));
}
let non_numeric_functions = vec![
"println",
"print",
"format",
"write",
"read",
"push",
"pop",
"insert",
"remove",
"clear",
"len",
"is_empty",
"contains",
"starts_with",
"ends_with",
"split",
"join",
"replace",
"trim",
"to_uppercase",
"to_lowercase",
];
for func in non_numeric_functions {
assert!(!super::super::function_analysis::looks_like_numeric_function(func));
}
let slice_patterns = vec![
Pattern::List(vec![Pattern::Wildcard]),
Pattern::List(vec![
Pattern::Identifier("x".to_string()),
Pattern::Wildcard,
]),
Pattern::Tuple(vec![Pattern::List(vec![])]),
];
for pattern in slice_patterns {
transpiler.pattern_needs_slice(&pattern); }
let vec_expressions = vec![
Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
},
Expr {
kind: ExprKind::Call {
func: Box::new(Expr {
kind: ExprKind::Identifier("vec".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
}),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: Vec::new(),
trailing_comment: None,
},
];
for expr in vec_expressions {
transpiler.value_creates_vec(&expr); }
}
#[test]
fn test_extreme_edge_cases() {
let mut transpiler = Transpiler::new();
let edge_cases = vec![
"let very_very_very_long_identifier_name_that_goes_on_and_on_and_on = 42",
"if true { if true { if true { if true { println!(\"deep\") } } } }",
"fn many_params(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) -> i32 { a + b + c + d + e + f + g + h }",
"fn generic_complex<T: Clone + Debug + Send + Sync + 'static>(x: T) -> T where T: PartialEq + Eq + Hash { x }",
"let 变量 = 42",
"let москва = \"city\"",
"let 🚀 = \"rocket\"",
"let big = 123456789012345678901234567890",
"let float = 123.456789012345678901234567890",
"let complex_string = \"String with \\n newlines \\t tabs \\\" quotes and 🚀 emojis\"",
"let raw_string = r#\"Raw string with \"quotes\" and #hashtags\"#",
"let nested = vec![vec![vec![1, 2], vec![3, 4]], vec![vec![5, 6], vec![7, 8]]]",
"println!(\"Format {} with {} multiple {} args\", 1, 2, 3)",
"vec![1; 1000]",
"format!(\"Complex formatting: {:#?}\", complex_data)",
];
for code in edge_cases {
let mut parser = Parser::new(code);
if let Ok(ast) = parser.parse() {
let result = transpiler.transpile(&ast);
assert!(result.is_ok() || result.is_err());
}
}
}
#[test]
fn test_is_variable_mutated_assign_v2() {
let target = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let assign_expr = Expr {
kind: ExprKind::Assign {
target: Box::new(target),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"x",
&assign_expr
));
assert!(!super::super::mutation_detection::is_variable_mutated(
"y",
&assign_expr
));
}
#[test]
fn test_is_variable_mutated_compound_assign_v2() {
let target = Expr {
kind: ExprKind::Identifier("counter".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let compound_expr = Expr {
kind: ExprKind::CompoundAssign {
target: Box::new(target),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Add,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"counter",
&compound_expr
));
}
#[test]
fn test_is_variable_mutated_pre_increment_v2() {
let target = Expr {
kind: ExprKind::Identifier("i".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let inc_expr = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(target),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"i", &inc_expr
));
}
#[test]
fn test_is_variable_mutated_post_decrement() {
let target = Expr {
kind: ExprKind::Identifier("value".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let dec_expr = Expr {
kind: ExprKind::PostDecrement {
target: Box::new(target),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"value", &dec_expr
));
}
#[test]
fn test_is_variable_mutated_in_block() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(10, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let block_expr = Expr {
kind: ExprKind::Block(vec![assign]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"x",
&block_expr
));
}
#[test]
fn test_is_variable_mutated_in_if() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("flag".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let if_expr = Expr {
kind: ExprKind::If {
condition: Box::new(assign),
then_branch: Box::new(Expr {
kind: ExprKind::Literal(Literal::Unit),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
else_branch: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"flag", &if_expr
));
}
#[test]
fn test_is_variable_mutated_in_while() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("count".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let while_expr = Expr {
kind: ExprKind::While {
condition: Box::new(Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(inc),
label: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"count",
&while_expr
));
}
#[test]
fn test_is_variable_mutated_in_for() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("sum".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(0, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let for_expr = Expr {
kind: ExprKind::For {
var: "item".to_string(),
pattern: Some(Pattern::Identifier("item".to_string())),
iter: Box::new(Expr {
kind: ExprKind::List(vec![]),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(assign),
label: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"sum", &for_expr
));
}
#[test]
fn test_is_variable_mutated_in_match() {
use crate::frontend::ast::MatchArm;
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("result".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let match_expr = Expr {
kind: ExprKind::Match {
expr: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
arms: vec![MatchArm {
pattern: Pattern::Wildcard,
guard: None,
body: Box::new(assign),
span: Span::default(),
}],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"result",
&match_expr
));
}
#[test]
fn test_is_variable_mutated_in_let() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let let_expr = Expr {
kind: ExprKind::Let {
name: "y".to_string(),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
body: Box::new(inc),
type_annotation: None,
is_mutable: false,
else_block: None,
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"x", &let_expr
));
}
#[test]
fn test_is_variable_mutated_in_binary() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("a".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let binary_expr = Expr {
kind: ExprKind::Binary {
left: Box::new(assign),
op: BinaryOp::Add,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(2, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"a",
&binary_expr
));
}
#[test]
fn test_is_variable_mutated_in_unary() {
let inc = Expr {
kind: ExprKind::PreIncrement {
target: Box::new(Expr {
kind: ExprKind::Identifier("val".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let unary_expr = Expr {
kind: ExprKind::Unary {
op: UnaryOp::Not,
operand: Box::new(inc),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"val",
&unary_expr
));
}
#[test]
fn test_is_variable_mutated_in_call() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("arg".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let call_expr = Expr {
kind: ExprKind::Call {
func: Box::new(Expr {
kind: ExprKind::Identifier("foo".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
args: vec![assign],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"arg", &call_expr
));
}
#[test]
fn test_is_variable_mutated_in_method_call() {
let assign = Expr {
kind: ExprKind::Assign {
target: Box::new(Expr {
kind: ExprKind::Identifier("obj".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
value: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(1, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
let method_expr = Expr {
kind: ExprKind::MethodCall {
receiver: Box::new(assign),
method: "process".to_string(),
args: vec![],
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(super::super::mutation_detection::is_variable_mutated(
"obj",
&method_expr
));
}
#[test]
fn test_is_variable_mutated_immutable_access() {
let literal = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!super::super::mutation_detection::is_variable_mutated(
"x", &literal
));
let ident = Expr {
kind: ExprKind::Identifier("x".to_string()),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!super::super::mutation_detection::is_variable_mutated("x", &ident));
}
#[test]
fn test_needs_lifetime_parameter_no_refs() {
let _transpiler = Transpiler::new();
let params = vec![Param {
pattern: Pattern::Identifier("x".to_string()),
ty: Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
},
default_value: None,
span: Span::default(),
is_mutable: false,
}];
assert!(!super::super::type_analysis::needs_lifetime_parameter(
¶ms, None
));
}
#[test]
fn test_needs_lifetime_parameter_requires_lifetime() {
let ref_type = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
let params = vec![
Param {
pattern: Pattern::Identifier("a".to_string()),
ty: ref_type.clone(),
default_value: None,
span: Span::default(),
is_mutable: false,
},
Param {
pattern: Pattern::Identifier("b".to_string()),
ty: ref_type.clone(),
default_value: None,
span: Span::default(),
is_mutable: false,
},
];
let return_type = Some(&ref_type);
assert!(super::super::type_analysis::needs_lifetime_parameter(
¶ms,
return_type
));
}
#[test]
fn test_is_reference_type_true() {
let ref_ty = Type {
kind: TypeKind::Reference {
is_mut: false,
lifetime: None,
inner: Box::new(Type {
kind: TypeKind::Named("str".to_string()),
span: Span::default(),
}),
},
span: Span::default(),
};
assert!(super::super::type_analysis::is_reference_type(&ref_ty));
}
#[test]
fn test_is_reference_type_false() {
let named_ty = Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
};
assert!(!super::super::type_analysis::is_reference_type(&named_ty));
}
#[test]
fn test_is_string_type_true() {
let string_ty = Type {
kind: TypeKind::Named("String".to_string()),
span: Span::default(),
};
assert!(super::super::type_analysis::is_string_type(&string_ty));
}
#[test]
fn test_is_string_type_false() {
let int_ty = Type {
kind: TypeKind::Named("i32".to_string()),
span: Span::default(),
};
assert!(!super::super::type_analysis::is_string_type(&int_ty));
}
#[test]
fn test_body_needs_string_conversion_string_literal() {
let body = Expr::new(
ExprKind::Literal(Literal::String("hello".to_string())),
Span::default(),
);
assert!(super::super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_body_needs_string_conversion_identifier() {
let body = Expr::new(ExprKind::Identifier("s".to_string()), Span::default());
assert!(super::super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_body_needs_string_conversion_integer() {
let body = Expr::new(
ExprKind::Literal(Literal::Integer(42, None)),
Span::default(),
);
assert!(!super::super::type_analysis::body_needs_string_conversion(&body));
}
#[test]
fn test_transpile_iterator_methods_map() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |x| x * 2 };
let result = transpiler
.transpile_iterator_methods(&obj, "map", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("iter"));
assert!(code.contains("map"));
assert!(code.contains("collect"));
}
#[test]
fn test_transpile_iterator_methods_filter() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |x| x > 10 };
let result = transpiler
.transpile_iterator_methods(&obj, "filter", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("into_iter"));
assert!(code.contains("filter"));
assert!(code.contains("collect"));
}
#[test]
fn test_transpile_iterator_methods_reduce() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { vec };
let f = quote! { |acc, x| acc + x };
let result = transpiler
.transpile_iterator_methods(&obj, "reduce", &[f])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("into_iter"));
assert!(code.contains("reduce"));
assert!(!code.contains("collect")); }
#[test]
fn test_transpile_map_set_methods_items() {
use proc_macro2::Span as ProcSpan;
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { map };
let method_ident = proc_macro2::Ident::new("items", ProcSpan::call_site());
let result = transpiler
.transpile_map_set_methods(&obj, &method_ident, "items", &[])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("iter"));
assert!(code.contains("clone"));
}
#[test]
fn test_transpile_map_set_methods_update() {
use proc_macro2::Span as ProcSpan;
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { map };
let method_ident = proc_macro2::Ident::new("update", ProcSpan::call_site());
let arg = quote! { other_map };
let result = transpiler
.transpile_map_set_methods(&obj, &method_ident, "update", &[arg])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("extend"));
}
#[test]
fn test_transpile_set_operations_union() {
use quote::quote;
let transpiler = Transpiler::new();
let obj = quote! { set1 };
let arg = quote! { set2 };
let result = transpiler
.transpile_set_operations(&obj, "union", &[arg])
.expect("operation should succeed in test");
let code = result.to_string();
assert!(code.contains("union"));
assert!(code.contains("cloned"));
assert!(code.contains("HashSet"));
}
#[test]
fn test_looks_like_numeric_function_true() {
let _transpiler = Transpiler::new();
assert!(super::super::function_analysis::looks_like_numeric_function("abs"));
assert!(super::super::function_analysis::looks_like_numeric_function(
"sqrt"
));
assert!(super::super::function_analysis::looks_like_numeric_function("pow"));
}
#[test]
fn test_looks_like_numeric_function_false() {
let _transpiler = Transpiler::new();
assert!(!super::super::function_analysis::looks_like_numeric_function(
"print"
));
assert!(!super::super::function_analysis::looks_like_numeric_function(
"hello"
));
}
#[test]
fn test_returns_boolean_literal() {
let body = Expr {
kind: ExprKind::Literal(Literal::Bool(true)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_boolean(&body));
}
#[test]
fn test_returns_boolean_comparison_v2() {
let body = Expr {
kind: ExprKind::Binary {
left: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
op: BinaryOp::Equal,
right: Box::new(Expr {
kind: ExprKind::Literal(Literal::Integer(5, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
},
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_boolean(&body));
}
#[test]
fn test_returns_string_literal_true() {
let body = Expr {
kind: ExprKind::Literal(Literal::String("test".to_string())),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(returns_string_literal(&body));
}
#[test]
fn test_returns_string_literal_false() {
let body = Expr {
kind: ExprKind::Literal(Literal::Integer(42, None)),
span: Span::default(),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
};
assert!(!returns_string_literal(&body));
}