← the record

Audit ced69a4cf45a

warpdotdev/warp, scoped to crates/fuzzy_match, at 714c51f1e2: the project's own tests caught 5 of 37 planted faults, 32 got through, and corral proved 6 of those missing tests by writing a test and running it.

repo
https://github.com/warpdotdev/warp
scope
crates/fuzzy_match (--path: only files under it were considered)
commit
714c51f1e29f0863b8b7a3e0f460a8acc89b1e0e
corral
v1.0.0-rc.21
substrate
workspace
seats
mutant-generator: gemini-3.8-flash
test-writer: gemini-3.8-flash
tokens
95.0k in, 2.9k out, 8 calls
started
2026-10-14 21:46 UTC
not audited
1 is-test · 1 no-language

crates/fuzzy_match/src/lib.rs

0.14kill rate, 95% interval 0.06–0.28 (n=37, duplicates counted)
5 of 37caught by the project's tests
32got through
6proven missing tests
language
rust
status
needs-review
tests land in
crates/fuzzy_match/src/fuzzy_tests.rs
the tests corral wrote — append to crates/fuzzy_match/src/fuzzy_tests.rs
#[cfg(test)]
mod corral_tests {
use super::super::*;

#[test]
fn test_substring_glob_match_indices_within_bounds() {
    let text = "/src/ui/button.rs";
    let pattern = "ui/*.rs";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match");

    let char_count = text.chars().count();
    for &idx in &result.matched_indices {
        assert!(
            idx < char_count,
            "matched index {idx} must be within bounds 0..{char_count}"
        );
    }
    assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}

#[test]
fn test_substring_glob_match_indices_partial_suffix() {
    let text = "/src/ui/button.rs";
    let pattern = "ui/*.r";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match");

    let char_count = text.chars().count();
    for &idx in &result.matched_indices {
        assert!(
            idx < char_count,
            "matched index {idx} must be within bounds 0..{char_count}"
        );
    }
    assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15]);
}

#[test]
fn test_wildcard_matched_indices_strictly_within_character_bounds() {
    let cases = [
        ("xabc", "a?c"),
        ("hello world", "w?rld"),
        ("abc", "?b?"),
        ("foo_test", "t?st"),
    ];

    for (text, pattern) in cases {
        let result = match_wildcard_pattern(text, pattern)
            .unwrap_or_else(|| panic!("expected match for text='{}', pattern='{}'", text, pattern));
        let char_count = text.chars().count();
        assert!(
            !result.matched_indices.is_empty(),
            "matched_indices should not be empty"
        );
        for &idx in &result.matched_indices {
            assert!(
                idx < char_count,
                "matched index {} is out of bounds for text '{}' (length {})",
                idx,
                text,
                char_count
            );
        }
    }
}

#[test]
fn test_wildcard_matched_indices_within_text_bounds() {
    let text = "hello_world";
    let pattern = "w?rld";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match text");
    assert!(!result.matched_indices.is_empty());
    let char_count = text.chars().count();
    for &idx in &result.matched_indices {
        assert!(
            idx < char_count,
            "matched index {} must be strictly within text bounds (char count: {})",
            idx,
            char_count
        );
    }
}

#[test]
fn test_wildcard_substring_matched_indices_strictly_within_bounds() {
    let test_cases = [
        ("/src/ui/button.rs", "ui/*.rs"),
        ("/src/ui/button.rs", "ui/*.r"),
        ("src/views/modal.tsx", "views/*.tsx"),
    ];

    for (text, pattern) in test_cases {
        let result = match_wildcard_pattern(text, pattern)
            .unwrap_or_else(|| panic!("expected match for text='{}', pattern='{}'", text, pattern));
        let char_count = text.chars().count();

        assert!(
            !result.matched_indices.is_empty(),
            "expected non-empty matched indices for pattern '{}'",
            pattern
        );

        for &idx in &result.matched_indices {
            assert!(
                idx < char_count,
                "matched index {} is out of bounds for text '{}' with character count {}",
                idx,
                text,
                char_count
            );
            assert!(
                text.chars().nth(idx).is_some(),
                "matched index {} does not correspond to a valid character in text '{}'",
                idx,
                text
            );
        }
    }
}

