1use crate::{
9 errors::TestFilterBuilderError,
10 list::RustTestArtifact,
11 partition::{Partitioner, PartitionerBuilder},
12};
13use aho_corasick::AhoCorasick;
14use nextest_filtering::{EvalContext, Filterset, TestQuery};
15use nextest_metadata::{FilterMatch, MismatchReason};
16use std::{collections::HashSet, fmt, mem};
17
18#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
20pub enum RunIgnored {
21 #[default]
25 Default,
26
27 Only,
29
30 All,
32}
33
34#[derive(Clone, Copy, Debug)]
36pub enum FilterBound {
37 DefaultSet,
39
40 All,
42}
43
44#[derive(Clone, Debug, Eq, PartialEq)]
46pub struct TestFilterBuilder {
47 run_ignored: RunIgnored,
48 partitioner_builder: Option<PartitionerBuilder>,
49 patterns: ResolvedFilterPatterns,
50 exprs: TestFilterExprs,
51}
52
53#[derive(Clone, Debug, Eq, PartialEq)]
54enum TestFilterExprs {
55 All,
57
58 Sets(Vec<Filterset>),
60}
61
62#[derive(Clone, Debug, Eq, PartialEq)]
64pub enum TestFilterPatterns {
65 SkipOnly {
68 skip_patterns: Vec<String>,
70
71 skip_exact_patterns: HashSet<String>,
73 },
74
75 Patterns {
82 patterns: Vec<String>,
84
85 exact_patterns: HashSet<String>,
87
88 skip_patterns: Vec<String>,
90
91 skip_exact_patterns: HashSet<String>,
93 },
94}
95
96impl Default for TestFilterPatterns {
97 fn default() -> Self {
98 Self::SkipOnly {
99 skip_patterns: Vec::new(),
100 skip_exact_patterns: HashSet::new(),
101 }
102 }
103}
104
105impl TestFilterPatterns {
106 pub fn new(substring_patterns: Vec<String>) -> Self {
111 if substring_patterns.is_empty() {
112 Self::default()
113 } else {
114 Self::Patterns {
115 patterns: substring_patterns,
116 exact_patterns: HashSet::new(),
117 skip_patterns: Vec::new(),
118 skip_exact_patterns: HashSet::new(),
119 }
120 }
121 }
122
123 pub fn add_substring_pattern(&mut self, pattern: String) {
125 match self {
126 Self::SkipOnly {
127 skip_patterns,
128 skip_exact_patterns,
129 } => {
130 *self = Self::Patterns {
131 patterns: vec![pattern],
132 exact_patterns: HashSet::new(),
133 skip_patterns: mem::take(skip_patterns),
134 skip_exact_patterns: mem::take(skip_exact_patterns),
135 };
136 }
137 Self::Patterns { patterns, .. } => {
138 patterns.push(pattern);
139 }
140 }
141 }
142
143 pub fn add_exact_pattern(&mut self, pattern: String) {
145 match self {
146 Self::SkipOnly {
147 skip_patterns,
148 skip_exact_patterns,
149 } => {
150 *self = Self::Patterns {
151 patterns: Vec::new(),
152 exact_patterns: [pattern].into_iter().collect(),
153 skip_patterns: mem::take(skip_patterns),
154 skip_exact_patterns: mem::take(skip_exact_patterns),
155 };
156 }
157 Self::Patterns { exact_patterns, .. } => {
158 exact_patterns.insert(pattern);
159 }
160 }
161 }
162
163 pub fn add_skip_pattern(&mut self, pattern: String) {
165 match self {
166 Self::SkipOnly { skip_patterns, .. } => {
167 skip_patterns.push(pattern);
168 }
169 Self::Patterns { skip_patterns, .. } => {
170 skip_patterns.push(pattern);
171 }
172 }
173 }
174
175 pub fn add_skip_exact_pattern(&mut self, pattern: String) {
177 match self {
178 Self::SkipOnly {
179 skip_exact_patterns,
180 ..
181 } => {
182 skip_exact_patterns.insert(pattern);
183 }
184 Self::Patterns {
185 skip_exact_patterns,
186 ..
187 } => {
188 skip_exact_patterns.insert(pattern);
189 }
190 }
191 }
192
193 fn resolve(self) -> Result<ResolvedFilterPatterns, TestFilterBuilderError> {
194 match self {
195 Self::SkipOnly {
196 mut skip_patterns,
197 skip_exact_patterns,
198 } => {
199 if skip_patterns.is_empty() {
200 Ok(ResolvedFilterPatterns::All)
201 } else {
202 skip_patterns.sort_unstable();
204 let skip_pattern_matcher = Box::new(AhoCorasick::new(&skip_patterns)?);
205 Ok(ResolvedFilterPatterns::SkipOnly {
206 skip_patterns,
207 skip_pattern_matcher,
208 skip_exact_patterns,
209 })
210 }
211 }
212 Self::Patterns {
213 mut patterns,
214 exact_patterns,
215 mut skip_patterns,
216 skip_exact_patterns,
217 } => {
218 patterns.sort_unstable();
220 skip_patterns.sort_unstable();
221
222 let pattern_matcher = Box::new(AhoCorasick::new(&patterns)?);
223 let skip_pattern_matcher = Box::new(AhoCorasick::new(&skip_patterns)?);
224
225 Ok(ResolvedFilterPatterns::Patterns {
226 patterns,
227 exact_patterns,
228 skip_patterns,
229 skip_exact_patterns,
230 pattern_matcher,
231 skip_pattern_matcher,
232 })
233 }
234 }
235 }
236}
237
238#[derive(Clone, Debug)]
239enum ResolvedFilterPatterns {
240 All,
245
246 SkipOnly {
248 skip_patterns: Vec<String>,
249 skip_pattern_matcher: Box<AhoCorasick>,
250 skip_exact_patterns: HashSet<String>,
251 },
252
253 Patterns {
255 patterns: Vec<String>,
256 exact_patterns: HashSet<String>,
257 skip_patterns: Vec<String>,
258 skip_exact_patterns: HashSet<String>,
259 pattern_matcher: Box<AhoCorasick>,
260 skip_pattern_matcher: Box<AhoCorasick>,
261 },
262}
263
264impl Default for ResolvedFilterPatterns {
265 fn default() -> Self {
266 Self::All
267 }
268}
269
270impl ResolvedFilterPatterns {
271 fn name_match(&self, test_name: &str) -> FilterNameMatch {
272 match self {
273 Self::All => FilterNameMatch::MatchEmptyPatterns,
274 Self::SkipOnly {
275 skip_patterns: _,
277 skip_exact_patterns,
278 skip_pattern_matcher,
279 } => {
280 if skip_exact_patterns.contains(test_name)
281 || skip_pattern_matcher.is_match(test_name)
282 {
283 FilterNameMatch::Mismatch(MismatchReason::String)
284 } else {
285 FilterNameMatch::MatchWithPatterns
286 }
287 }
288 Self::Patterns {
289 patterns: _,
291 exact_patterns,
292 skip_patterns: _,
294 skip_exact_patterns,
295 pattern_matcher,
296 skip_pattern_matcher,
297 } => {
298 if skip_exact_patterns.contains(test_name)
300 || skip_pattern_matcher.is_match(test_name)
301 {
302 FilterNameMatch::Mismatch(MismatchReason::String)
303 } else if exact_patterns.contains(test_name) || pattern_matcher.is_match(test_name)
304 {
305 FilterNameMatch::MatchWithPatterns
306 } else {
307 FilterNameMatch::Mismatch(MismatchReason::String)
308 }
309 }
310 }
311 }
312}
313
314impl PartialEq for ResolvedFilterPatterns {
315 fn eq(&self, other: &Self) -> bool {
316 match (self, other) {
317 (Self::All, Self::All) => true,
318 (
319 Self::SkipOnly {
320 skip_patterns,
321 skip_exact_patterns,
322 skip_pattern_matcher: _,
324 },
325 Self::SkipOnly {
326 skip_patterns: other_skip_patterns,
327 skip_exact_patterns: other_skip_exact_patterns,
328 skip_pattern_matcher: _,
329 },
330 ) => {
331 skip_patterns == other_skip_patterns
332 && skip_exact_patterns == other_skip_exact_patterns
333 }
334 (
335 Self::Patterns {
336 patterns,
337 exact_patterns,
338 skip_patterns,
339 skip_exact_patterns,
340 pattern_matcher: _,
343 skip_pattern_matcher: _,
344 },
345 Self::Patterns {
346 patterns: other_patterns,
347 exact_patterns: other_exact_patterns,
348 skip_patterns: other_skip_patterns,
349 skip_exact_patterns: other_skip_exact_patterns,
350 pattern_matcher: _,
351 skip_pattern_matcher: _,
352 },
353 ) => {
354 patterns == other_patterns
355 && exact_patterns == other_exact_patterns
356 && skip_patterns == other_skip_patterns
357 && skip_exact_patterns == other_skip_exact_patterns
358 }
359 _ => false,
360 }
361 }
362}
363
364impl Eq for ResolvedFilterPatterns {}
365
366impl TestFilterBuilder {
367 pub fn new(
371 run_ignored: RunIgnored,
372 partitioner_builder: Option<PartitionerBuilder>,
373 patterns: TestFilterPatterns,
374 exprs: Vec<Filterset>,
375 ) -> Result<Self, TestFilterBuilderError> {
376 let patterns = patterns.resolve()?;
377
378 let exprs = if exprs.is_empty() {
379 TestFilterExprs::All
380 } else {
381 TestFilterExprs::Sets(exprs)
382 };
383
384 Ok(Self {
385 run_ignored,
386 partitioner_builder,
387 patterns,
388 exprs,
389 })
390 }
391
392 pub fn default_set(run_ignored: RunIgnored) -> Self {
394 Self {
395 run_ignored,
396 partitioner_builder: None,
397 patterns: ResolvedFilterPatterns::default(),
398 exprs: TestFilterExprs::All,
399 }
400 }
401
402 pub fn filter_binary_match(
408 &self,
409 test_binary: &RustTestArtifact<'_>,
410 ecx: &EvalContext<'_>,
411 bound: FilterBound,
412 ) -> FilterBinaryMatch {
413 let query = test_binary.to_binary_query();
414 let expr_result = match &self.exprs {
415 TestFilterExprs::All => FilterBinaryMatch::Definite,
416 TestFilterExprs::Sets(exprs) => exprs.iter().fold(
417 FilterBinaryMatch::Mismatch {
418 reason: BinaryMismatchReason::Expression,
420 },
421 |acc, expr| {
422 acc.logic_or(FilterBinaryMatch::from_result(
423 expr.matches_binary(&query, ecx),
424 BinaryMismatchReason::Expression,
425 ))
426 },
427 ),
428 };
429
430 if !expr_result.is_match() {
432 return expr_result;
433 }
434
435 match bound {
436 FilterBound::All => expr_result,
437 FilterBound::DefaultSet => expr_result.logic_and(FilterBinaryMatch::from_result(
438 ecx.default_filter.matches_binary(&query, ecx),
439 BinaryMismatchReason::DefaultSet,
440 )),
441 }
442 }
443
444 pub fn build(&self) -> TestFilter<'_> {
448 let partitioner = self
449 .partitioner_builder
450 .as_ref()
451 .map(|partitioner_builder| partitioner_builder.build());
452 TestFilter {
453 builder: self,
454 partitioner,
455 }
456 }
457}
458
459#[derive(Copy, Clone, Debug)]
463pub enum FilterBinaryMatch {
464 Definite,
466
467 Possible,
469
470 Mismatch {
472 reason: BinaryMismatchReason,
474 },
475}
476
477impl FilterBinaryMatch {
478 fn from_result(result: Option<bool>, reason: BinaryMismatchReason) -> Self {
479 match result {
480 Some(true) => Self::Definite,
481 None => Self::Possible,
482 Some(false) => Self::Mismatch { reason },
483 }
484 }
485
486 fn is_match(self) -> bool {
487 match self {
488 Self::Definite | Self::Possible => true,
489 Self::Mismatch { .. } => false,
490 }
491 }
492
493 fn logic_or(self, other: Self) -> Self {
494 match (self, other) {
495 (Self::Definite, _) | (_, Self::Definite) => Self::Definite,
496 (Self::Possible, _) | (_, Self::Possible) => Self::Possible,
497 (Self::Mismatch { reason: r1 }, Self::Mismatch { reason: r2 }) => Self::Mismatch {
498 reason: r1.prefer_expression(r2),
499 },
500 }
501 }
502
503 fn logic_and(self, other: Self) -> Self {
504 match (self, other) {
505 (Self::Definite, Self::Definite) => Self::Definite,
506 (Self::Definite, Self::Possible)
507 | (Self::Possible, Self::Definite)
508 | (Self::Possible, Self::Possible) => Self::Possible,
509 (Self::Mismatch { reason: r1 }, Self::Mismatch { reason: r2 }) => {
510 Self::Mismatch {
513 reason: r1.prefer_expression(r2),
514 }
515 }
516 (Self::Mismatch { reason }, _) | (_, Self::Mismatch { reason }) => {
517 Self::Mismatch { reason }
518 }
519 }
520 }
521}
522
523#[derive(Copy, Clone, Debug, Eq, PartialEq)]
527pub enum BinaryMismatchReason {
528 Expression,
530
531 DefaultSet,
533}
534
535impl BinaryMismatchReason {
536 fn prefer_expression(self, other: Self) -> Self {
537 match (self, other) {
538 (Self::Expression, _) | (_, Self::Expression) => Self::Expression,
539 (Self::DefaultSet, Self::DefaultSet) => Self::DefaultSet,
540 }
541 }
542}
543
544impl fmt::Display for BinaryMismatchReason {
545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 match self {
547 Self::Expression => write!(f, "didn't match filtersets"),
548 Self::DefaultSet => write!(f, "didn't match the default set"),
549 }
550 }
551}
552
553#[derive(Debug)]
555pub struct TestFilter<'builder> {
556 builder: &'builder TestFilterBuilder,
557 partitioner: Option<Box<dyn Partitioner>>,
558}
559
560impl TestFilter<'_> {
561 pub fn filter_match(
563 &mut self,
564 test_binary: &RustTestArtifact<'_>,
565 test_name: &str,
566 ecx: &EvalContext<'_>,
567 bound: FilterBound,
568 ignored: bool,
569 ) -> FilterMatch {
570 self.filter_ignored_mismatch(ignored)
571 .or_else(|| {
572 use FilterNameMatch::*;
593 match (
594 self.filter_name_match(test_name),
595 self.filter_expression_match(test_binary, test_name, ecx, bound),
596 ) {
597 (
599 MatchEmptyPatterns | MatchWithPatterns,
600 MatchEmptyPatterns | MatchWithPatterns,
601 ) => None,
602 (Mismatch(reason), _) | (_, Mismatch(reason)) => {
608 Some(FilterMatch::Mismatch { reason })
609 }
610 }
611 })
612 .or_else(|| self.filter_partition_mismatch(test_name))
616 .unwrap_or(FilterMatch::Matches)
617 }
618
619 fn filter_ignored_mismatch(&self, ignored: bool) -> Option<FilterMatch> {
620 match self.builder.run_ignored {
621 RunIgnored::Only => {
622 if !ignored {
623 return Some(FilterMatch::Mismatch {
624 reason: MismatchReason::Ignored,
625 });
626 }
627 }
628 RunIgnored::Default => {
629 if ignored {
630 return Some(FilterMatch::Mismatch {
631 reason: MismatchReason::Ignored,
632 });
633 }
634 }
635 _ => {}
636 }
637 None
638 }
639
640 fn filter_name_match(&self, test_name: &str) -> FilterNameMatch {
641 self.builder.patterns.name_match(test_name)
642 }
643
644 fn filter_expression_match(
645 &self,
646 test_binary: &RustTestArtifact<'_>,
647 test_name: &str,
648 ecx: &EvalContext<'_>,
649 bound: FilterBound,
650 ) -> FilterNameMatch {
651 let query = TestQuery {
652 binary_query: test_binary.to_binary_query(),
653 test_name,
654 };
655
656 let expr_result = match &self.builder.exprs {
657 TestFilterExprs::All => FilterNameMatch::MatchEmptyPatterns,
658 TestFilterExprs::Sets(exprs) => {
659 if exprs.iter().any(|expr| expr.matches_test(&query, ecx)) {
660 FilterNameMatch::MatchWithPatterns
661 } else {
662 return FilterNameMatch::Mismatch(MismatchReason::Expression);
663 }
664 }
665 };
666
667 match bound {
668 FilterBound::All => expr_result,
669 FilterBound::DefaultSet => {
670 if ecx.default_filter.matches_test(&query, ecx) {
671 expr_result
672 } else {
673 FilterNameMatch::Mismatch(MismatchReason::DefaultFilter)
674 }
675 }
676 }
677 }
678
679 fn filter_partition_mismatch(&mut self, test_name: &str) -> Option<FilterMatch> {
680 let partition_match = match &mut self.partitioner {
681 Some(partitioner) => partitioner.test_matches(test_name),
682 None => true,
683 };
684 if partition_match {
685 None
686 } else {
687 Some(FilterMatch::Mismatch {
688 reason: MismatchReason::Partition,
689 })
690 }
691 }
692}
693
694#[derive(Clone, Debug, Eq, PartialEq)]
695enum FilterNameMatch {
696 MatchEmptyPatterns,
698 MatchWithPatterns,
700 Mismatch(MismatchReason),
702}
703
704impl FilterNameMatch {
705 #[cfg(test)]
706 fn is_match(&self) -> bool {
707 match self {
708 Self::MatchEmptyPatterns | Self::MatchWithPatterns => true,
709 Self::Mismatch(_) => false,
710 }
711 }
712}
713
714#[cfg(test)]
715mod tests {
716 use super::*;
717 use proptest::{collection::vec, prelude::*};
718 use test_strategy::proptest;
719
720 #[proptest(cases = 50)]
721 fn proptest_empty(#[strategy(vec(any::<String>(), 0..16))] test_names: Vec<String>) {
722 let patterns = TestFilterPatterns::default();
723 let test_filter =
724 TestFilterBuilder::new(RunIgnored::Default, None, patterns, Vec::new()).unwrap();
725 let single_filter = test_filter.build();
726 for test_name in test_names {
727 prop_assert!(single_filter.filter_name_match(&test_name).is_match());
728 }
729 }
730
731 #[proptest(cases = 50)]
733 fn proptest_exact(#[strategy(vec(any::<String>(), 0..16))] test_names: Vec<String>) {
734 let patterns = TestFilterPatterns::new(test_names.clone());
736 let test_filter =
737 TestFilterBuilder::new(RunIgnored::Default, None, patterns, Vec::new()).unwrap();
738 let single_filter = test_filter.build();
739 for test_name in &test_names {
740 prop_assert!(single_filter.filter_name_match(test_name).is_match());
741 }
742
743 let mut patterns = TestFilterPatterns::default();
745 for test_name in &test_names {
746 patterns.add_exact_pattern(test_name.clone());
747 }
748 let test_filter =
749 TestFilterBuilder::new(RunIgnored::Default, None, patterns, Vec::new()).unwrap();
750 let single_filter = test_filter.build();
751 for test_name in &test_names {
752 prop_assert!(single_filter.filter_name_match(test_name).is_match());
753 }
754 }
755
756 #[proptest(cases = 50)]
758 fn proptest_substring(
759 #[strategy(vec([any::<String>(); 3], 0..16))] substring_prefix_suffixes: Vec<[String; 3]>,
760 ) {
761 let mut patterns = TestFilterPatterns::default();
762 let mut test_names = Vec::with_capacity(substring_prefix_suffixes.len());
763 for [substring, prefix, suffix] in substring_prefix_suffixes {
764 test_names.push(prefix + &substring + &suffix);
765 patterns.add_substring_pattern(substring);
766 }
767
768 let test_filter =
769 TestFilterBuilder::new(RunIgnored::Default, None, patterns, Vec::new()).unwrap();
770 let single_filter = test_filter.build();
771 for test_name in test_names {
772 prop_assert!(single_filter.filter_name_match(&test_name).is_match());
773 }
774 }
775
776 #[proptest(cases = 50)]
778 fn proptest_no_match(substring: String, prefix: String, suffix: String) {
779 prop_assume!(!substring.is_empty() && !prefix.is_empty() && !suffix.is_empty());
780 let pattern = prefix + &substring + &suffix;
781 let patterns = TestFilterPatterns::new(vec![pattern]);
782 let test_filter =
783 TestFilterBuilder::new(RunIgnored::Default, None, patterns, Vec::new()).unwrap();
784 let single_filter = test_filter.build();
785 prop_assert!(!single_filter.filter_name_match(&substring).is_match());
786 }
787
788 #[test]
789 fn pattern_examples() {
790 let mut patterns = TestFilterPatterns::new(vec!["foo".to_string()]);
791 patterns.add_substring_pattern("bar".to_string());
792 patterns.add_exact_pattern("baz".to_string());
793 patterns.add_skip_pattern("quux".to_string());
794 patterns.add_skip_exact_pattern("quuz".to_string());
795
796 let resolved = patterns.clone().resolve().unwrap();
797
798 assert_eq!(
800 resolved.name_match("foo"),
801 FilterNameMatch::MatchWithPatterns,
802 );
803 assert_eq!(
804 resolved.name_match("1foo2"),
805 FilterNameMatch::MatchWithPatterns,
806 );
807 assert_eq!(
808 resolved.name_match("bar"),
809 FilterNameMatch::MatchWithPatterns,
810 );
811 assert_eq!(
812 resolved.name_match("x_bar_y"),
813 FilterNameMatch::MatchWithPatterns,
814 );
815
816 assert_eq!(
818 resolved.name_match("baz"),
819 FilterNameMatch::MatchWithPatterns,
820 );
821 assert_eq!(
822 resolved.name_match("abazb"),
823 FilterNameMatch::Mismatch(MismatchReason::String),
824 );
825
826 assert_eq!(
828 resolved.name_match("bazfoo"),
829 FilterNameMatch::MatchWithPatterns,
830 );
831
832 assert_eq!(
834 resolved.name_match("quux"),
835 FilterNameMatch::Mismatch(MismatchReason::String),
836 );
837 assert_eq!(
838 resolved.name_match("1quux2"),
839 FilterNameMatch::Mismatch(MismatchReason::String),
840 );
841
842 assert_eq!(
844 resolved.name_match("quuxbar"),
845 FilterNameMatch::Mismatch(MismatchReason::String),
846 );
847
848 assert_eq!(
850 resolved.name_match("quuz"),
851 FilterNameMatch::Mismatch(MismatchReason::String),
852 );
853
854 patterns.add_skip_pattern("baz".to_string());
856 let resolved = patterns.resolve().unwrap();
857 assert_eq!(
858 resolved.name_match("quuxbaz"),
859 FilterNameMatch::Mismatch(MismatchReason::String),
860 );
861 }
862
863 #[test]
864 fn skip_only_pattern_examples() {
865 let mut patterns = TestFilterPatterns::default();
866 patterns.add_skip_pattern("foo".to_string());
867 patterns.add_skip_pattern("bar".to_string());
868 patterns.add_skip_exact_pattern("baz".to_string());
869
870 let resolved = patterns.clone().resolve().unwrap();
871
872 assert_eq!(
874 resolved.name_match("foo"),
875 FilterNameMatch::Mismatch(MismatchReason::String),
876 );
877 assert_eq!(
878 resolved.name_match("1foo2"),
879 FilterNameMatch::Mismatch(MismatchReason::String),
880 );
881 assert_eq!(
882 resolved.name_match("bar"),
883 FilterNameMatch::Mismatch(MismatchReason::String),
884 );
885 assert_eq!(
886 resolved.name_match("x_bar_y"),
887 FilterNameMatch::Mismatch(MismatchReason::String),
888 );
889
890 assert_eq!(
892 resolved.name_match("baz"),
893 FilterNameMatch::Mismatch(MismatchReason::String),
894 );
895 assert_eq!(
896 resolved.name_match("abazb"),
897 FilterNameMatch::MatchWithPatterns,
898 );
899
900 assert_eq!(
902 resolved.name_match("quux"),
903 FilterNameMatch::MatchWithPatterns,
904 );
905 }
906
907 #[test]
908 fn empty_pattern_examples() {
909 let patterns = TestFilterPatterns::default();
910 let resolved = patterns.resolve().unwrap();
911 assert_eq!(resolved, ResolvedFilterPatterns::All);
912
913 assert_eq!(
915 resolved.name_match("foo"),
916 FilterNameMatch::MatchEmptyPatterns,
917 );
918 assert_eq!(
919 resolved.name_match("1foo2"),
920 FilterNameMatch::MatchEmptyPatterns,
921 );
922 assert_eq!(
923 resolved.name_match("bar"),
924 FilterNameMatch::MatchEmptyPatterns,
925 );
926 assert_eq!(
927 resolved.name_match("x_bar_y"),
928 FilterNameMatch::MatchEmptyPatterns,
929 );
930 assert_eq!(
931 resolved.name_match("baz"),
932 FilterNameMatch::MatchEmptyPatterns,
933 );
934 assert_eq!(
935 resolved.name_match("abazb"),
936 FilterNameMatch::MatchEmptyPatterns,
937 );
938 }
939}