1#![allow(clippy::cognitive_complexity)]
2#![allow(clippy::too_many_lines)]
3
4#[test]
5fn simple() {
6 use crate::simple::internal::string_keywords::SplitContext;
7 use crate::simple::{AutocompleteType, Indexable, SearchIndex, SearchType};
8 use kstring::KString;
9 use pretty_assertions::assert_eq;
10
11 #[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
12 struct MyStruct {
13 title: String,
14 year: u16,
15 body: String,
16 }
17
18 impl Indexable for MyStruct {
19 fn strings(&self) -> Vec<String> {
20 vec![self.title.clone(), self.year.to_string(), self.body.clone()]
21 }
22 }
23
24 let my_vec = [
25 MyStruct {
26 title: "Harold Godwinson".to_string(),
27 year: 1066,
28 body: "Last crowned Anglo-Saxon king of England.".to_string(),
29 },
30 MyStruct {
31 title: "Edgar Ætheling".to_string(),
32 year: 1066,
33 body: "Last male member of the royal house of Cerdic of Wessex.".to_string(),
34 },
35 MyStruct {
36 title: "William the Conqueror".to_string(),
37 year: 1066,
38 body: "First Norman monarch of England.".to_string(),
39 },
40 MyStruct {
41 title: "William Rufus".to_string(),
42 year: 1087,
43 body: "Third son of William the Conqueror.".to_string(),
44 },
45 MyStruct {
46 title: "Henry Beauclerc".to_string(),
47 year: 1100,
48 body: "Fourth son of William the Conqueror.".to_string(),
49 }
50 ];
51
52 let mut search_index: SearchIndex<usize> = SearchIndex::default();
53
54 let string_keywords: Vec<KString> = search_index.string_keywords(
57 "All is not lost, the unconquerable will, and study of revenge, \
58 immortal hate, and the courage never to submit or yield.",
59 &SplitContext::Indexing,
60 );
61
62 assert_eq!(
63 string_keywords,
64 [
65 "all",
66 "is",
67 "not",
68 "lost",
69 "unconquerable",
70 "will",
71 "study",
72 "revenge",
73 "immortal",
74 "hate",
75 "courage",
76 "never",
77 "submit",
78 "yield"
79 ]
80 );
81
82 let string_keywords: Vec<KString> = search_index.string_keywords(
85 "He prayeth best, who loveth best All things both great and small; For \
86 the dear God who loveth us, He made and loveth all.",
87 &SplitContext::Searching,
88 );
89
90 assert_eq!(
91 string_keywords,
92 [
93 "he", "prayeth", "best", "who", "loveth", "best", "all", "things", "both", "great",
94 "small", "dear", "god", "who", "loveth", "us", "he", "made", "loveth", "all"
95 ]
96 );
97
98 let string_keywords: Vec<KString> = search_index.string_keywords(
102 "Digby was a floccinaucinihilipilificator at heart—which is an \
103 eight-dollar word meaning a joker who does not believe in anything he \
104 can't bite.",
105 &SplitContext::Indexing,
106 );
107
108 assert_eq!(
109 string_keywords,
110 [
111 "digby", "was", "heart", "which", "is", "eight", "dollar", "word", "meaning", "joker",
112 "who", "does", "not", "believe", "anything", "he", "can't", "bite"
113 ]
114 );
115
116 my_vec
117 .iter()
118 .enumerate()
119 .for_each(|(index, element)| search_index.insert(&index, element));
120
121 let search_results = search_index.search("third william");
123 assert_eq!(search_results, vec![&3]);
124
125 let search_results = search_index.search_type(&SearchType::Keyword, "Wessex");
126 assert_eq!(search_results, vec![&1]);
127
128 let search_results = search_index.search_type(&SearchType::Or, "last Wessex");
132 assert_eq!(search_results, vec![&1, &0]);
133
134 let search_results = search_index.search_type(&SearchType::Or, "last England");
135 assert_eq!(search_results, vec![&0, &1, &2]);
136
137 let search_results = search_index.search_type(&SearchType::And, "Conqueror third");
138 assert_eq!(search_results, vec![&3]);
139
140 let search_results = search_index.search_type(&SearchType::Live, "Last m");
141 assert_eq!(search_results, vec![&1]);
142
143 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
145 let search_results = search_index.search_type(&SearchType::Live, "1066 Harry");
146 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
147 assert_eq!(search_results, vec![&0]);
148
149 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Keyword, "E");
150 assert_eq!(
151 autocomplete_options,
152 vec![
153 "edgar".to_string(),
154 "edgar ætheling".to_string(),
155 "england".to_string()
156 ]
157 );
158
159 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Global, "1100 e");
160 assert_eq!(
161 autocomplete_options,
162 vec![
163 "1100 edgar".to_string(),
164 "1100 edgar ætheling".to_string(),
165 "1100 england".to_string()
166 ]
167 );
168
169 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
171 let autocomplete_options =
172 search_index.autocomplete_type(&AutocompleteType::Global, "1100 Englelund");
173 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
174 assert!(autocomplete_options.contains(&"1100 england".to_string()));
175
176 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Context, "1087 W");
180 assert_eq!(
181 autocomplete_options,
182 vec!["1087 william".to_string(), "1087 william rufus".to_string()]
183 );
184
185 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
187 let autocomplete_options =
188 search_index.autocomplete_type(&AutocompleteType::Context, "1087 Willy");
189 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
190 assert_eq!(
191 autocomplete_options,
192 vec!["1087 william".to_string(), "1087 william rufus".to_string()]
193 );
194
195 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Context, "108");
199 assert_eq!(autocomplete_options, vec!["1087".to_string()]);
200
201 #[cfg(feature = "eddie")]
213 let similar_autocompletions = search_index.eddie_global(&[], &"Normy".to_lowercase());
214 #[cfg(feature = "rapidfuzz")]
215 let similar_autocompletions = search_index.rapidfuzz_global(&[], &"Normy".to_lowercase());
216 #[cfg(feature = "strsim")]
217 let similar_autocompletions = search_index.strsim_global(&[], &"Normy".to_lowercase());
218 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
219 let similar_autocompletions_vec: Vec<&KString> = similar_autocompletions
220 .into_iter()
221 .map(|(keyword, _keys)| keyword)
222 .collect();
223 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
224 assert_eq!(similar_autocompletions_vec, vec![&"norman".to_string()]);
225
226 let my_vec: Vec<&str> = vec![
229 "Vopnafjarðarhreppur", "Weapon Fjord Municipality", "Annerveenschekanaal", "Channel through the peat of Annen", "Cadibarrawirracanna", "The stars were dancing", "Newtownmountkennedy", "A new town near Mt. Kennedy", "Cottonshopeburnfoot", "The end of the Cottonshope Burn", "Nyugotszenterzsébet", "Western St. Elizabeth", "Balatonszentgyörgy", "St. George by Balaton", "Kirkjubæjarklaustur", "Church farm monastery", "Jászalsószentgyörgy", "Lower St. George in Jászság", "Krammerjachtensluis", "Lock on the river Krammer of the hunt", ]; let mut search_index: SearchIndex<usize> = SearchIndex::default();
252
253 my_vec
254 .iter()
255 .enumerate()
256 .for_each(|(index, element)| search_index.insert(&index, element));
257
258 let search_results = search_index.search_type(&SearchType::Keyword, "Cottonshope");
260 assert_eq!(search_results, vec![&9]);
261
262 let search_results = search_index.search_type(&SearchType::Or, "George Elizabeth");
264 assert_eq!(search_results, vec![&11, &13, &17]);
265
266 let search_results = search_index.search_type(&SearchType::And, "George Jászság");
268 assert_eq!(search_results, vec![&17]);
269
270 let search_results = search_index.search_type(&SearchType::Live, "Geo");
272 assert_eq!(search_results, vec![&13, &17]);
273
274 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
276 let search_results = search_index.search_type(&SearchType::Live, "rivers");
277 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
278 assert_eq!(search_results, vec![&19]);
279
280 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
282 let search_results = search_index.search_type(&SearchType::Live, "peat of Annan");
283 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
284 assert_eq!(search_results, vec![&3]);
285
286 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Keyword, "Chan");
288 assert_eq!(autocomplete_options, vec!["channel".to_string()]);
289
290 let autocomplete_options = search_index.autocomplete_type(&AutocompleteType::Global, "Lo");
292 assert_eq!(
293 autocomplete_options,
294 vec!["lock".to_string(), "lower".to_string()]
295 );
296
297 let autocomplete_options =
299 search_index.autocomplete_type(&AutocompleteType::Context, "Krammer Lo");
300 assert_eq!(autocomplete_options, vec!["krammer lock".to_string()]);
301
302 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
304 let autocomplete_options =
305 search_index.autocomplete_type(&AutocompleteType::Context, "stars are dancers");
306 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
307 assert_eq!(autocomplete_options, vec!["stars are dancing".to_string()]);
308
309 let mut search_index = crate::simple::SearchIndex::<usize>::default();
311 search_index.insert(&0, &"лол"); search_index.insert(&1, &"lol");
313 search_index.insert(&2, &"lol лол");
314 search_index.insert(&3, &"лол lol");
315 let search_results = search_index.search("лол");
316 assert_eq!(search_results, vec![&0, &2, &3]);
317} #[test]
320fn simple_all() {
321 use crate::simple::SearchIndex;
322 #[cfg(any(feature = "strsim", feature = "eddie", feature = "rapidfuzz"))]
323 use crate::simple::SearchType;
324 #[cfg(any(feature = "strsim", feature = "eddie", feature = "rapidfuzz"))]
325 use pretty_assertions::assert_eq;
326
327 let all_vec: Vec<&str> = vec![
330 "allanite", "allanites", "allantoic", "allantoid", "allantoides", "allantoids", "allantoin", "allantoins", "allantois", "allargando", "allay", "allayed", "allayer", "allayers", "allaying", "allays", "allee", "allees", "allegation", "allegations", "allege", "alleged", "allegedly", "alleger", "allegers", "alleges", "allegiance", "allegiances", "allegiant", "allegiants", "alleging", "allegoric", "allegorical", "allegorically", "allegoricalness", "allegories", "allegorise", "allegorised", "allegorises", "allegorising", "allegorist", "allegorists", "allegorization", "allegorizations", "allegorize", "allegorized", "allegorizer", "allegorizers", "allegorizes", "allegorizing", "allegory", "allegretto", "allegrettos", "allegro", "allegros", "allele", "alleles", "allelic", "allelism", "allelisms", "allelomorph", "allelomorphic", "allelomorphism", "allelomorphisms", "allelomorphs", "allelopathic", "allelopathies", "allelopathy", "alleluia", "alleluias", "allemande", "allemandes", "allergen", "allergenic", "allergenicities", "allergenicity", "allergens", "allergic", "allergies", "allergin", "allergins", "allergist", "allergists", "allergy", "allethrin", "allethrins", "alleviant", "alleviants", "alleviate", "alleviated", "alleviates", "alleviating", "alleviation", "alleviations", "alleviator", "alleviators", "alley", "alleys", "alleyway", "alleyways", "allheal", "allheals", "alliable", "alliaceous", "alliance", "alliances", "allicin", "allicins", "allied", "allies", "alligator", "alligators", "alliterate", "alliterated", "alliterates", "alliterating", "alliteration", "alliterations", "alliterative", "alliteratively", "allium", "alliums", "alloantibodies", "alloantibody", "alloantigen", "alloantigens", "allobar", "allobars", "allocable", "allocatable", "allocate", "allocated", "allocates", "allocating", "allocation", "allocations", "allocator", "allocators", "allocution", "allocutions", "allod", "allodia", "allodial", "allodium", "allods", "allogamies", "allogamous", "allogamy", "allogeneic", "allogenic", "allograft", "allografted", "allografting", "allografts", "allograph", "allographic", "allographs", "allometric", "allometries", "allometry", "allomorph", "allomorphic", "allomorphism", "allomorphisms", "allomorphs", "allonge", "allonges", "allonym", "allonyms", "allopath", "allopathies", "allopaths", "allopathy", "allopatric", "allopatrically", "allopatries", "allopatry", "allophane", "allophanes", "allophone", "allophones", "allophonic", "alloplasm", "alloplasms", "allopolyploid", "allopolyploids", "allopolyploidy", "allopurinol", "allopurinols", "allosaur", "allosaurs", "allosaurus", "allosauruses", "allosteric", "allosterically", "allosteries", "allostery", "allot", "allotetraploid", "allotetraploids", "allotetraploidy", "allotment", "allotments", "allotrope", "allotropes", "allotropic", "allotropies", "allotropy", "allots", "allotted", "allottee", "allottees", "allotter", "allotters", "allotting", "allotype", "allotypes", "allotypic", "allotypically", "allotypies", "allotypy", "allover", "allovers", "allow", "allowable", "allowables", "allowably", "allowance", "allowanced", "allowances", "allowancing", "allowed", "allowedly", "allowing", "allows", "alloxan", "alloxans", "alloy", "alloyed", "alloying", "alloys", "alls", "allseed", "allseeds", "allspice", "allspices", "allude", "alluded", "alludes", "alluding", "allure", "allured", "allurement", "allurements", "allurer", "allurers", "allures", "alluring", "alluringly", "allusion", "allusions", "allusive", "allusively", "allusiveness", "allusivenesses", "alluvia", "alluvial", "alluvials", "alluvion", "alluvions", "alluvium", "alluviums", "ally", "allying", "allyl", "allylic", "allyls", ]; let mut search_index: SearchIndex<usize> = SearchIndex::default();
610
611 all_vec
612 .iter()
613 .enumerate()
614 .for_each(|(index, element)| search_index.insert(&index, element));
615
616 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
618 let search_results = search_index.search_type(&SearchType::Live, "ally");
619 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
620 let search_results: Vec<&str> = search_results.into_iter().map(|key| all_vec[*key]).collect();
621 #[cfg(any(feature = "eddie", feature = "rapidfuzz", feature = "strsim"))]
622 assert_eq!(search_results, vec!["ally", "allying", "allyl", "allylic", "allyls"]);
623} #[test]
626#[cfg(feature = "unicode-normalization")]
627fn unicode_normalization() {
628 use crate::simple::{SearchIndex, SearchType};
629 use pretty_assertions::assert_eq;
630
631 let mut search_index: SearchIndex<usize> = SearchIndex::default();
632
633 search_index.insert(&0, &"file"); search_index.insert(&1, &"file"); search_index.insert(&2, &"flood"); search_index.insert(&3, &"flood"); search_index.insert(&4, &"①②③"); search_index.insert(&5, &"123"); search_index.insert(&6, &"Ω resistor"); search_index.insert(&7, &"Ω resistor"); search_index.insert(&8, &"fullwidth"); search_index.insert(&9, &"fullwidth"); let results = search_index.search_type(&SearchType::Keyword, "file");
647 assert_eq!(results, vec![&0, &1]);
648
649 let results = search_index.search_type(&SearchType::Keyword, "file");
650 assert_eq!(results, vec![&0, &1]);
651
652 let results = search_index.search_type(&SearchType::Keyword, "flood");
653 assert_eq!(results, vec![&2, &3]);
654
655 let results = search_index.search_type(&SearchType::Keyword, "resistor");
657 assert_eq!(results, vec![&6, &7]);
658
659 let results = search_index.search_type(&SearchType::Keyword, "fullwidth");
661 assert_eq!(results, vec![&8, &9]);
662
663 let results = search_index.search_type(&SearchType::Keyword, "fullwidth");
664 assert_eq!(results, vec![&8, &9]);
665}
666
667#[test]
668#[cfg(feature = "unicode-normalization")]
669fn unicode_normalization_case_insensitive() {
670 use crate::simple::{SearchIndex, SearchType};
671 use pretty_assertions::assert_eq;
672
673 let mut search_index: SearchIndex<usize> = SearchIndex::default();
674
675 search_index.insert(&0, &"FILE"); search_index.insert(&1, &"file"); search_index.insert(&2, &"FILE"); search_index.insert(&3, &"file"); let results = search_index.search_type(&SearchType::Keyword, "file");
683 assert_eq!(results, vec![&0, &1, &2, &3]);
684
685 let results = search_index.search_type(&SearchType::Keyword, "FILE");
686 assert_eq!(results, vec![&0, &1, &2, &3]);
687}
688
689#[test]
690#[cfg(feature = "unicode-normalization")]
691fn unicode_normalization_case_sensitive() {
692 use crate::simple::{SearchIndex, SearchIndexBuilder, SearchType};
693 use pretty_assertions::assert_eq;
694
695 let mut search_index: SearchIndex<usize> = SearchIndexBuilder::default()
696 .case_sensitive(true)
697 .build();
698
699 search_index.insert(&0, &"FILE"); search_index.insert(&1, &"file"); search_index.insert(&2, &"FILE"); search_index.insert(&3, &"file"); let results = search_index.search_type(&SearchType::Keyword, "file");
707 assert_eq!(results, vec![&1, &3]);
708
709 let results = search_index.search_type(&SearchType::Keyword, "FILE");
710 assert_eq!(results, vec![&0, &2]);
711}