#[test]
fn test_wildcard_substring_matched_indices_exact_content() {
    let text = "/src/ui/button.rs";
    let pattern = "ui/*.rs";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match");

    assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}

#[test]
fn test_wildcard_prefix_suffix_matched_indices_bounds() {
    let text = "/src/ui/button.rs";
    let pattern = "ui/*.rs";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
    let char_count = text.chars().count();

    for &idx in &result.matched_indices {
        assert!(
            idx < char_count,
            "matched index {} is out of bounds (text length is {} chars)",
            idx,
            char_count
        );
    }

    assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}

#[test]
fn test_wildcard_exact_matched_indices_bounds() {
    let text = "dir/file.ext";
    let pattern = "dir/*.ext";
    let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
    let char_count = text.chars().count();

    for &idx in &result.matched_indices {
        assert!(
            idx < char_count,
            "matched index {} is out of bounds (text length is {} chars)",
            idx,
            char_count
        );
    }

    assert_eq!(result.matched_indices, vec![0, 1, 2, 3, 8, 9, 10, 11]);
}

#[test]
fn test_wildcard_pattern_matched_indices_within_text_bounds() {
    let text = "src/ui/test.spec.ts";
    let pattern = "ui/*.*.ts";
    let result = match_wildcard_pattern(text, pattern);
    assert!(result.is_some());

    let match_result = result.unwrap();
    let text_char_count = text.chars().count();
    assert!(!match_result.matched_indices.is_empty());

    for &idx in &match_result.matched_indices {
        assert!(
            idx < text_char_count,
            "matched index {} must be strictly less than text character length {}",
            idx,
            text_char_count
        );
    }
}

#[test]
fn test_wildcard_pattern_complex_suffix_indices_bounds() {
    let text = "ui/button.test.rs";
    let pattern = "ui/*?*.rs";
    let result = match_wildcard_pattern(text, pattern);
    assert!(result.is_some());

    let match_result = result.unwrap();
    let text_char_count = text.chars().count();

    for &idx in &match_result.matched_indices {
        assert!(
            idx < text_char_count,
            "matched index {} must be within character bounds (0..{})",
            idx,
            text_char_count
        );
    }
}
}

The faults that got through

A proven fault was caught by a test corral wrote and ran; an unproven one was not, so it may be a missing test or a fault no test can see.

s0/m6 · line 421 proven

- matched_indices: (start_idx..remaining_char_count).collect(),
+ matched_indices: (start_idx..=remaining_char_count).collect(),

s0/m8 · line 438 proven

- matched_indices: (0..remaining_text.chars().count()).collect(),
+ matched_indices: (0..=remaining_text.chars().count()).collect(),

s0/m5 · line 454 proven

+ combined_indices.push(text.chars().count());

s0/m1 · line 457 proven

- combined_indices.push(remaining_start_char + idx);
+ combined_indices.push(remaining_start_char + idx + 1);

s0/m3 · line 493 proven

- let matched_indices: Vec<usize> = (start_idx..end_idx.min(text_chars.len())).collect();
+ let matched_indices: Vec<usize> = (start_idx..=text_chars.len()).collect();

s0/m4 · line 493 proven

- let matched_indices: Vec<usize> = (start_idx..end_idx.min(text_chars.len())).collect();
+ let matched_indices: Vec<usize> = (start_idx..end_idx.saturating_add(5)).collect();

s6/m1 · line 68 unproven

- matched_indices: vec![],
+ matched_indices: vec![usize::MAX],

s1/m2 · line 230 unproven

- let matched_indices: Vec<usize> = (start_char_idx..text_char_count).collect();
+ let matched_indices: Vec<usize> = (start_char_idx + 1..=text_char_count).collect();

s1/m1 · line 231 unproven

- let matched_indices: Vec<usize> = (start_char_idx..text_char_count).collect();
+ let matched_indices: Vec<usize> = (start_char_idx..=text_char_count).collect();

s1/m3 · line 239 unproven

