warpdotdev/warp at 714c51f1e2: the project's own tests caught 9 of 37 planted faults, 28 got through, and corral proved 27 of those missing tests by writing a test and running it.
#[cfg(test)]
mod corral_tests {
use super::super::*;
#[test]
fn test_wildcard_substring_matched_indices_bounds_and_values() {
let text = "/src/ui/button.rs";
let pattern = "ui/*.rs";
let result = match_wildcard_pattern(text, pattern).expect("pattern should match text");
let text_char_len = text.chars().count();
for &idx in &result.matched_indices {
assert!(
idx < text_char_len,
"matched index {} must be within text character bounds (length {})",
idx,
text_char_len
);
}
assert_eq!(result.matched_indices, vec![5, 6, 7, 14, 15, 16]);
}
#[test]
fn test_wildcard_indices_within_bounds_for_substring_glob() {
let text = "abcde";
let pattern = "?de";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = text.chars().count();
assert!(!match_result.matched_indices.is_empty());
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text of length {}",
idx,
char_count
);
}
}
#[test]
fn test_wildcard_question_mark_substring_indices_bounds() {
let text = "path/to/test1.rs";
let pattern = "test?.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = text.chars().count();
assert!(!match_result.matched_indices.is_empty());
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text of length {}",
idx,
char_count
);
}
}
#[test]
fn test_wildcard_prefix_star_no_match() {
let result = match_wildcard_pattern("hello/world.rs", "ui/*");
assert!(result.is_none());
let result2 = match_wildcard_pattern("src/controllers/test.rs", "ui/*");
assert!(result2.is_none());
let result3 = match_wildcard_pattern("abc", "xyz/*");
assert!(result3.is_none());
let result_ci = match_wildcard_pattern_case_insensitive("src/controllers/test.rs", "ui/*");
assert!(result_ci.is_none());
}
#[test]
fn test_wildcard_prefix_star_matched_indices_bounds() {
let text = "a";
let pattern = "long_prefix/*";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_none());
}
#[test]
fn test_wildcard_prefix_star_suffix_matched_indices() {
let text = "ui/.rs_extra";
let pattern = "ui/*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![0, 1, 2, 3, 4, 5]);
}
#[test]
fn test_wildcard_pattern_suffix_not_at_end_indices() {
let text = "a/b_c";
let pattern = "a/*b";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
assert_eq!(match_result.matched_indices, vec![0, 1, 2]);
}
#[test]
fn test_complex_wildcard_suffix_no_match() {
assert!(match_wildcard_pattern("src/xyz", "src/*a*b").is_none());
assert!(match_wildcard_pattern("/path/to/file.rs", "to/*x*y").is_none());
assert!(match_wildcard_pattern("prefix_test_file", "prefix_*1?2*").is_none());
}
#[test]
fn test_complex_wildcard_suffix_match_indices_bounds() {
let text = "src/alpha_beta.rs";
let pattern = "src/*a*b*";
let res = match_wildcard_pattern(text, pattern);
assert!(res.is_some());
let match_result = res.unwrap();
let char_count = text.chars().count();
for &idx in &match_result.matched_indices {
assert!(idx < char_count, "Index {} out of bounds for len {}", idx, char_count);
}
}
#[test]
fn test_wildcard_prefix_not_matching_text() {
let result = match_wildcard_pattern("abcdef.rs", "xyz*.rs");
assert!(result.is_none());
let result2 = match_wildcard_pattern("/src/components/button.rs", "views/*.rs");
assert!(result2.is_none());
let result3 = match_wildcard_pattern_case_insensitive("/src/components/button.rs", "views/*.rs");
assert!(result3.is_none());
}
#[test]
fn test_wildcard_substring_matched_indices_accuracy() {
let text = "/src/ui/button.rs";
let pattern = "ui/*.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
// "/src/" occupies indices 0..5, "ui/" starts at index 5
assert!(!match_result.matched_indices.contains(&0));
assert!(!match_result.matched_indices.contains(&1));
assert!(!match_result.matched_indices.contains(&2));
assert!(match_result.matched_indices.contains(&5));
assert!(match_result.matched_indices.contains(&6));
assert!(match_result.matched_indices.contains(&7));
let char_count = text.chars().count();
for &idx in &match_result.matched_indices {
assert!(idx < char_count);
}
}
#[test]
fn test_wildcard_suffix_matched_indices_bounds() {
let text = "button.rs";
let pattern = "*.rs";
let result = match_wildcard_pattern(text, pattern).expect("expected match for *.rs");
let char_count = text.chars().count();
assert_eq!(result.matched_indices, vec![6, 7, 8]);
for &idx in &result.matched_indices {
assert!(
idx < char_count,
"index {} out of bounds for char count {}",
idx,
char_count
);
}
}
#[test]
fn test_prefix_star_pattern_negative_match() {
let result = match_wildcard_pattern("components/button.rs", "src/*");
assert!(result.is_none());
let result2 = match_wildcard_pattern("other/path/file.txt", "prefix/*");
assert!(result2.is_none());
}
#[test]
fn test_prefix_pattern_matched_indices_bounds_and_content() {
let text = "src/main.rs";
let pattern = "src/*";
let result = match_wildcard_pattern(text, pattern).expect("pattern should match");
assert_eq!(result.matched_indices, vec![0, 1, 2, 3]);
let char_count = text.chars().count();
for &idx in &result.matched_indices {
assert!(
idx < char_count,
"matched index {} must be within text character bounds {}",
idx,
char_count
);
}
}
#[test]
fn test_wildcard_matched_indices_within_char_bounds() {
let text = "🦀.rs";
let pattern = "????.rs";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = text.chars().count();
assert_eq!(match_result.matched_indices.len(), char_count);
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is outside character bounds 0..{}",
idx,
char_count
);
}
}
#[test]
fn test_multibyte_fallback_matched_indices_bounds() {
let text = "東";
let pattern = "???";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
let char_count = text.chars().count();
assert_eq!(match_result.matched_indices.len(), char_count);
for &idx in &match_result.matched_indices {
assert!(
idx < char_count,
"matched index {} is outside character bounds 0..{}",
idx,
char_count
);
}
}
#[test]
fn test_prefix_star_matched_indices_not_at_start() {
let text = "/src/ui/button.rs";
let pattern = "ui/*";
let result = match_wildcard_pattern(text, pattern).expect("pattern ui/* should match /src/ui/button.rs");
assert_eq!(result.matched_indices, vec![5, 6, 7]);
}
#[test]
fn test_prefix_star_pattern_substring_indices() {
let text = "path/to/src/main.rs";
let pattern = "src/*";
let result = match_wildcard_pattern(text, pattern).expect("pattern src/* should match path/to/src/main.rs");
assert_eq!(result.matched_indices, vec![8, 9, 10, 11]);
}
#[test]
fn test_wildcard_suffix_not_at_end_indices_and_score() {
let text = "file.rs.txt";
let pattern = "*.rs";
let result = match_wildcard_pattern(text, pattern).expect("should match partially");
assert_eq!(result.score, 800);
assert_eq!(result.matched_indices, vec![4, 5, 6]);
let text_chars: Vec<char> = text.chars().collect();
let matched_str: String = result
.matched_indices
.iter()
.map(|&idx| text_chars[idx])
.collect();
assert_eq!(matched_str, ".rs");
}
#[test]
fn test_wildcard_pattern_remaining_chars_after_star_must_not_match_exhausted_text() {
assert!(match_wildcard_pattern("foo", "foo*bar").is_none());
assert!(match_wildcard_pattern("test", "test*extra").is_none());
assert!(match_wildcard_pattern("hello", "hello*world").is_none());
}
#[test]
fn test_wildcard_pattern_matched_indices_within_bounds() {
let test_cases = [
("button.rs", "*.rs"),
("/src/ui/button.rs", "ui/*"),
("component.tsx", "*.t"),
("/src/components/button.rs", "src/*"),
("test1.rs", "test?.rs"),
];
for (text, pattern) in test_cases {
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some(), "Expected match for {} with {}", text, pattern);
let res = result.unwrap();
let char_count = text.chars().count();
for &idx in &res.matched_indices {
assert!(
idx < char_count,
"Matched index {} is outside character count {} of {:?}",
idx,
char_count,
text
);
}
}
}
#[test]
fn test_glob_match_chars_star_matches_zero_characters() {
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_recursive_zero_length_star() {
let text: Vec<char> = "file.rs".chars().collect();
let pattern: Vec<char> = "file*.rs".chars().collect();
assert!(is_glob_match_chars_recursive(&text, &pattern, 0, 0));
}
#[test]
fn test_glob_match_chars_consecutive_stars_and_empty() {
let text: Vec<char> = "foo".chars().collect();
let pattern: Vec<char> = "foo*".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
}
#[test]
fn test_glob_match_chars_star_matches_single_char() {
let text: Vec<char> = "acxb".chars().collect();
let pattern: Vec<char> = "a?*b".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
}
#[test]
fn test_wildcard_pattern_substring_star_single_char_in_bounds() {
let text = "dir/acxb";
let pattern = "a?*b";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
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_wildcard_pattern_multibyte_star_single_char_in_bounds() {
let text = "path/a🦀xb";
let pattern = "a?*b";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let match_result = result.unwrap();
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_question_mark_char_matching() {
let result = match_wildcard_pattern("hello_world", "w?rld");
assert!(result.is_some());
let res = result.unwrap();
assert!(res.matched_indices.iter().all(|&idx| idx < "hello_world".chars().count()));
let no_match = match_wildcard_pattern("hello_wrld", "w?rld");
assert!(no_match.is_none());
let file_result = match_wildcard_pattern("file.rs", "file.r?");
assert!(file_result.is_some());
let file_res = file_result.unwrap();
assert!(file_res.matched_indices.iter().all(|&idx| idx < "file.rs".chars().count()));
let file_no_match = match_wildcard_pattern("file.r", "file.r?");
assert!(file_no_match.is_none());
}
#[test]
fn test_is_glob_match_chars_question_mark() {
let text: Vec<char> = "world".chars().collect();
let pat: Vec<char> = "w?rld".chars().collect();
assert!(is_glob_match_chars(&text, &pat));
let short_text: Vec<char> = "wrld".chars().collect();
assert!(!is_glob_match_chars(&short_text, &pat));
}
#[test]
fn test_wildcard_no_match_pattern_with_trailing_chars_and_star() {
assert!(!is_glob_match("", "*x*"));
assert!(match_wildcard_pattern("", "*x*").is_none());
assert!(match_wildcard_pattern("hello", "hello*world*").is_none());
assert!(match_wildcard_pattern("foo", "foo*bar*baz").is_none());
assert!(match_wildcard_pattern("button.rs", "button.rs*extra*").is_none());
}
#[test]
fn test_wildcard_glob_match_zero_length_star() {
assert!(is_glob_match("foobar", "foo*bar"));
assert!(is_glob_match("a", "*a"));
assert!(is_glob_match("abc", "*a*b*c*"));
assert!(is_glob_match("button.rs", "*button.rs*"));
assert!(is_glob_match("src/lib.rs", "*src*/*lib.rs*"));
}
#[test]
fn test_wildcard_question_mark_must_consume_character() {
assert!(!is_glob_match("ab", "a?b"));
assert!(!is_glob_match("test.rs", "test?.rs"));
assert!(match_wildcard_pattern("ab", "a?b").is_none());
assert!(match_wildcard_pattern("test.rs", "test?.rs").is_none());
// Verify that single-character substitutions do match
assert!(is_glob_match("axb", "a?b"));
assert!(is_glob_match("test1.rs", "test?.rs"));
assert!(match_wildcard_pattern("axb", "a?b").is_some());
assert!(match_wildcard_pattern("test1.rs", "test?.rs").is_some());
}
#[test]
fn test_is_glob_match_case_insensitivity() {
assert!(is_glob_match("button.rs", "*.RS"));
assert!(is_glob_match("BUTTON.RS", "*.rs"));
assert!(is_glob_match("file_NAME.txt", "*_name.*"));
}
#[test]
fn test_is_glob_match_recursive_ascii_case_insensitivity() {
assert!(is_glob_match_recursive(b"abc", b"ABC", 0, 0));
assert!(is_glob_match_recursive(b"HELLO", b"hello", 0, 0));
assert!(is_glob_match_recursive(b"Test.Txt", b"test.txt", 0, 0));
assert!(!is_glob_match_recursive(b"Test.Txt", b"other.txt", 0, 0));
}
#[test]
fn test_glob_match_star_single_char() {
assert!(is_glob_match("axb", "a*b"));
assert!(is_glob_match("a", "*"));
assert!(is_glob_match("dir/a/file", "dir/*/file"));
}
#[test]
fn test_glob_match_recursive_star_single_char() {
assert!(is_glob_match_recursive(b"axb", b"a*b", 0, 0));
assert!(is_glob_match_recursive(b"a", b"*", 0, 0));
assert!(is_glob_match_recursive(b"foo_x_bar", b"foo_*_bar", 0, 0));
}
#[test]
fn test_partial_suffix_matched_indices_exact_range() {
let result = match_wildcard_pattern("button.rs", "*.r").expect("should match partial suffix");
assert_eq!(result.matched_indices, vec![6, 7]);
let result_tsx = match_wildcard_pattern("component.tsx", "*.t").expect("should match partial suffix");
assert_eq!(result_tsx.matched_indices, vec![9, 10]);
}
#[test]
fn test_wildcard_pattern_suffix_not_matched_when_shorter() {
assert!(match_wildcard_pattern("file.r", "*.rs").is_none());
assert!(match_wildcard_pattern("test.", "*.js").is_none());
assert!(match_wildcard_pattern("button.r", "*.rs").is_none());
assert!(match_wildcard_pattern("/src/ui/button.r", "ui/*.rs").is_none());
}
#[test]
fn test_case_insensitive_indices_within_bounds() {
let text = "Button.RS";
let pattern = "*.rs";
let result = match_wildcard_pattern_case_insensitive(text, pattern)
.expect("expected match for case-insensitive wildcard");
let char_count = text.chars().count();
assert_eq!(result.matched_indices, vec![6, 7, 8]);
for &idx in &result.matched_indices {
assert!(
idx < char_count,
"matched index {} is out of bounds for text length {}",
idx,
char_count
);
}
}
#[test]
fn test_case_insensitive_prefix_indices_within_bounds() {
let text = "ABC";
let pattern = "a*";
let result = match_wildcard_pattern_case_insensitive(text, pattern)
.expect("expected match for prefix wildcard");
let char_count = text.chars().count();
assert_eq!(result.matched_indices, vec![0]);
assert!(
result.matched_indices.iter().all(|&idx| idx < char_count),
"all matched indices must be within character bounds of text"
);
}
#[test]
fn test_corral_no_match_has_empty_indices_and_within_bounds() {
let dummy = FuzzyMatchResult::no_match();
assert_eq!(dummy.score, 0);
assert_eq!(dummy.matched_indices, Vec::<usize>::new());
let text = "test_file.rs";
let result = match_wildcard_pattern(text, "").expect("empty pattern returns no_match");
assert_eq!(result.score, 0);
assert!(result.matched_indices.is_empty());
for &idx in &result.matched_indices {
assert!(idx < text.chars().count());
}
}
#[test]
fn test_find_glob_match_end_boundary() {
let text: Vec<char> = "button.rs".chars().collect();
let pattern: Vec<char> = "button.*".chars().collect();
let end_idx = find_glob_match_end(&text, &pattern, 0);
assert_eq!(end_idx, Some(text.len()));
}
#[test]
fn test_is_glob_match_chars_parameter_order() {
let text: Vec<char> = "file1.txt".chars().collect();
let pattern: Vec<char> = "file?.txt".chars().collect();
assert!(is_glob_match_chars(&text, &pattern));
}
#[test]
fn test_substring_wildcard_question_mark_in_path() {
let text = "/path/to/file1.txt";
let pattern = "file?.txt";
let result = match_wildcard_pattern(text, pattern);
assert!(result.is_some());
let res = result.unwrap();
let text_len = text.chars().count();
assert!(!res.matched_indices.is_empty());
assert!(res.matched_indices.iter().all(|&idx| idx < text_len));
}
}
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.
s6/m1 · line 68 proven
- matched_indices: vec![], + matched_indices: vec![usize::MAX],
s1/m8 · line 226 proven
- if text.ends_with(suffix) {
+ if text.contains(suffix) {s1/m1 · line 230 proven
- 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/m7 · line 250 proven
- if text.starts_with(prefix) {
+ if text.contains(prefix) {s1/m2 · line 254 proven
- if text.starts_with(prefix) {
+ if !text.starts_with(prefix) {s1/m3 · line 255 proven
- let matched_indices: Vec<usize> = (0..prefix_char_count).collect(); + let matched_indices: Vec<usize> = (0..=text.chars().count()).collect();
s1/m4 · line 277 proven
- let matched_indices: Vec<usize> = (0..text.chars().count()).collect(); + let matched_indices: Vec<usize> = (0..=text.chars().count()).collect();
s4/m3 · line 328 proven
- if remaining_text.len() >= partial_chars.len() {
+ if remaining_text.len() > 0 {s4/m1 · line 337 proven
- (start_pos..start_pos + partial_chars.len()).collect(); + (start_pos..=start_pos + partial_chars.len()).collect();
s0/m8 · line 407 proven
- if let Some(prefix_start) = text.find(prefix) {
+ if let Some(prefix_start) = Some(0) {s0/m4 · line 420 proven
- if remaining_text.ends_with(suffix_part) {
+ if remaining_text.starts_with(suffix_part) {s0/m6 · line 437 proven
- if is_glob_match(remaining_text, suffix_pattern) {
+ if !is_glob_match(remaining_text, suffix_pattern) {s0/m1 · line 457 proven
- combined_indices.push(remaining_start_char + idx); + combined_indices.push(remaining_start_char + idx + 1);
s0/m3 · line 468 proven
- if let Some(start_pos) = text.find(prefix) {
+ if let Some(start_pos) = Some(0) {s0/m2 · line 495 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() + 1).collect();
s6/m3 · line 520 proven
- Some(text_chars.len()) + Some(text_chars.len() + 1)
s7/m3 · line 528 proven
- is_glob_match_chars_recursive(text, pattern, 0, 0) + is_glob_match_chars_recursive(pattern, text, 0, 0)
s2/m1 · line 543 proven
- return pattern[pattern_idx..].iter().all(|&c| c == '*'); + return pattern[pattern_idx..].iter().any(|&c| c == '*');
s2/m2 · line 550 proven
- if is_glob_match_chars_recursive(text, pattern, text_idx, pattern_idx + 1) {
+ if false {s2/m3 · line 555 proven
- for i in text_idx..text.len() {
+ for i in (text_idx + 1)..text.len() {s2/m4 · 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 pattern[pattern_idx..].iter().any(|&c| c == b'*');
s3/m2 · line 596 proven
- // Try matching zero characters (skip the *)
- if is_glob_match_recursive(text, pattern, text_idx, pattern_idx + 1) {
- return true;
- }s3/m5 · line 601 proven
- for i in text_idx..text.len() {
+ for i in (text_idx + 1)..text.len() {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)
s3/m4 · line 613 proven
- if text[text_idx].eq_ignore_ascii_case(&c) {
+ if text[text_idx] == c {s5/m3 · line 663 proven
- .retain(|&idx| idx < text.chars().count()); + .push(text.chars().count());
s0/m5 · line 477 unproven
- (start_char_idx..start_char_idx + prefix_char_count).collect(); + (start_char_idx..text.chars().count() + 1).collect();