use crate::interactive::*;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_interactive_session_creation() {
let session = InteractiveSession::new();
let _ = session; }
#[test]
fn test_suggestion_type_variants() {
let types = [
SuggestionType::Performance,
SuggestionType::Safety,
SuggestionType::TypeStrategy,
SuggestionType::ErrorHandling,
SuggestionType::Concurrency,
SuggestionType::Memory,
];
assert_eq!(types.len(), 6);
}
#[test]
fn test_impact_level_ordering() {
assert!(ImpactLevel::Low < ImpactLevel::Medium);
assert!(ImpactLevel::Medium < ImpactLevel::High);
assert!(ImpactLevel::Low < ImpactLevel::High);
}
#[test]
fn test_annotation_suggestion_creation() {
let suggestion = AnnotationSuggestion {
line: 5,
function_name: "test_func".to_string(),
suggestion_type: SuggestionType::Performance,
annotation: "# @depyler: optimize = true".to_string(),
reason: "Function has nested loops".to_string(),
impact: ImpactLevel::High,
};
assert_eq!(suggestion.line, 5);
assert_eq!(suggestion.function_name, "test_func");
assert!(matches!(
suggestion.suggestion_type,
SuggestionType::Performance
));
assert_eq!(suggestion.impact, ImpactLevel::High);
}
#[test]
fn test_attempt_transpilation_simple() {
let session = InteractiveSession::new();
let python_code = "def add(a: int, b: int) -> int:\n return a + b";
match session.attempt_transpilation(python_code) {
Ok((rust_code, warnings)) => {
assert!(!rust_code.is_empty());
assert!(warnings.is_empty() || warnings.len() < 2);
}
Err(_) => {
}
}
}
#[test]
fn test_attempt_transpilation_with_unsafe() {
let _session = InteractiveSession::new();
let rust_code = "unsafe { std::ptr::null() }";
let _warnings: Vec<String> = vec![];
assert!(rust_code.contains("unsafe"));
}
#[test]
#[ignore = "Requires terminal interaction"]
fn test_run_with_temp_file() {
let mut session = InteractiveSession::new();
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, "def simple():\n return 42").unwrap();
let result = session.run(temp_file.path().to_str().unwrap(), false);
if result.is_ok() {}
}
#[test]
#[ignore = "Requires terminal interaction"]
fn test_suggest_improvements() {
let session = InteractiveSession::new();
let python_code =
"def compute(data):\n for i in data:\n for j in data:\n pass";
let rust_code = "fn compute(data: Vec<i32>) {}";
let result = session.suggest_improvements(python_code, rust_code);
if result.is_ok() {}
}
#[test]
fn test_default_trait() {
let session1 = InteractiveSession::new();
let session2 = InteractiveSession::default();
let _ = session1;
let _ = session2;
}
#[test]
fn test_suggestion_type_debug() {
let perf = SuggestionType::Performance;
let safety = SuggestionType::Safety;
let type_strat = SuggestionType::TypeStrategy;
let error = SuggestionType::ErrorHandling;
let concurrency = SuggestionType::Concurrency;
let memory = SuggestionType::Memory;
assert!(format!("{:?}", perf).contains("Performance"));
assert!(format!("{:?}", safety).contains("Safety"));
assert!(format!("{:?}", type_strat).contains("TypeStrategy"));
assert!(format!("{:?}", error).contains("ErrorHandling"));
assert!(format!("{:?}", concurrency).contains("Concurrency"));
assert!(format!("{:?}", memory).contains("Memory"));
}
#[test]
fn test_suggestion_type_clone() {
let original = SuggestionType::Performance;
let cloned = original.clone();
assert!(matches!(cloned, SuggestionType::Performance));
}
#[test]
fn test_impact_level_debug() {
let low = ImpactLevel::Low;
let medium = ImpactLevel::Medium;
let high = ImpactLevel::High;
assert!(format!("{:?}", low).contains("Low"));
assert!(format!("{:?}", medium).contains("Medium"));
assert!(format!("{:?}", high).contains("High"));
}
#[test]
fn test_impact_level_clone() {
let original = ImpactLevel::High;
let cloned = original; assert_eq!(original, cloned);
}
#[test]
fn test_impact_level_equality() {
let l1 = ImpactLevel::Low;
let l2 = ImpactLevel::Low;
let m = ImpactLevel::Medium;
assert_eq!(l1, l2);
assert_ne!(l1, m);
}
#[test]
fn test_impact_level_sorting() {
let mut levels = vec![ImpactLevel::High, ImpactLevel::Low, ImpactLevel::Medium];
levels.sort();
assert_eq!(levels, vec![ImpactLevel::Low, ImpactLevel::Medium, ImpactLevel::High]);
}
#[test]
fn test_annotation_suggestion_debug() {
let suggestion = AnnotationSuggestion {
line: 10,
function_name: "test".to_string(),
suggestion_type: SuggestionType::Safety,
annotation: "# @depyler: safe = true".to_string(),
reason: "Test reason".to_string(),
impact: ImpactLevel::Medium,
};
let debug = format!("{:?}", suggestion);
assert!(debug.contains("line"));
assert!(debug.contains("function_name"));
}
#[test]
fn test_annotation_suggestion_clone() {
let suggestion = AnnotationSuggestion {
line: 1,
function_name: "clone_test".to_string(),
suggestion_type: SuggestionType::Memory,
annotation: "# @depyler: memory = \"efficient\"".to_string(),
reason: "Memory optimization".to_string(),
impact: ImpactLevel::Low,
};
let cloned = suggestion.clone();
assert_eq!(suggestion.line, cloned.line);
assert_eq!(suggestion.function_name, cloned.function_name);
assert_eq!(suggestion.annotation, cloned.annotation);
assert_eq!(suggestion.reason, cloned.reason);
assert_eq!(suggestion.impact, cloned.impact);
}
#[test]
fn test_attempt_transpilation_function_with_loop() {
let session = InteractiveSession::new();
let python_code = r#"def sum_list(items: list) -> int:
result = 0
for item in items:
result = result + item
return result"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_nested_function() {
let session = InteractiveSession::new();
let python_code = r#"def outer(x: int) -> int:
def inner(y: int) -> int:
return y * 2
return inner(x)"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_with_conditionals() {
let session = InteractiveSession::new();
let python_code = r#"def abs_value(x: int) -> int:
if x < 0:
return -x
else:
return x"#;
let result = session.attempt_transpilation(python_code);
if let Ok((rust_code, _)) = result {
assert!(!rust_code.is_empty());
}
}
#[test]
fn test_attempt_transpilation_empty_function() {
let session = InteractiveSession::new();
let python_code = "def empty() -> None:\n pass";
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_with_string_ops() {
let session = InteractiveSession::new();
let python_code = r#"def concat(a: str, b: str) -> str:
return a + b"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_with_list_append() {
let session = InteractiveSession::new();
let python_code = r#"def build_list() -> list:
result = []
result.append(1)
result.append(2)
return result"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_with_dict() {
let session = InteractiveSession::new();
let python_code = r#"def get_dict() -> dict:
d = {}
d["key"] = "value"
return d"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_multiline() {
let session = InteractiveSession::new();
let python_code = r#"def multi_line(x: int, y: int, z: int) -> int:
a = x + y
b = a * z
c = b - x
return c"#;
let result = session.attempt_transpilation(python_code);
if let Ok((rust_code, _)) = result {
assert!(!rust_code.is_empty());
}
}
#[test]
fn test_attempt_transpilation_invalid_syntax() {
let session = InteractiveSession::new();
let python_code = "def invalid(\n syntax error here";
let result = session.attempt_transpilation(python_code);
assert!(result.is_err());
}
#[test]
fn test_attempt_transpilation_empty_source() {
let session = InteractiveSession::new();
let python_code = "";
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_comment_only() {
let session = InteractiveSession::new();
let python_code = "# Just a comment";
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_class_definition() {
let session = InteractiveSession::new();
let python_code = r#"class Point:
def __init__(self, x: int, y: int):
self.x = x
self.y = y"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_with_import() {
let session = InteractiveSession::new();
let python_code = r#"from typing import List
def process(items: List[int]) -> int:
return sum(items)"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_run_interactive_session_function_exists() {
}
#[test]
fn test_annotation_suggestion_with_all_suggestion_types() {
let suggestions = vec![
AnnotationSuggestion {
line: 1,
function_name: "perf_fn".to_string(),
suggestion_type: SuggestionType::Performance,
annotation: "# @depyler: optimize".to_string(),
reason: "Perf".to_string(),
impact: ImpactLevel::High,
},
AnnotationSuggestion {
line: 2,
function_name: "safe_fn".to_string(),
suggestion_type: SuggestionType::Safety,
annotation: "# @depyler: safe".to_string(),
reason: "Safety".to_string(),
impact: ImpactLevel::High,
},
AnnotationSuggestion {
line: 3,
function_name: "type_fn".to_string(),
suggestion_type: SuggestionType::TypeStrategy,
annotation: "# @depyler: type".to_string(),
reason: "Type".to_string(),
impact: ImpactLevel::Medium,
},
AnnotationSuggestion {
line: 4,
function_name: "error_fn".to_string(),
suggestion_type: SuggestionType::ErrorHandling,
annotation: "# @depyler: error".to_string(),
reason: "Error".to_string(),
impact: ImpactLevel::Medium,
},
AnnotationSuggestion {
line: 5,
function_name: "conc_fn".to_string(),
suggestion_type: SuggestionType::Concurrency,
annotation: "# @depyler: concurrent".to_string(),
reason: "Concurrency".to_string(),
impact: ImpactLevel::Low,
},
AnnotationSuggestion {
line: 6,
function_name: "mem_fn".to_string(),
suggestion_type: SuggestionType::Memory,
annotation: "# @depyler: memory".to_string(),
reason: "Memory".to_string(),
impact: ImpactLevel::Low,
},
];
assert_eq!(suggestions.len(), 6);
let mut sorted = suggestions.clone();
sorted.sort_by(|a, b| b.impact.cmp(&a.impact).then_with(|| a.line.cmp(&b.line)));
assert!(matches!(sorted[0].impact, ImpactLevel::High));
}
#[test]
fn test_multiple_sessions() {
let session1 = InteractiveSession::new();
let session2 = InteractiveSession::new();
let session3 = InteractiveSession::default();
let code = "def foo() -> int:\n return 1";
let _r1 = session1.attempt_transpilation(code);
let _r2 = session2.attempt_transpilation(code);
let _r3 = session3.attempt_transpilation(code);
}
#[test]
fn test_impact_level_partial_ord() {
let low = ImpactLevel::Low;
let medium = ImpactLevel::Medium;
let high = ImpactLevel::High;
assert!(low.partial_cmp(&medium) == Some(std::cmp::Ordering::Less));
assert!(medium.partial_cmp(&high) == Some(std::cmp::Ordering::Less));
assert!(high.partial_cmp(&low) == Some(std::cmp::Ordering::Greater));
assert!(medium.partial_cmp(&medium) == Some(std::cmp::Ordering::Equal));
}
#[test]
fn test_warning_detection_unsafe() {
let rust_code = "pub fn dangerous() { unsafe { } }";
assert!(rust_code.contains("unsafe"));
}
#[test]
fn test_warning_detection_panic() {
let rust_code = "pub fn might_fail() { panic!(\"error\"); }";
assert!(rust_code.contains("panic!"));
}
#[test]
fn test_attempt_transpilation_boolean_ops() {
let session = InteractiveSession::new();
let python_code = r#"def check(a: bool, b: bool) -> bool:
return a and b or not a"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_comparison() {
let session = InteractiveSession::new();
let python_code = r#"def compare(x: int, y: int) -> bool:
return x < y and y > 0"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_while_loop() {
let session = InteractiveSession::new();
let python_code = r#"def countdown(n: int) -> int:
while n > 0:
n = n - 1
return n"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_optional_return() {
let session = InteractiveSession::new();
let python_code = r#"from typing import Optional
def maybe_value(x: int) -> Optional[int]:
if x > 0:
return x
return None"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_run_nonexistent_file() {
let mut session = InteractiveSession::new();
let result = session.run("/nonexistent/path/to/file.py", false);
assert!(result.is_err());
}
#[test]
fn test_impact_level_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(ImpactLevel::Low);
set.insert(ImpactLevel::Medium);
set.insert(ImpactLevel::High);
set.insert(ImpactLevel::Low);
assert_eq!(set.len(), 3);
}
mod helper_method_tests {
use super::*;
use depyler_core::ast_bridge::AstBridge;
use depyler_core::hir::{BinOp, HirExpr, HirFunction, Literal};
use rustpython_parser::{parse, Mode};
fn parse_to_hir(python_code: &str) -> Vec<HirFunction> {
let ast = parse(python_code, Mode::Module, "<test>").unwrap();
let (hir, _) = AstBridge::new()
.with_source(python_code.to_string())
.python_to_hir(ast)
.unwrap();
hir.functions
}
#[test]
fn test_has_loops_with_for_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n pass");
assert!(session.has_loops(&funcs[0].body));
}
#[test]
fn test_has_loops_with_while_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n while True:\n break");
assert!(session.has_loops(&funcs[0].body));
}
#[test]
fn test_has_loops_no_loops() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n x = 1\n return x");
assert!(!session.has_loops(&funcs[0].body));
}
#[test]
fn test_has_loops_in_if_branch() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int):\n if x > 0:\n for i in range(x):\n pass");
assert!(session.has_loops(&funcs[0].body));
}
#[test]
fn test_has_loops_in_else_branch() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int):\n if x > 0:\n pass\n else:\n for i in range(10):\n pass");
assert!(session.has_loops(&funcs[0].body));
}
#[test]
fn test_has_nested_loops_true() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n for j in range(10):\n pass");
assert!(session.has_nested_loops(&funcs[0].body));
}
#[test]
fn test_has_nested_loops_false_single_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n x = i");
assert!(!session.has_nested_loops(&funcs[0].body));
}
#[test]
fn test_has_nested_loops_while_in_for() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n while i > 0:\n i = i - 1");
assert!(session.has_nested_loops(&funcs[0].body));
}
#[test]
fn test_has_nested_loops_in_if() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int):\n if x > 0:\n for i in range(x):\n for j in range(i):\n pass");
assert!(session.has_nested_loops(&funcs[0].body));
}
#[test]
fn test_has_simple_numeric_loop_range() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n x = i");
assert!(session.has_simple_numeric_loop(&funcs[0].body));
}
#[test]
fn test_has_simple_numeric_loop_nested_not_simple() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n for j in range(i):\n pass");
assert!(!session.has_simple_numeric_loop(&funcs[0].body));
}
#[test]
fn test_has_large_collections_list_param() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(items: list) -> int:\n return len(items)");
assert!(session.has_large_collections(&funcs[0]));
}
#[test]
fn test_has_large_collections_dict_param() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(data: dict) -> int:\n return len(data)");
assert!(session.has_large_collections(&funcs[0]));
}
#[test]
fn test_has_large_collections_no_collections() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int, y: int) -> int:\n return x + y");
assert!(!session.has_large_collections(&funcs[0]));
}
#[test]
fn test_is_collection_modified_with_append() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(items: list):\n items.append(1)");
let _ = session.is_collection_modified(&funcs[0]);
}
#[test]
fn test_is_collection_modified_no_modification() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(items: list) -> int:\n return len(items)");
assert!(!session.is_collection_modified(&funcs[0]));
}
#[test]
fn test_is_collection_modified_simple_assignment() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(items: list):\n x = items[0]");
assert!(!session.is_collection_modified(&funcs[0]));
}
#[test]
fn test_has_string_operations_param() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(s: str) -> int:\n return len(s)");
assert!(session.has_string_operations(&funcs[0]));
}
#[test]
fn test_has_string_operations_return() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> str:\n return str(x)");
assert!(session.has_string_operations(&funcs[0]));
}
#[test]
fn test_has_string_operations_none() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x * 2");
assert!(!session.has_string_operations(&funcs[0]));
}
#[test]
fn test_has_string_concatenation_true() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(a: str, b: str) -> str:\n return a + b");
let _ = session.has_string_concatenation(&funcs[0].body);
}
#[test]
fn test_has_string_concatenation_int_addition() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x + 1");
let _ = session.has_string_concatenation(&funcs[0].body);
}
#[test]
fn test_has_string_concatenation_no_add() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x * 2");
assert!(!session.has_string_concatenation(&funcs[0].body));
}
#[test]
fn test_calculate_complexity_simple() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x");
let complexity = session.calculate_complexity(&funcs[0].body);
assert!(complexity >= 1);
}
#[test]
fn test_calculate_complexity_with_if() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n if x > 0:\n return x\n return 0");
let complexity = session.calculate_complexity(&funcs[0].body);
assert!(complexity >= 2); }
#[test]
fn test_calculate_complexity_with_loops() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f():\n for i in range(10):\n x = i");
let complexity = session.calculate_complexity(&funcs[0].body);
assert!(complexity >= 3); }
#[test]
fn test_calculate_complexity_nested_structures() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int):\n if x > 0:\n for i in range(x):\n if i > 5:\n pass");
let complexity = session.calculate_complexity(&funcs[0].body);
assert!(complexity >= 5); }
#[test]
fn test_find_function_line_found() {
let session = InteractiveSession::new();
let source = "# comment\ndef my_func():\n pass";
let line = session.find_function_line(source, "my_func");
assert_eq!(line, 2);
}
#[test]
fn test_find_function_line_first_line() {
let session = InteractiveSession::new();
let source = "def first():\n pass";
let line = session.find_function_line(source, "first");
assert_eq!(line, 1);
}
#[test]
fn test_find_function_line_not_found() {
let session = InteractiveSession::new();
let source = "def other():\n pass";
let line = session.find_function_line(source, "nonexistent");
assert_eq!(line, 0);
}
#[test]
fn test_find_function_line_multiple_functions() {
let session = InteractiveSession::new();
let source = "def first():\n pass\n\ndef second():\n pass";
assert_eq!(session.find_function_line(source, "first"), 1);
assert_eq!(session.find_function_line(source, "second"), 4);
}
#[test]
fn test_apply_annotation_basic() {
let session = InteractiveSession::new();
let source = "def my_func():\n pass";
let suggestion = AnnotationSuggestion {
line: 1,
function_name: "my_func".to_string(),
suggestion_type: SuggestionType::Performance,
annotation: "# @depyler: optimize".to_string(),
reason: "test".to_string(),
impact: ImpactLevel::High,
};
let result = session.apply_annotation(source, &suggestion).unwrap();
assert!(result.contains("# @depyler: optimize"));
assert!(result.contains("def my_func"));
}
#[test]
fn test_apply_annotation_preserves_code() {
let session = InteractiveSession::new();
let source = "def foo():\n return 42";
let suggestion = AnnotationSuggestion {
line: 1,
function_name: "foo".to_string(),
suggestion_type: SuggestionType::Safety,
annotation: "# @depyler: safe".to_string(),
reason: "test".to_string(),
impact: ImpactLevel::Medium,
};
let result = session.apply_annotation(source, &suggestion).unwrap();
assert!(result.contains("return 42"));
}
#[test]
fn test_has_array_access_true() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list) -> int:\n return arr[0]");
assert!(session.has_array_access(&funcs[0]));
}
#[test]
fn test_has_array_access_false() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x");
assert!(!session.has_array_access(&funcs[0]));
}
#[test]
fn test_has_dict_access_true() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict) -> int:\n return d[\"key\"]");
assert!(session.has_dict_access(&funcs[0].body));
}
#[test]
fn test_has_shared_state_always_false() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x");
assert!(!session.has_shared_state(&funcs[0]));
}
#[test]
fn test_only_reads_strings_true() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(s: str) -> int:\n return len(s)");
assert!(session.only_reads_strings(&funcs[0]));
}
#[test]
fn test_has_frequent_lookups_dict_in_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict):\n for k in d:\n x = d[k]");
assert!(session.has_frequent_lookups(&funcs[0]));
}
#[test]
fn test_has_frequent_lookups_no_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict) -> int:\n return d[\"key\"]");
assert!(!session.has_frequent_lookups(&funcs[0]));
}
#[test]
fn test_generate_annotation_suggestions_nested_loops() {
let session = InteractiveSession::new();
let code = "def matrix_mult(a: list, b: list) -> list:\n for i in range(len(a)):\n for j in range(len(b)):\n pass\n return a";
let suggestions = session.generate_annotation_suggestions(code).unwrap();
assert!(!suggestions.is_empty());
}
#[test]
fn test_generate_annotation_suggestions_simple_function() {
let session = InteractiveSession::new();
let code = "def add(a: int, b: int) -> int:\n return a + b";
let suggestions = session.generate_annotation_suggestions(code).unwrap();
let _ = suggestions;
}
#[test]
fn test_generate_annotation_suggestions_with_collections() {
let session = InteractiveSession::new();
let code = "def process(data: list) -> int:\n result = 0\n for item in data:\n result = result + item\n return result";
let suggestions = session.generate_annotation_suggestions(code).unwrap();
let _ = suggestions;
}
#[test]
fn test_show_diff_identical() {
let session = InteractiveSession::new();
let original = "line1\nline2\nline3";
let modified = "line1\nline2\nline3";
let result = session.show_diff(original, modified);
assert!(result.is_ok());
}
#[test]
fn test_show_diff_with_changes() {
let session = InteractiveSession::new();
let original = "line1\nline2";
let modified = "line1\nmodified_line2";
let result = session.show_diff(original, modified);
assert!(result.is_ok());
}
#[test]
fn test_show_diff_added_lines() {
let session = InteractiveSession::new();
let original = "line1";
let modified = "line1\nline2\nline3";
let result = session.show_diff(original, modified);
assert!(result.is_ok());
}
#[test]
fn test_display_suggestion_all_types() {
let session = InteractiveSession::new();
let types = vec![
SuggestionType::Performance,
SuggestionType::Safety,
SuggestionType::TypeStrategy,
SuggestionType::ErrorHandling,
SuggestionType::Concurrency,
SuggestionType::Memory,
];
let impacts = vec![ImpactLevel::High, ImpactLevel::Medium, ImpactLevel::Low];
for (i, suggestion_type) in types.into_iter().enumerate() {
let suggestion = AnnotationSuggestion {
line: i + 1,
function_name: format!("func_{}", i),
suggestion_type,
annotation: "# @depyler: test".to_string(),
reason: "Test reason".to_string(),
impact: impacts[i % 3],
};
session.display_suggestion(i + 1, &suggestion);
}
}
#[test]
fn test_has_modification_patterns_method_call_not_detected() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.append(1)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_extend_method() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.extend([1, 2])");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_in_if() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list, x: int):\n if x > 0:\n lst.append(x)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_in_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n for i in range(10):\n lst.append(i)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_remove() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.remove(1)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_pop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.pop()");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_clear() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.clear()");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_insert() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list):\n lst.insert(0, 1)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_no_calls() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(x: int) -> int:\n return x + 1");
assert!(!session.has_modification_patterns(&funcs[0].body));
}
#[test]
fn test_has_modification_patterns_in_else_branch() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list, x: int):\n if x > 0:\n pass\n else:\n lst.append(x)");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_modification_patterns_in_while_loop() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(lst: list, i: int):\n while i > 0:\n lst.append(i)\n i = i - 1");
let _ = session.has_modification_patterns(&funcs[0].body);
}
#[test]
fn test_has_index_access_in_assign() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list):\n x = arr[0]");
assert!(session.has_index_access(&funcs[0].body));
}
#[test]
fn test_has_index_access_in_return() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list) -> int:\n return arr[0]");
assert!(session.has_index_access(&funcs[0].body));
}
#[test]
fn test_has_index_access_in_condition() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list) -> bool:\n if arr[0] > 0:\n return True\n return False");
let _ = session.has_index_access(&funcs[0].body);
}
#[test]
fn test_has_index_access_direct_in_condition_expr() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list):\n x = arr[0]\n if x > 0:\n pass");
assert!(session.has_index_access(&funcs[0].body));
}
#[test]
fn test_has_index_access_in_for_body() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(arr: list):\n for i in range(len(arr)):\n x = arr[i]");
assert!(session.has_index_access(&funcs[0].body));
}
#[test]
fn test_is_string_expr_literal() {
let session = InteractiveSession::new();
let expr = HirExpr::Literal(Literal::String("test".to_string()));
assert!(session.is_string_expr(&expr));
}
#[test]
fn test_is_string_expr_var() {
let session = InteractiveSession::new();
let expr = HirExpr::Var("s".to_string());
assert!(session.is_string_expr(&expr));
}
#[test]
fn test_is_string_expr_int() {
let session = InteractiveSession::new();
let expr = HirExpr::Literal(Literal::Int(42));
assert!(!session.is_string_expr(&expr));
}
#[test]
fn test_has_index_expr_true() {
let session = InteractiveSession::new();
let expr = HirExpr::Index {
base: Box::new(HirExpr::Var("arr".to_string())),
index: Box::new(HirExpr::Literal(Literal::Int(0))),
};
assert!(session.has_index_expr(&expr));
}
#[test]
fn test_has_index_expr_false() {
let session = InteractiveSession::new();
let expr = HirExpr::Var("x".to_string());
assert!(!session.has_index_expr(&expr));
}
#[test]
fn test_has_lookup_in_loop_for() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict):\n for k in d:\n v = d[k]");
assert!(session.has_lookup_in_loop(&funcs[0].body));
}
#[test]
fn test_has_lookup_in_loop_while() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict, i: int):\n while i > 0:\n v = d[\"key\"]\n i = i - 1");
assert!(session.has_lookup_in_loop(&funcs[0].body));
}
#[test]
fn test_has_lookup_in_loop_none() {
let session = InteractiveSession::new();
let funcs = parse_to_hir("def f(d: dict) -> int:\n return d[\"key\"]");
assert!(!session.has_lookup_in_loop(&funcs[0].body));
}
#[test]
fn test_has_string_concat_expr_with_string_literal() {
let session = InteractiveSession::new();
let expr = HirExpr::Binary {
op: BinOp::Add,
left: Box::new(HirExpr::Literal(Literal::String("hello".to_string()))),
right: Box::new(HirExpr::Var("s".to_string())),
};
assert!(session.has_string_concat_expr(&expr));
}
#[test]
fn test_has_string_concat_expr_with_int() {
let session = InteractiveSession::new();
let expr = HirExpr::Binary {
op: BinOp::Add,
left: Box::new(HirExpr::Literal(Literal::Int(1))),
right: Box::new(HirExpr::Literal(Literal::Int(2))),
};
assert!(!session.has_string_concat_expr(&expr));
}
#[test]
fn test_has_string_concat_expr_not_add() {
let session = InteractiveSession::new();
let expr = HirExpr::Binary {
op: BinOp::Mul,
left: Box::new(HirExpr::Var("a".to_string())),
right: Box::new(HirExpr::Var("b".to_string())),
};
assert!(!session.has_string_concat_expr(&expr));
}
}
#[test]
fn test_run_with_empty_file() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, "").unwrap();
let mut session = InteractiveSession::new();
let _ = session.run(temp_file.path().to_str().unwrap(), false);
}
#[test]
fn test_attempt_transpilation_deeply_nested() {
let session = InteractiveSession::new();
let python_code = r#"def deep(x: int) -> int:
if x > 0:
if x > 10:
if x > 100:
return x
else:
return x * 2
else:
return x + 1
else:
return 0"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_attempt_transpilation_multiple_returns() {
let session = InteractiveSession::new();
let python_code = r#"def multi_return(x: int) -> int:
if x < 0:
return -1
if x == 0:
return 0
if x < 10:
return 1
return 2"#;
let _result = session.attempt_transpilation(python_code);
}
#[test]
fn test_annotation_suggestion_sorting() {
let mut suggestions = vec![
AnnotationSuggestion {
line: 10,
function_name: "a".to_string(),
suggestion_type: SuggestionType::Performance,
annotation: "".to_string(),
reason: "".to_string(),
impact: ImpactLevel::Low,
},
AnnotationSuggestion {
line: 5,
function_name: "b".to_string(),
suggestion_type: SuggestionType::Safety,
annotation: "".to_string(),
reason: "".to_string(),
impact: ImpactLevel::High,
},
AnnotationSuggestion {
line: 1,
function_name: "c".to_string(),
suggestion_type: SuggestionType::Memory,
annotation: "".to_string(),
reason: "".to_string(),
impact: ImpactLevel::High,
},
];
suggestions.sort_by(|a, b| b.impact.cmp(&a.impact).then_with(|| a.line.cmp(&b.line)));
assert_eq!(suggestions[0].line, 1); assert_eq!(suggestions[1].line, 5); assert_eq!(suggestions[2].line, 10); }