- if let Some(match_info) = find_partial_suffix_match(text, suffix) {
+ if let Some(mut match_info) = find_partial_suffix_match(text, suffix) {
+     match_info.push(text.chars().count());

s1/m4 · line 255 unproven

- let matched_indices: Vec<usize> = (0..prefix_char_count).collect();
+ let mut matched_indices: Vec<usize> = (0..prefix_char_count).collect();
+ matched_indices.push(text.chars().count());

s1/m5 · line 255 unproven

- let matched_indices: Vec<usize> = (0..prefix_char_count).collect();
+ let matched_indices: Vec<usize> = (prefix_char_count..=text.chars().count()).collect();

s1/m6 · line 268 unproven

- if let Some(match_info) = find_substring_glob_match(text, pattern) {
+ if let Some(mut match_info) = find_substring_glob_match(text, pattern) {
+     match_info.push(text.chars().count());

s1/m7 · line 276 unproven

- let matched_indices: Vec<usize> = (0..text.chars().count()).collect();
+ let matched_indices: Vec<usize> = (0..=text.chars().count()).collect();

s4/m1 · line 337 unproven

- (start_pos..start_pos + partial_chars.len()).collect();
+ (start_pos..=start_pos + partial_chars.len()).collect();

s4/m2 · line 337 unproven

- (start_pos..start_pos + partial_chars.len()).collect();
+ (start_pos + 1..start_pos + partial_chars.len() + 1).collect();

s4/m3 · line 337 unproven

- (start_pos..start_pos + partial_chars.len()).collect();
+ (text_chars.len()..text_chars.len() + partial_chars.len()).collect();

s0/m7 · line 475 unproven

- (start_char_idx..start_char_idx + prefix_char_count).collect();
+ (start_char_idx..start_char_idx + prefix_char_count + text.chars().count()).collect();

s0/m2 · line 477 unproven

- (start_char_idx..start_char_idx + prefix_char_count).collect();
+ (start_char_idx..=text.chars().count()).collect();

s6/m3 · line 513 unproven

- Some(text_chars.len())
+ Some(text_chars.len() + 1)

s2/m1 · line 543 unproven

- return pattern[pattern_idx..].iter().all(|&c| c == '*');
+ return true;

s2/m2 · line 551 unproven

- if is_glob_match_chars_recursive(text, pattern, text_idx, pattern_idx + 1) {
+ if is_glob_match_chars_recursive(text, pattern, text_idx + 1, pattern_idx + 1) {

s2/m3 · line 555 unproven

- if is_glob_match_chars_recursive(text, pattern, i + 1, pattern_idx + 1) {
+ if is_glob_match_chars_recursive(text, pattern, i + 2, pattern_idx + 1) {

s2/m4 · line 563 unproven

- is_glob_match_chars_recursive(text, pattern, text_idx + 1, pattern_idx + 1)
+ is_glob_match_chars_recursive(text, pattern, text_idx, pattern_idx + 1)

s2/m5 · line 568 unproven

- is_glob_match_chars_recursive(text, pattern, text_idx + 1, pattern_idx + 1)
+ is_glob_match_chars_recursive(text, pattern, text_idx + 2, pattern_idx + 1)

s3/m1 · line 589 unproven

- return pattern[pattern_idx..].iter().all(|&c| c == b'*');
+ return true;

s3/m3 · line 597 unproven

- if is_glob_match_recursive(text, pattern, text_idx, pattern_idx + 1) {
+ if is_glob_match_recursive(text, pattern, text_idx + 1, pattern_idx + 1) {

s3/m5 · line 601 unproven

- false
+ true

s3/m2 · line 609 unproven

- is_glob_match_recursive(text, pattern, text_idx + 1, pattern_idx + 1)
+ is_glob_match_recursive(text, pattern, text_idx, pattern_idx + 1)

s3/m4 · line 613 unproven

- if text[text_idx].eq_ignore_ascii_case(&c) {
+ if text[text_idx] == c {

s5/m2 · line 660 unproven

+ result.matched_indices.push(text.chars().count());

s5/m1 · line 663 unproven

- .retain(|&idx| idx < text.chars().count());
+ .retain(|&idx| idx <= text.chars().count());