Skip to content

Commit f84c5e5

Browse files
Add regression test for NuschtOS/search#339 (#103)
1 parent d7a538d commit f84c5e5

4 files changed

Lines changed: 120 additions & 28 deletions

File tree

Cargo.lock

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libixx/src/string_view.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,52 @@ impl Display for StringView<'_, '_> {
3535
impl StringView<'_, '_> {
3636
pub fn matches(&self, search: &[Vec<&[u8]>]) -> Result<bool, IxxError> {
3737
let mut self_parts_start = 0;
38+
// byte offset into self.parts[self_parts_start] to resume from
3839
let mut self_parts_start_str_idx = 0;
40+
// single-part matches leave self_parts_start on the matched label,
41+
// a subsequent multi-part segment needs to start at the next label
42+
let mut prev_was_single_part = false;
3943

4044
for segment in search {
41-
for part in segment {
45+
// for eg: "programs.vim" each dot-component matches a full label exactly
46+
if segment.len() > 1 {
47+
if prev_was_single_part {
48+
self_parts_start += 1;
49+
self_parts_start_str_idx = 0;
50+
51+
prev_was_single_part = false;
52+
}
53+
for part in segment {
54+
if self_parts_start >= self.parts.len() {
55+
return Ok(false);
56+
}
57+
let self_part = self.index.resolve_reference(self.parts[self_parts_start])?;
58+
if !eq_ignore_ascii_case(&self_part.data, part) {
59+
return Ok(false);
60+
}
61+
self_parts_start += 1;
62+
}
63+
} else {
64+
// bare word or trailing wildcard: substring should match across remaining labels
65+
let part = &segment[0];
4266
'outer: {
4367
for (self_part_idx, self_part) in self.parts[self_parts_start..].iter().enumerate() {
4468
let self_part = self.index.resolve_reference(*self_part)?;
4569

4670
if let Some(idx) = ascii_ignore_case_find(&self_part.data[self_parts_start_str_idx..], part) {
4771
self_parts_start += self_part_idx;
48-
if self_part_idx == 0 {
49-
self_parts_start_str_idx += idx;
72+
self_parts_start_str_idx = if self_part_idx == 0 {
73+
self_parts_start_str_idx + idx
5074
} else {
51-
self_parts_start_str_idx = 0;
52-
}
75+
idx
76+
};
5377
break 'outer;
5478
}
5579
self_parts_start_str_idx = 0;
5680
}
5781
return Ok(false);
5882
}
83+
prev_was_single_part = true;
5984
}
6085
}
6186

libixx/src/test/search.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,70 @@ fn test() {
7373

7474
assert_eq!(index.get_idx_by_name(1, "home.enableDebugInfo"), Some(12));
7575
}
76+
77+
#[test]
78+
fn test_exact_search() {
79+
let index = Index::build(
80+
vec![
81+
("programs.neovim.enable", 0),
82+
("programs.nixvim.enable", 0),
83+
("programs.vim.enable", 0),
84+
]
85+
.as_slice(),
86+
);
87+
88+
assert_eq!(
89+
index.search(Some(0), "programs.neovim", 10).unwrap(),
90+
vec![(0, 0, "programs.neovim.enable".to_string())]
91+
);
92+
assert_eq!(
93+
index.search(Some(0), "programs.neovim.enable", 10).unwrap(),
94+
vec![(0, 0, "programs.neovim.enable".to_string())]
95+
);
96+
97+
assert_eq!(
98+
index.search(Some(0), "programs.nixvim", 10).unwrap(),
99+
vec![(1, 0, "programs.nixvim.enable".to_string())]
100+
);
101+
assert_eq!(
102+
index.search(Some(0), "programs.nixvim.enable", 10).unwrap(),
103+
vec![(1, 0, "programs.nixvim.enable".to_string())]
104+
);
105+
106+
assert_eq!(
107+
index.search(Some(0), "programs.vim", 10).unwrap(),
108+
vec![(2, 0, "programs.vim.enable".to_string())]
109+
);
110+
assert_eq!(
111+
index.search(Some(0), "programs.vim.enable", 10).unwrap(),
112+
vec![(2, 0, "programs.vim.enable".to_string())]
113+
);
114+
115+
// regression tests that wildcard matching also works as expected
116+
assert_eq!(
117+
index.search(Some(0), "programs.vim*", 10).unwrap(),
118+
vec![(2, 0, "programs.vim.enable".to_string())]
119+
);
120+
assert_eq!(
121+
index.search(Some(0), "programs.*vim.enable", 10).unwrap(),
122+
vec![(2, 0, "programs.vim.enable".to_string())]
123+
);
124+
assert_eq!(
125+
index.search(Some(0), "programs.neovim*", 10).unwrap(),
126+
vec![(0, 0, "programs.neovim.enable".to_string())]
127+
);
128+
assert_eq!(
129+
index.search(Some(0), "programs.nixvim*", 10).unwrap(),
130+
vec![(1, 0, "programs.nixvim.enable".to_string())]
131+
);
132+
133+
// regression test that no out of bounds happen
134+
assert_eq!(
135+
index.search(Some(0), "programs.vim.enable.extra", 10).unwrap(),
136+
vec![]
137+
);
138+
assert_eq!(
139+
index.search(Some(0), "programs*vim.enable.extra", 10).unwrap(),
140+
vec![]
141+
);
142+
}

0 commit comments

Comments
 (0)