warpdotdev/warp at 714c51f1e2: the project's own tests caught 11 of 34 planted faults, 23 got through, and corral proved 22 of those missing tests by writing a test and running it.
#[cfg(test)]
mod corral_tests {
use super::super::*;
#[test]
fn test_substring_glob_match_indices_exact_and_in_bounds() {
let path = "/src/ui/button.rs";
let pattern = "ui/*.rs";
let result = match_wildcard_pattern(path, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = path.chars().count();
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text of length {}",
idx,
char_count
);
}
assert_eq!(match_result.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}
#[test]
fn test_substring_glob_match_partial_suffix_indices() {
let path = "/src/ui/button.rs";
let pattern = "ui/*.r";
let result = match_wildcard_pattern(path, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = path.chars().count();
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text of length {}",
idx,
char_count
);
}
assert_eq!(match_result.matched_indices, vec![5, 6, 7, 14, 15]);
}
#[test]
fn test_substring_glob_matched_indices_exact() {
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]);
let text_chars: Vec<char> = text.chars().collect();
let matched_chars: String = result.matched_indices.iter().map(|&i| text_chars[i]).collect();
assert_eq!(matched_chars, "ui/.rs");
}
#[test]
fn test_substring_glob_partial_suffix_matched_indices() {
let text = "/src/ui/button.rs";
let pattern = "ui/*.r";
let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15]);
let text_chars: Vec<char> = text.chars().collect();
let matched_chars: String = result.matched_indices.iter().map(|&i| text_chars[i]).collect();
assert_eq!(matched_chars, "ui/.r");
}
#[test]
fn test_wildcard_question_mark_indices_complete() {
let text = "button.rs";
let pattern = "butto?.rs";
let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
assert_eq!(
result.matched_indices,
vec![0, 1, 2, 3, 4, 5, 6, 7, 8],
"matched indices must cover the full match up to the end index"
);
let text_sub = "dir/file1.txt";
let pattern_sub = "file?.txt";
let result_sub = match_wildcard_pattern(text_sub, pattern_sub).expect("substring pattern should match");
assert_eq!(
result_sub.matched_indices,
vec![4, 5, 6, 7, 8, 9, 10, 11, 12],
"matched indices must include all matched characters to the end"
);
}
#[test]
fn test_wildcard_pattern_multibyte_question_mark_at_start() {
let result = match_wildcard_pattern("🦀test.rs", "?test.rs");
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![0, 1, 2, 3, 4, 5, 6, 7]);
let result2 = match_wildcard_pattern("日a", "?a");
assert!(result2.is_some());
let match_result2 = result2.unwrap();
assert_eq!(match_result2.matched_indices, vec![0, 1]);
let result3 = match_wildcard_pattern("αβγ", "??γ");
assert!(result3.is_some());
let match_result3 = result3.unwrap();
assert_eq!(match_result3.matched_indices, vec![0, 1, 2]);
}
#[test]
fn test_wildcard_substring_suffix_matched_indices_exact_and_in_bounds() {
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]);
let char_count = text.chars().count();
for &idx in &result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text with {} chars",
idx,
char_count
);
}
}
#[test]
fn test_wildcard_pattern_multiple_prefix_occurrences() {
let text = "dir/test.rs/dir/foo";
let pattern = "dir/*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(
result.is_some(),
"Pattern should match when prefix occurs earlier even if a later occurrence cannot match"
);
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![0, 1, 2, 3, 8, 9, 10]);
}
#[test]
fn test_wildcard_pattern_prefix_indices_use_first_occurrence() {
let text = "src/ui/widget_ui/button.rs";
let pattern = "ui/*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
// Prefix "ui/" starts at index 4 (first occurrence), not index 14
assert!(
match_result.matched_indices.starts_with(&[4, 5, 6]),
"Expected matched indices to start at first 'ui/' occurrence (4, 5, 6), got {:?}",
match_result.matched_indices
);
}
#[test]
fn test_wildcard_exact_suffix_score() {
let text = "main.rs";
let pattern = "*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.score, 1000);
assert_eq!(match_result.matched_indices, vec![4, 5, 6]);
}
#[test]
fn test_wildcard_suffix_not_matched_as_prefix() {
let text = ".rs_script";
let pattern = "*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
// Since text starts with .rs but does not end with .rs,
// this should be treated as a partial match (score 800),
// and matched indices must reflect where .rs actually appears.
assert_eq!(match_result.score, 800);
assert_eq!(match_result.matched_indices, vec![0, 1, 2]);
}
#[test]
fn test_wildcard_pattern_exact_suffix_indices() {
let result = match_wildcard_pattern("button.rs", "*.rs").expect("should match *.rs");
assert_eq!(result.score, 1000);
assert_eq!(result.matched_indices, vec![6, 7, 8]);
let result2 = match_wildcard_pattern("hello/world.txt", "*.txt").expect("should match *.txt");
assert_eq!(result2.score, 1000);
assert_eq!(result2.matched_indices, vec![11, 12, 13, 14]);
}
#[test]
fn test_prefix_star_pattern_at_end_of_text_indices() {
let text = "dir/sub";
let pattern = "sub*";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![4, 5, 6]);
}
#[test]
fn test_prefix_star_directory_pattern_at_end_indices() {
let text = "parent/child/";
let pattern = "child/*";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![7, 8, 9, 10, 11, 12]);
}
#[test]
fn test_complex_fallback_matched_indices_bounds() {
let text = "東";
let pattern = "???";
let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
let char_count = text.chars().count();
assert_eq!(result.matched_indices, vec![0]);
for &idx in &result.matched_indices {
assert!(idx < char_count, "index {} out of bounds for length {}", idx, char_count);
}
}
#[test]
fn test_is_glob_match_chars_consumed_text_trailing_stars() {
let text: Vec<char> = "file1".chars().collect();
let pattern: Vec<char> = "file?*".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
let pattern_multiple_stars: Vec<char> = "file?***".chars().collect();
assert!(is_glob_match_chars(&text, &pattern_multiple_stars));
}
#[test]
fn test_match_wildcard_pattern_question_and_trailing_star_substring() {
let text = "/path/to/file1";
let pattern = "file?*";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert!(match_result.score > 0);
assert!(!match_result.matched_indices.is_empty());
let char_count = text.chars().count();
for &idx in &match_result.matched_indices {
assert!(idx < char_count);
}
}
#[test]
fn test_glob_match_chars_star_matches_zero_chars() {
let text: Vec<char> = "ab".chars().collect();
let pattern: Vec<char> = "a*b".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
}
#[test]
fn test_glob_match_chars_consecutive_stars_empty() {
let text: Vec<char> = "abc".chars().collect();
let pattern: Vec<char> = "a**b*c".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
}
#[test]
fn test_glob_match_chars_recursive_zero_length_star() {
let text: Vec<char> = "hello_world".chars().collect();
let pattern: Vec<char> = "hello_*world".chars().collect();
assert!(is_glob_match_chars_recursive(&text, &pattern, 0, 0));
}
#[test]
fn test_question_mark_requires_character_in_substring_glob() {
// '?' must match and consume exactly one character, never zero characters.
// When the text lacks the character for '?', matching must fail.
assert!(match_wildcard_pattern("dir/abc", "ab?c").is_none());
assert!(match_wildcard_pattern("path/fil.rs", "fil?.rs").is_none());
assert!(match_wildcard_pattern("prefix/ac", "a??c").is_none());
assert!(match_wildcard_pattern("prefix/abc", "a??c").is_none());
// When the required number of characters is present, matching must succeed.
let single_q = match_wildcard_pattern("path/file.rs", "fil?.rs");
assert!(single_q.is_some());
let single_res = single_q.unwrap();
assert!(single_res.score > 0);
assert!(!single_res.matched_indices.is_empty());
for &idx in &single_res.matched_indices {
assert!(idx < "path/file.rs".chars().count());
}
let double_q = match_wildcard_pattern("prefix/abbc", "a??c");
assert!(double_q.is_some());
let double_res = double_q.unwrap();
assert!(double_res.score > 0);
assert!(!double_res.matched_indices.is_empty());
for &idx in &double_res.matched_indices {
assert!(idx < "prefix/abbc".chars().count());
}
}
#[test]
fn test_glob_match_chars_mismatch_with_star() {
let text_chars: Vec<char> = "hello".chars().collect();
let pat_chars: Vec<char> = "*xyz".chars().collect();
assert!(!is_glob_match_chars(&text_chars, &pat_chars));
let pat_chars2: Vec<char> = "h*xyz".chars().collect();
assert!(!is_glob_match_chars(&text_chars, &pat_chars2));
}
#[test]
fn test_wildcard_pattern_question_star_mismatch() {
assert!(match_wildcard_pattern("hello", "?*xyz").is_none());
assert!(match_wildcard_pattern("abcdef", "?*zzz").is_none());
}
#[test]
fn test_is_glob_match_trailing_wildcard() {
assert!(is_glob_match("a", "a*"));
assert!(is_glob_match("hello", "hello*"));
assert!(is_glob_match("hello", "hello**"));
assert!(is_glob_match("test", "t*st*"));
assert!(is_glob_match("abc", "*a*b*c*"));
assert!(!is_glob_match("a", "a*b"));
}
#[test]
fn test_glob_match_star_matching_zero_characters() {
assert!(is_glob_match("abc", "a*b*c"));
assert!(is_glob_match("foo", "*foo"));
assert!(is_glob_match("prefix_suffix", "prefix_*suffix"));
assert!(is_glob_match("test.txt", "test*.txt"));
assert!(is_glob_match("foo/bar/baz", "foo/*bar/*baz"));
assert!(is_glob_match_recursive(b"abc", b"a*b*c", 0, 0));
assert!(is_glob_match_recursive(b"foo", b"*foo", 0, 0));
}
#[test]
fn test_glob_match_question_mark_requires_character() {
assert!(!is_glob_match("ac", "a?c"));
assert!(is_glob_match("abc", "a?c"));
assert!(!is_glob_match("ac", "*a?c"));
assert!(is_glob_match("abc", "*a?c"));
assert!(match_wildcard_pattern("ac", "a?c").is_none());
assert!(match_wildcard_pattern("foo/ac", "foo/*a?c").is_none());
}
#[test]
fn test_glob_match_star_matches_one_or_more_characters() {
assert!(is_glob_match("hello world", "*world"));
assert!(is_glob_match("hello world", "he*ld"));
assert!(is_glob_match("button.rs", "*.rs"));
assert!(is_glob_match("test_file.txt", "test*txt"));
assert!(is_glob_match("path/to/file.rs", "*/*/file.rs"));
assert!(!is_glob_match("hello", "*world"));
}
#[test]
fn test_glob_match_recursive_byte_star_middle() {
assert!(is_glob_match_recursive(b"hello", b"*lo", 0, 0));
assert!(is_glob_match_recursive(b"abcde", b"a*e", 0, 0));
assert!(is_glob_match_recursive(b"abcdef", b"*c*", 0, 0));
}
#[test]
fn test_partial_suffix_matched_indices_exact() {
let text = "button.rs";
let pattern = "*.r";
let result = match_wildcard_pattern(text, pattern).expect("expected pattern to match");
assert_eq!(result.matched_indices, vec![6, 7]);
}
#[test]
fn test_partial_suffix_component_matched_indices() {
let text = "component.tsx";
let pattern = "*.t";
let result = match_wildcard_pattern(text, pattern).expect("expected pattern to match");
assert_eq!(result.matched_indices, vec![9, 10]);
}
#[test]
fn test_ui_star_partial_matched_indices() {
let path = "/src/ui/button.rs";
let result =
match_wildcard_pattern_case_insensitive(path, "ui/*.r").expect("expected pattern to match");
assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15]);
}
#[test]
fn test_partial_suffix_matches_last_occurrence_from_end() {
let text = "file.test.txt";
let pattern = "*.t";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.score, 800);
// Partial suffix matching must search backwards from the end of the text
// to match the final extension (".txt" at indices 9, 10), rather than
// an earlier substring (".test" at indices 4, 5).
assert_eq!(match_result.matched_indices, vec![9, 10]);
}
#[test]
fn test_find_partial_suffix_match_prefers_end_of_text() {
let text = "alpha.beta.batch";
let partial_suffix = ".b";
let result = find_partial_suffix_match(text, partial_suffix);
// ".beta.batch":
// "alpha.beta.batch"
// 0123456789012345
// index 5 is '.b' for ".beta"
// index 10 is '.b' for ".batch"
// Backwards iteration must return the last occurrence [10, 11]
assert_eq!(result, Some(vec![10, 11]));
}
#[test]
fn test_case_insensitive_pattern_with_uppercase_pattern() {
// An exact suffix pattern in uppercase should match with score 1000
// and only index the matched extension, not fall back to partial matching.
let result_suffix = match_wildcard_pattern_case_insensitive("button.rs", "*.RS");
assert!(result_suffix.is_some());
let match_suffix = result_suffix.unwrap();
assert_eq!(match_suffix.score, 1000);
assert_eq!(match_suffix.matched_indices, vec![6, 7, 8]);
// An uppercase prefix pattern should only match the prefix characters,
// not fall back to matching the entire remaining string.
let result_prefix = match_wildcard_pattern_case_insensitive("/src/ui/button.rs", "UI/*");
assert!(result_prefix.is_some());
let match_prefix = result_prefix.unwrap();
assert_eq!(match_prefix.score, 1000);
assert_eq!(match_prefix.matched_indices, vec![5, 6, 7]);
// An uppercase substring glob pattern should match exact prefix and suffix indices.
let result_glob = match_wildcard_pattern_case_insensitive("/src/ui/button.rs", "UI/*.RS");
assert!(result_glob.is_some());
let match_glob = result_glob.unwrap();
assert_eq!(match_glob.score, 1000);
assert_eq!(match_glob.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}
#[test]
fn test_find_glob_match_end_boundary() {
let text: Vec<char> = "foobar".chars().collect();
let matching_pattern: Vec<char> = "foo*".chars().collect();
let non_matching_pattern: Vec<char> = "baz*".chars().collect();
assert_eq!(find_glob_match_end(&text, &matching_pattern, 0), Some(text.len()));
assert_eq!(find_glob_match_end(&text, &non_matching_pattern, 0), None);
}
}
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.
s1/m1 · line 226 proven
- if text.ends_with(suffix) {
+ if text.starts_with(suffix) {s1/m2 · line 230 proven
- let matched_indices: Vec<usize> = (start_char_idx..text_char_count).collect(); + let matched_indices: Vec<usize> = (0..suffix_char_count).collect();
s1/m4 · line 254 proven
- if text.starts_with(prefix) {
+ if text.ends_with(prefix) {s1/m7 · line 277 proven
- let matched_indices: Vec<usize> = (0..text.chars().count()).collect(); + let matched_indices: Vec<usize> = (0..=text.chars().count()).collect();
s4/m2 · line 326 proven
- for start_pos in (0..text_chars.len()).rev() {
+ for start_pos in 0..text_chars.len() {s4/m1 · line 337 proven
- (start_pos..start_pos + partial_chars.len()).collect(); + (start_pos + 1..=start_pos + partial_chars.len()).collect();
s0/m7 · line 407 proven
- if let Some(prefix_start) = text.find(prefix) {
+ if let Some(prefix_start) = text.rfind(prefix) {s0/m6 · line 420 proven
- matched_indices: (start_idx..remaining_char_count).collect(), + matched_indices: (start_idx..remaining_char_count + 1).collect(),
s0/m2 · line 454 proven
- combined_indices.push(remaining_start_char + idx); + combined_indices.push(remaining_start_char + idx + 1);
s0/m1 · line 457 proven
+ combined_indices.push(text.len() + 100);
s0/m5 · line 488 proven
- for start_idx in 0..text_chars.len() {
+ for start_idx in 1..text_chars.len() {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_sub(1).min(text_chars.len())).collect();
s6/m3 · line 520 proven
- Some(text_chars.len())
- } else {
- None
+ None
+ } else {
+ Some(text_chars.len())s2/m1 · line 543 proven
- return pattern[pattern_idx..].iter().all(|&c| c == '*'); + return false;
s2/m2 · line 550 proven
- 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/m4 · line 555 proven
- if is_glob_match_chars_recursive(text, pattern, i + 1, pattern_idx + 1) {
+ if !is_glob_match_chars_recursive(text, pattern, i + 1, pattern_idx + 1) {s2/m3 · line 563 proven
- 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)
s3/m1 · line 589 proven
- return pattern[pattern_idx..].iter().all(|&c| c == b'*'); + return false;
s3/m2 · line 596 proven
- if is_glob_match_recursive(text, pattern, text_idx, pattern_idx + 1) {
- return true;
- }s3/m4 · line 601 proven
- for i in text_idx..text.len() {
- if is_glob_match_recursive(text, pattern, i + 1, pattern_idx + 1) {
- return true;
- }
- }s3/m3 · line 609 proven
- is_glob_match_recursive(text, pattern, text_idx + 1, pattern_idx + 1) + is_glob_match_recursive(text, pattern, text_idx, pattern_idx + 1)
s5/m3 · line 655 proven
- let pattern_lower = pattern.to_lowercase(); + let pattern_lower = pattern.to_string();
s0/m3 · line 472 unproven
- (start_char_idx..start_char_idx + prefix_char_count).collect(); + (start_char_idx + 1..start_char_idx + prefix_char_count).collect();