use vb6parse::parsers::cst::ConcreteSyntaxTree;
use std::fmt::Write;
#[test]
fn deeply_nested_if_statements() {
const DEPTH: usize = 50;
let mut source = String::from("Sub Test()\n");
for i in 0..DEPTH {
let _ = writeln!(source, "{}If x{} Then", " ".repeat(i + 1), i);
}
let _ = writeln!(source, "{}y = 1", " ".repeat(DEPTH + 1));
for i in (0..DEPTH).rev() {
let _ = writeln!(source, "{}End If", " ".repeat(i + 1));
}
let _ = writeln!(source, "End Sub");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for deeply_nested_if_statements (depth={DEPTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("deeply_nested_if_statements_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("deeply_nested_if_statements_failures", failure_messages);
}
#[test]
fn deeply_nested_for_loops() {
const DEPTH: usize = 30;
let mut source = String::from("Sub Test()\n");
for i in 0..DEPTH {
let _ = writeln!(source, "{}For i{i} = 1 To 10", " ".repeat(i + 1));
}
let _ = writeln!(source, "{}x = x + 1", " ".repeat(DEPTH + 1));
for i in (0..DEPTH).rev() {
let _ = writeln!(source, "{}Next i{i}", " ".repeat(i + 1));
}
let _ = writeln!(source, "End Sub");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for deeply_nested_for_loops (depth={DEPTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("deeply_nested_for_loops_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("deeply_nested_for_loops_failures", failure_messages);
}
#[test]
fn deeply_nested_parentheses() {
const DEPTH: usize = 100;
let mut source = String::from("Sub Test()\n result = ");
for _ in 0..DEPTH {
source.push('(');
}
source.push('x');
for _ in 0..DEPTH {
source.push(')');
}
let _ = writeln!(source);
let _ = writeln!(source, "End Sub");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for deeply_nested_parentheses (depth={DEPTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("deeply_nested_parentheses_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("deeply_nested_parentheses_failures", failure_messages);
}
#[test]
fn long_binary_operation_chain() {
const LENGTH: usize = 200;
let mut source = String::from("Sub Test()\n result = ");
for i in 0..LENGTH {
if i > 0 {
source.push_str(" + ");
}
let _ = write!(source, "x{i}");
}
source.push_str("\nEnd Sub\n");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for long_binary_operation_chain (length={LENGTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("long_binary_operation_chain_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("long_binary_operation_chain_failures", failure_messages);
}
#[test]
fn mixed_nested_control_flow() {
let source = r"
Sub Test()
If a Then
For i = 1 To 10
If b Then
While c
Do
If d Then
For j = 1 To 5
Select Case e
Case 1
If f Then
While g
Do While h
If i Then
For k = 1 To 3
x = x + 1
Next k
End If
Loop
Wend
End If
Case 2
x = 2
End Select
Next j
End If
Loop Until j
Wend
End If
Next i
End If
End Sub
";
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
eprintln!("=== Failures for mixed_nested_control_flow ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("mixed_nested_control_flow_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("mixed_nested_control_flow_failures", failure_messages);
}
#[test]
fn complex_nested_boolean_expression() {
let source = r"
Sub Test()
result = ((a And b) Or (c And d)) And _
((e Or f) And (g Or h)) Or _
(((i And j) Or (k And l)) And _
((m Or n) And (o Or p))) And _
((q And r) Or ((s And t) And (u Or v)))
End Sub
";
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
eprintln!("=== Failures for complex_nested_boolean_expression ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("complex_nested_boolean_expression_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!(
"complex_nested_boolean_expression_failures",
failure_messages
);
}
#[test]
fn deeply_nested_select_case() {
const DEPTH: usize = 20;
let mut source = String::from("Sub Test()\n");
for i in 0..DEPTH {
let _ = writeln!(source, "{}Select Case x{i}", " ".repeat(i + 1));
let _ = writeln!(source, "{}Case 1", " ".repeat(i + 2));
}
let _ = writeln!(source, "{}y = 1", " ".repeat(DEPTH + 2));
for i in (0..DEPTH).rev() {
let _ = writeln!(source, "{}End Select", " ".repeat(i + 1));
}
source.push_str("End Sub\n");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for deeply_nested_select_case (depth={DEPTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("deeply_nested_select_case_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("deeply_nested_select_case_failures", failure_messages);
}
#[test]
fn deeply_nested_with_blocks() {
const DEPTH: usize = 25;
let mut source = String::from("Sub Test()\n");
for i in 0..DEPTH {
let _ = writeln!(source, "{}With obj{i}", " ".repeat(i + 1));
}
let _ = writeln!(source, "{}.Property = 1", " ".repeat(DEPTH + 1));
for i in (0..DEPTH).rev() {
let _ = writeln!(source, "{}End With", " ".repeat(i + 1));
}
let _ = writeln!(source, "End Sub");
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", &source).unpack();
eprintln!("=== Failures for deeply_nested_with_blocks (depth={DEPTH}) ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("deeply_nested_with_blocks_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!("deeply_nested_with_blocks_failures", failure_messages);
}
#[test]
fn combined_expression_and_statement_nesting() {
let source = r"
Sub Test()
If ((a + b) * (c + d)) > ((e - f) / (g - h)) Then
For i = (x * y) To ((z + w) * 2)
If (((p And q) Or (r And s)) And ((t Or u) And (v Or w))) Then
result = ((a + (b * (c + (d * e)))) - ((f * (g + h)) / i))
While (x > ((y * z) + (w / 2)))
Do
x = x - ((a + b) * (c + d))
Loop Until (x < ((y + z) / 2))
Wend
End If
Next i
End If
End Sub
";
let (cst_opt, failures) = ConcreteSyntaxTree::from_text("test.bas", source).unpack();
eprintln!("=== Failures for combined_expression_and_statement_nesting ===");
eprintln!("Number of failures: {}", failures.len());
for failure in &failures {
failure.eprint();
}
eprintln!("=== End Failures ===");
let cst = cst_opt.expect("CST should be present even with syntax errors");
let tree = cst.to_serializable();
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("../../snapshots/tests/edge_cases/recursion_limits");
settings.set_prepend_module_to_snapshot(false);
let _guard = settings.bind_to_scope();
insta::assert_yaml_snapshot!("combined_expression_and_statement_nesting_cst", tree);
let failure_messages: Vec<String> = failures.iter().map(|f| format!("{f:?}")).collect();
insta::assert_yaml_snapshot!(
"combined_expression_and_statement_nesting_failures",
failure_messages
);
}