#[cfg(test)]
mod tests {
#[test]
fn test_simple_continue_in_for_loop() {
let c_code = r#"
for (int i = 0; i < 10; i++) {
if (i == 5) continue;
process(i);
}
"#;
let rust_expected = r#"
for i in 0..10 {
if i == 5 { continue; }
process(i);
}
"#;
assert!(c_code.contains("if (i == 5) continue;"));
assert!(rust_expected.contains("if i == 5 { continue; }"));
}
#[test]
fn test_continue_filter_pattern() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (arr[i] < 0) continue;
sum += arr[i];
}
"#;
let rust_expected = r#"
for i in 0..n {
if arr[i] < 0 { continue; }
sum += arr[i];
}
"#;
assert!(c_code.contains("if (arr[i] < 0) continue;"));
assert!(rust_expected.contains("if arr[i] < 0 { continue; }"));
}
#[test]
fn test_multiple_continue_conditions() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (arr[i] == SKIP_VALUE) continue;
if (arr[i] == 0) continue;
if (arr[i] < MIN_VALUE) continue;
process(arr[i]);
}
"#;
let rust_expected = r#"
for i in 0..n {
if arr[i] == SKIP_VALUE { continue; }
if arr[i] == 0 { continue; }
if arr[i] < MIN_VALUE { continue; }
process(arr[i]);
}
"#;
assert_eq!(c_code.matches("continue;").count(), 3);
assert_eq!(rust_expected.matches("continue;").count(), 3);
}
#[test]
fn test_continue_in_while_loop() {
let c_code = r#"
while (has_data()) {
int val = get_next();
if (is_invalid(val)) continue;
process(val);
}
"#;
let rust_expected = r#"
while has_data() {
let val = get_next();
if is_invalid(val) { continue; }
process(val);
}
"#;
assert!(c_code.contains("if (is_invalid(val)) continue;"));
assert!(rust_expected.contains("if is_invalid(val) { continue; }"));
}
#[test]
fn test_continue_in_infinite_loop() {
let c_code = r#"
while (1) {
int val = read_input();
if (val == 0) continue; // Skip zero
if (val < 0) break; // Exit on negative
process(val);
}
"#;
let rust_expected = r#"
loop {
let val = read_input();
if val == 0 { continue; } // Skip zero
if val < 0 { break; } // Exit on negative
process(val);
}
"#;
assert!(c_code.contains("while (1)"));
assert!(rust_expected.contains("loop {"));
assert!(c_code.contains("continue;"));
assert!(rust_expected.contains("continue;"));
}
#[test]
fn test_continue_complex_condition() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (arr[i] < MIN || arr[i] > MAX) continue;
process(arr[i]);
}
"#;
let rust_expected = r#"
for i in 0..n {
if arr[i] < MIN || arr[i] > MAX { continue; }
process(arr[i]);
}
"#;
assert!(c_code.contains("||"));
assert!(rust_expected.contains("||"));
}
#[test]
fn test_continue_after_partial_processing() {
let c_code = r#"
for (int i = 0; i < n; i++) {
count++;
if (arr[i] == 0) continue;
process(arr[i]);
}
"#;
let rust_expected = r#"
for i in 0..n {
count += 1;
if arr[i] == 0 { continue; }
process(arr[i]);
}
"#;
assert!(c_code.contains("count++;"));
assert!(c_code.contains("continue;"));
assert!(rust_expected.contains("count += 1;"));
}
#[test]
fn test_continue_in_nested_loops_simple() {
let c_code = r#"
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == 0) continue; // Skips to next j
process(matrix[i][j]);
}
}
"#;
let rust_expected = r#"
for i in 0..n {
for j in 0..m {
if matrix[i][j] == 0 { continue; } // Skips to next j
process(matrix[i][j]);
}
}
"#;
assert!(c_code.contains("continue;"));
assert!(rust_expected.contains("continue;"));
assert!(c_code.contains("matrix[i][j]"));
assert!(rust_expected.contains("matrix[i][j]"));
}
#[test]
fn test_labeled_continue() {
let _c_code = r#"
int skip = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (should_skip_outer(i, j)) {
skip = 1;
break;
}
process_inner(i, j);
}
if (skip) { skip = 0; continue; }
process_outer(i);
}
"#;
let rust_idiomatic = r#"
'outer: for i in 0..n {
for j in 0..m {
if should_skip_outer(i, j) {
continue 'outer; // Skip to next i directly
}
process_inner(i, j);
}
process_outer(i);
}
"#;
assert!(rust_idiomatic.contains("'outer:"));
assert!(rust_idiomatic.contains("continue 'outer;"));
}
#[test]
fn test_continue_with_validation() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (!is_valid(arr[i])) continue;
if (arr[i] == NULL) continue;
process(arr[i]);
}
"#;
let rust_expected = r#"
for i in 0..n {
if !is_valid(arr[i]) { continue; }
if arr[i].is_none() { continue; }
process(arr[i]);
}
"#;
assert!(c_code.contains("!is_valid"));
assert!(rust_expected.contains("!is_valid"));
}
#[test]
fn test_continue_skip_whitespace() {
let c_code = r#"
for (int i = 0; i < len; i++) {
char c = str[i];
if (c == ' ') continue;
if (c == '\t') continue;
if (c == '\n') continue;
process_char(c);
}
"#;
let rust_expected = r#"
for i in 0..len {
let c = str[i];
if c == b' ' { continue; }
if c == b'\t' { continue; }
if c == b'\n' { continue; }
process_char(c);
}
"#;
assert_eq!(c_code.matches("continue;").count(), 3);
assert_eq!(rust_expected.matches("continue;").count(), 3);
}
#[test]
fn test_continue_with_counter() {
let c_code = r#"
int valid_count = 0;
for (int i = 0; i < n; i++) {
if (arr[i] < 0) continue;
valid_count++;
process(arr[i]);
}
"#;
let rust_expected = r#"
let mut valid_count = 0;
for i in 0..n {
if arr[i] < 0 { continue; }
valid_count += 1;
process(arr[i]);
}
"#;
assert!(c_code.contains("valid_count++;"));
assert!(rust_expected.contains("valid_count += 1;"));
}
#[test]
fn test_continue_skip_sentinel() {
let c_code = r#"
for (int i = 0; i < len; i++) {
if (arr[i] == SENTINEL) continue;
sum += arr[i];
count++;
}
"#;
let rust_expected = r#"
for i in 0..len {
if arr[i] == SENTINEL { continue; }
sum += arr[i];
count += 1;
}
"#;
assert!(c_code.contains("SENTINEL"));
assert!(rust_expected.contains("SENTINEL"));
}
#[test]
fn test_continue_with_state_check() {
let c_code = r#"
for (int i = 0; i < n; i++) {
if (items[i].state == STATE_INVALID) continue;
if (items[i].state == STATE_PENDING) continue;
process_item(&items[i]);
}
"#;
let rust_expected = r#"
for i in 0..n {
if items[i].state == State::Invalid { continue; }
if items[i].state == State::Pending { continue; }
process_item(&items[i]);
}
"#;
assert!(c_code.contains("STATE_INVALID"));
assert!(rust_expected.contains("State::Invalid"));
}
#[test]
fn test_continue_transformation_rules_summary() {
let c_code = r#"
// Rule 1: Simple continue
for (int i = 0; i < n; i++) {
if (skip) continue;
process(i);
}
// Rule 2: Filter pattern
for (int i = 0; i < n; i++) {
if (arr[i] < 0) continue;
sum += arr[i];
}
// Rule 3: While loop continue
while (has_data()) {
int val = get_next();
if (is_invalid(val)) continue;
process(val);
}
// Rule 4: Multiple continues
for (int i = 0; i < n; i++) {
if (arr[i] == 0) continue;
if (arr[i] < MIN) continue;
process(arr[i]);
}
// Rule 5: Nested loop (C needs flag)
int skip = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (condition) { skip = 1; break; }
}
if (skip) { skip = 0; continue; }
}
"#;
let rust_expected = r#"
// Rule 1: Simple continue (same)
for i in 0..n {
if skip { continue; }
process(i);
}
// Rule 2: Filter pattern (same)
for i in 0..n {
if arr[i] < 0 { continue; }
sum += arr[i];
}
// Rule 3: While loop continue (same)
while has_data() {
let val = get_next();
if is_invalid(val) { continue; }
process(val);
}
// Rule 4: Multiple continues (same)
for i in 0..n {
if arr[i] == 0 { continue; }
if arr[i] < MIN { continue; }
process(arr[i]);
}
// Rule 5: Labeled continue (idiomatic)
'outer: for i in 0..n {
for j in 0..m {
if condition { continue 'outer; }
}
}
"#;
assert!(c_code.contains("continue;"));
assert!(rust_expected.contains("continue;"));
assert!(rust_expected.contains("'outer:"));
assert!(rust_expected.contains("continue 'outer;"));
}
}