#[cfg(test)]
mod tests {
#[test]
fn test_simple_break_in_for_loop() {
let c_code = r#"
for (int i = 0; i < 10; i++) {
if (i == 5) break;
process(i);
}
"#;
let rust_expected = r#"
for i in 0..10 {
if i == 5 { break; }
process(i);
}
"#;
assert!(c_code.contains("if (i == 5) break;"));
assert!(rust_expected.contains("if i == 5 { break; }"));
}
#[test]
fn test_break_in_while_loop() {
let c_code = r#"
while (1) {
int val = get_next();
if (val == 0) break;
process(val);
}
"#;
let rust_expected = r#"
loop {
let val = get_next();
if val == 0 { break; }
process(val);
}
"#;
assert!(c_code.contains("while (1)"));
assert!(rust_expected.contains("loop {"));
assert!(rust_expected.contains("break;"));
}
#[test]
fn test_break_in_do_while() {
let c_code = r#"
do {
int val = read_input();
if (val < 0) break;
total += val;
} while (total < 100);
"#;
let rust_expected = r#"
loop {
let val = read_input();
if val < 0 { break; }
total += val;
if !(total < 100) { break; }
}
"#;
assert!(c_code.contains("do {"));
assert!(rust_expected.contains("loop {"));
}
#[test]
fn test_break_in_switch_vs_match() {
let c_code = r#"
switch (state) {
case 0:
initialize();
break;
case 1:
process();
break;
default:
error();
break;
}
"#;
let rust_expected = r#"
match state {
0 => initialize(),
1 => process(),
_ => error(),
}
"#;
assert_eq!(c_code.matches("break;").count(), 3);
assert!(!rust_expected.contains("break"));
}
#[test]
fn test_search_with_break() {
let c_code = r#"
int result = -1;
for (int i = 0; i < len; i++) {
if (arr[i] == target) {
result = i;
break;
}
}
"#;
let rust_expected = r#"
let mut result = -1;
for i in 0..len {
if arr[i] == target {
result = i;
break;
}
}
"#;
assert!(c_code.contains("result = i;"));
assert!(c_code.contains("break;"));
assert!(rust_expected.contains("break;"));
}
#[test]
fn test_nested_loops_with_flag() {
let c_code = r#"
int found = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == target) {
found = 1;
break; // Breaks inner loop only
}
}
if (found) break; // Must break outer loop separately
}
"#;
let rust_flag_style = r#"
let mut found = false;
for i in 0..n {
for j in 0..m {
if matrix[i][j] == target {
found = true;
break; // Breaks inner loop only
}
}
if found { break; } // Break outer loop separately
}
"#;
assert!(c_code.contains("int found = 0;"));
assert_eq!(c_code.matches("break;").count(), 2);
assert!(rust_flag_style.contains("let mut found = false;"));
}
#[test]
fn test_labeled_break_nested_loops() {
let _c_code = r#"
int found = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == target) {
found = 1;
break;
}
}
if (found) break;
}
"#;
let rust_idiomatic = r#"
'outer: for i in 0..n {
for j in 0..m {
if matrix[i][j] == target {
break 'outer; // Breaks outer loop directly
}
}
}
"#;
assert!(rust_idiomatic.contains("'outer:"));
assert!(rust_idiomatic.contains("break 'outer;"));
assert!(!rust_idiomatic.contains("found"));
}
#[test]
fn test_break_on_error() {
let c_code = r#"
while (has_data()) {
int val = read_value();
if (val == ERROR_CODE) break;
if (val < 0) break;
process(val);
}
"#;
let rust_expected = r#"
while has_data() {
let val = read_value();
if val == ERROR_CODE { break; }
if val < 0 { break; }
process(val);
}
"#;
assert_eq!(c_code.matches("break;").count(), 2);
assert_eq!(rust_expected.matches("break;").count(), 2);
}
#[test]
fn test_break_with_limit() {
let c_code = r#"
int count = 0;
while (1) {
process_item();
count++;
if (count >= MAX_ITEMS) break;
}
"#;
let rust_expected = r#"
let mut count = 0;
loop {
process_item();
count += 1;
if count >= MAX_ITEMS { break; }
}
"#;
assert!(c_code.contains("if (count >= MAX_ITEMS) break;"));
assert!(rust_expected.contains("if count >= MAX_ITEMS { break; }"));
}
#[test]
fn test_break_complex_condition() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (i > 10 && arr[i] == 0) break;
process(i);
}
"#;
let rust_expected = r#"
for i in 0..n {
if i > 10 && arr[i] == 0 { break; }
process(i);
}
"#;
assert!(c_code.contains("&&"));
assert!(rust_expected.contains("&&"));
}
#[test]
fn test_multiple_breaks_in_loop() {
let c_code = r#"
while (running) {
if (check_exit_early()) break;
process_step1();
if (should_stop()) break;
process_step2();
}
"#;
let rust_expected = r#"
while running {
if check_exit_early() { break; }
process_step1();
if should_stop() { break; }
process_step2();
}
"#;
assert_eq!(c_code.matches("break;").count(), 2);
assert_eq!(rust_expected.matches("break;").count(), 2);
}
#[test]
fn test_break_in_nested_switch() {
let c_code = r#"
for (int i = 0; i < n; i++) {
switch (arr[i]) {
case 0: handle_zero(); break;
case -1: continue; // Skip to next iteration
default: handle_other(); break;
}
if (done) break; // Break loop, not switch
}
"#;
let rust_expected = r#"
for i in 0..n {
match arr[i] {
0 => handle_zero(),
-1 => continue,
_ => handle_other(),
}
if done { break; }
}
"#;
assert!(c_code.contains("switch"));
assert!(rust_expected.contains("match"));
assert!(c_code.matches("break;").count() > 1);
}
#[test]
fn test_break_with_value() {
let _c_code = r#"
int result = -1;
for (int i = 0; i < n; i++) {
if (arr[i] > 0) {
result = arr[i];
break;
}
}
"#;
let rust_with_value = r#"
let result = 'search: loop {
for i in 0..n {
if arr[i] > 0 {
break 'search arr[i]; // Break with value
}
}
break -1; // Default value
};
"#;
assert!(_c_code.contains("result = arr[i];"));
assert!(rust_with_value.contains("break 'search arr[i];"));
}
#[test]
fn test_break_after_modification() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
arr[i] = NEW_VALUE;
found_index = i;
break;
}
}
"#;
let rust_expected = r#"
for i in 0..n {
if arr[i] == target {
arr[i] = NEW_VALUE;
found_index = i;
break;
}
}
"#;
assert!(c_code.contains("arr[i] = NEW_VALUE;"));
assert!(rust_expected.contains("arr[i] = NEW_VALUE;"));
}
#[test]
fn test_break_transformation_rules_summary() {
let c_code = r#"
// Rule 1: Simple loop break
for (int i = 0; i < n; i++) {
if (condition) break;
}
// Rule 2: While loop break
while (1) {
if (done) break;
}
// Rule 3: Switch case break (required)
switch (x) {
case 1: do_work(); break;
default: break;
}
// Rule 4: Nested loops with flag
int found = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (match) { found = 1; break; }
}
if (found) break;
}
// Rule 5: Search with break
for (int i = 0; i < n; i++) {
if (arr[i] == target) {
result = i;
break;
}
}
"#;
let rust_expected = r#"
// Rule 1: Simple loop break (same)
for i in 0..n {
if condition { break; }
}
// Rule 2: While loop break
loop {
if done { break; }
}
// Rule 3: Match (no break needed)
match x {
1 => do_work(),
_ => {}
}
// Rule 4: Labeled break (idiomatic)
'outer: for i in 0..n {
for j in 0..m {
if match { break 'outer; }
}
}
// Rule 5: Search with break (same)
for i in 0..n {
if arr[i] == target {
result = i;
break;
}
}
"#;
assert!(c_code.contains("break;"));
assert!(rust_expected.contains("break;"));
assert!(rust_expected.contains("'outer:"));
assert!(c_code.contains("switch"));
assert!(rust_expected.contains("match"));
}
}