1use crate::error::*;
6use crate::parser::{self, ParsingError, RequireEscaped, VerboseError};
7use crate::validate::*;
8use anyhow::format_err;
9use buf_read_ext::BufReadExt as _;
10use fidl_fuchsia_diagnostics__common::{
11 self as fdiagnostics, ComponentSelector, LogInterestSelector, PropertySelector, Selector,
12 SelectorArgument, StringSelector, SubtreeSelector, TreeNames, TreeSelector,
13};
14
15use fidl_fuchsia_inspect__common::DEFAULT_TREE_NAME;
16use itertools::Itertools;
17use moniker::{
18 BorrowedChildName, EXTENDED_MONIKER_COMPONENT_MANAGER_STR, ExtendedMoniker, Moniker,
19};
20use std::borrow::{Borrow, Cow};
21use std::fs;
22use std::io::BufReader;
23use std::iter::once;
24use std::path::Path;
25use std::sync::Arc;
26
27#[cfg(fuchsia_api_level_less_than = "27")]
28use fidl_fuchsia_diagnostics::{Interest, Severity};
29#[cfg(fuchsia_api_level_at_least = "27")]
30use fidl_fuchsia_diagnostics_types::{Interest, Severity};
31
32pub const SELECTOR_DELIMITER: char = ':';
35
36const PATH_NODE_DELIMITER: char = '/';
38
39pub const ESCAPE_CHARACTER: char = '\\';
42
43const TAB_CHAR: char = '\t';
44const SPACE_CHAR: char = ' ';
45
46const WILDCARD_SYMBOL_CHAR: char = '*';
48
49const RECURSIVE_WILDCARD_SYMBOL_STR: &str = "**";
50
51const ROOT_SEGMENT: &str = "<root>";
52
53pub fn contains_recursive_glob(component_selector: &ComponentSelector) -> bool {
56 let last_segment = component_selector.moniker_segments.as_ref().unwrap().last().unwrap();
58 string_selector_contains_recursive_glob(last_segment)
59}
60
61fn string_selector_contains_recursive_glob(selector: &StringSelector) -> bool {
62 matches!(
63 selector,
64 StringSelector::StringPattern(pattern) if pattern == RECURSIVE_WILDCARD_SYMBOL_STR
65 )
66}
67
68pub fn take_from_argument<E>(arg: SelectorArgument) -> Result<Selector, Error>
70where
71 E: for<'a> ParsingError<'a>,
72{
73 match arg {
74 SelectorArgument::StructuredSelector(s) => {
75 s.validate()?;
76 Ok(s)
77 }
78 SelectorArgument::RawSelector(r) => parse_selector::<VerboseError>(&r),
79 _ => Err(Error::InvalidSelectorArgument),
80 }
81}
82
83pub fn parse_tree_selector<'a, E>(
85 unparsed_tree_selector: &'a str,
86) -> Result<TreeSelector, ParseError>
87where
88 E: ParsingError<'a>,
89{
90 let result = parser::standalone_tree_selector::<E>(unparsed_tree_selector)?;
91 Ok(result.into())
92}
93
94pub fn parse_component_selector<'a, E>(
96 unparsed_component_selector: &'a str,
97) -> Result<ComponentSelector, ParseError>
98where
99 E: ParsingError<'a>,
100{
101 let result = parser::consuming_component_selector::<E>(
102 unparsed_component_selector,
103 RequireEscaped::COLONS,
104 )?;
105 Ok(result.into())
106}
107
108fn parse_component_selector_no_escaping<'a, E>(
109 unparsed_component_selector: &'a str,
110) -> Result<ComponentSelector, ParseError>
111where
112 E: ParsingError<'a>,
113{
114 let result = parser::consuming_component_selector::<E>(
115 unparsed_component_selector,
116 RequireEscaped::empty(),
117 )?;
118 Ok(result.into())
119}
120
121pub fn parse_log_interest_selector(selector: &str) -> Result<LogInterestSelector, anyhow::Error> {
124 let default_invalid_selector_err = format_err!(
125 "Invalid component interest selector: '{}'. Expecting: '/some/moniker/selector#<log-level>'.",
126 selector
127 );
128 let mut parts = selector.split('#');
129
130 let Some(component) = parts.next() else {
133 return Err(default_invalid_selector_err);
134 };
135 let Some(interest) = parts.next() else {
136 return Err(format_err!(
137 concat!(
138 "Missing <log-level> in selector. Expecting: '{}#<log-level>', ",
139 "such as #DEBUG or #INFO."
140 ),
141 selector
142 ));
143 };
144 if parts.next().is_some() {
145 return Err(default_invalid_selector_err);
146 }
147 let parsed_selector = match parse_component_selector_no_escaping::<VerboseError>(component) {
148 Ok(s) => s,
149 Err(e) => {
150 return Err(format_err!(
151 "Invalid component interest selector: '{}'. Error: {}",
152 selector,
153 e
154 ));
155 }
156 };
157 let Some(min_severity) = parse_severity(interest.to_uppercase().as_ref()) else {
158 return Err(format_err!(
159 concat!(
160 "Invalid <log-level> in selector '{}'. Expecting: a min log level ",
161 "such as #DEBUG or #INFO."
162 ),
163 selector
164 ));
165 };
166 Ok(LogInterestSelector {
167 selector: parsed_selector,
168 interest: Interest { min_severity: Some(min_severity), ..Default::default() },
169 })
170}
171
172pub fn parse_log_interest_selector_or_severity(
175 selector: &str,
176) -> Result<LogInterestSelector, anyhow::Error> {
177 if let Some(min_severity) = parse_severity(selector.to_uppercase().as_ref()) {
178 return Ok(LogInterestSelector {
179 selector: ComponentSelector {
180 moniker_segments: Some(vec![StringSelector::StringPattern("**".into())]),
181 ..Default::default()
182 },
183 interest: Interest { min_severity: Some(min_severity), ..Default::default() },
184 });
185 }
186 parse_log_interest_selector(selector)
187}
188
189fn parse_severity(severity: &str) -> Option<Severity> {
190 match severity {
191 "TRACE" => Some(Severity::Trace),
192 "DEBUG" => Some(Severity::Debug),
193 "INFO" => Some(Severity::Info),
194 "WARN" => Some(Severity::Warn),
195 "ERROR" => Some(Severity::Error),
196 "FATAL" => Some(Severity::Fatal),
197 _ => None,
198 }
199}
200
201pub fn parse_selector<E>(unparsed_selector: &str) -> Result<Selector, Error>
203where
204 for<'a> E: ParsingError<'a>,
205{
206 let result = parser::selector::<E>(unparsed_selector)?;
207 Ok(result.into())
208}
209
210pub fn parse_verbose(unparsed_selector: &str) -> Result<Selector, Error> {
211 parse_selector::<VerboseError>(unparsed_selector)
212}
213
214pub fn parse_selector_file<E>(selector_file: &Path) -> Result<Vec<Selector>, Error>
216where
217 E: for<'a> ParsingError<'a>,
218{
219 let selector_file = fs::File::open(selector_file)?;
220 let mut result = Vec::new();
221 let mut reader = BufReader::new(selector_file);
222 let mut lines = reader.lending_lines();
223 while let Some(line) = lines.next() {
224 let line = line?;
225 if line.is_empty() {
226 continue;
227 }
228 if let Some(selector) = parser::selector_or_comment::<E>(line)? {
229 result.push(selector.into());
230 }
231 }
232 Ok(result)
233}
234
235fn is_special_character(character: char) -> bool {
239 character == ESCAPE_CHARACTER
240 || character == PATH_NODE_DELIMITER
241 || character == SELECTOR_DELIMITER
242 || character == WILDCARD_SYMBOL_CHAR
243 || character == SPACE_CHAR
244 || character == TAB_CHAR
245}
246
247pub fn sanitize_string_for_selectors(node: &str) -> Cow<'_, str> {
252 if node.is_empty() {
253 return Cow::Borrowed(node);
254 }
255
256 let mut token_builder = TokenBuilder::new(node);
257 for (index, node_char) in node.char_indices() {
258 token_builder.maybe_init(index);
259 if is_special_character(node_char) {
260 token_builder.turn_into_string();
261 token_builder.push(ESCAPE_CHARACTER, index);
262 }
263 token_builder.push(node_char, index);
264 }
265
266 token_builder.take()
267}
268
269pub fn sanitize_moniker_for_selectors(moniker: impl AsRef<str>) -> String {
274 moniker.as_ref().replace(":", "\\:")
275}
276
277fn match_moniker_against_component_selector<I, S>(
278 mut moniker_segments: I,
279 component_selector: &ComponentSelector,
280) -> Result<bool, anyhow::Error>
281where
282 I: Iterator<Item = S>,
283 S: AsRef<str>,
284{
285 let selector_segments = match &component_selector.moniker_segments {
286 Some(path_vec) => path_vec,
287 None => return Err(format_err!("Component selectors require moniker segments.")),
288 };
289
290 for (i, selector_segment) in selector_segments.iter().enumerate() {
291 let Some(moniker_segment) = moniker_segments.next() else {
293 return Ok(false);
294 };
295
296 if i == selector_segments.len() - 1
298 && string_selector_contains_recursive_glob(selector_segment)
299 {
300 return Ok(true);
301 }
302
303 if !match_string(selector_segment, moniker_segment.as_ref()) {
304 return Ok(false);
305 }
306 }
307
308 if moniker_segments.next().is_some() {
310 return Ok(false);
311 }
312
313 Ok(true)
314}
315
316fn match_component_and_tree_name<T>(
323 moniker: impl AsRef<[T]>,
324 tree_name: &str,
325 selector: &Selector,
326) -> Result<bool, anyhow::Error>
327where
328 T: AsRef<str>,
329{
330 Ok(match_component_moniker_against_selector(moniker, selector)?
331 && match_tree_name_against_selector(tree_name, selector))
332}
333
334pub fn match_tree_name_against_selector(tree_name: &str, selector: &Selector) -> bool {
339 match selector.tree_names.as_ref() {
340 Some(TreeNames::All(_)) => true,
341
342 Some(TreeNames::Some(filters)) => filters.iter().any(|f| f == tree_name),
343
344 None => tree_name == DEFAULT_TREE_NAME,
345
346 Some(TreeNames::__SourceBreaking { .. }) => false,
347 }
348}
349
350fn match_component_moniker_against_selector<T>(
356 moniker: impl AsRef<[T]>,
357 selector: &Selector,
358) -> Result<bool, anyhow::Error>
359where
360 T: AsRef<str>,
361{
362 selector.validate()?;
363
364 if moniker.as_ref().is_empty() {
365 return Err(format_err!(
366 "Cannot have empty monikers, at least the component name is required."
367 ));
368 }
369
370 let component_selector = selector.component_selector.as_ref().unwrap();
372
373 match_moniker_against_component_selector(moniker.as_ref().iter(), component_selector)
374}
375
376fn match_component_moniker_against_selectors<'a>(
382 moniker: Vec<String>,
383 selectors: impl IntoIterator<Item = &'a Selector>,
384) -> impl Iterator<Item = Result<&'a Selector, anyhow::Error>> {
385 selectors
386 .into_iter()
387 .map(|selector| {
388 selector.validate()?;
389 Ok(selector)
390 })
391 .filter_map(move |selector| -> Option<Result<&'a Selector, anyhow::Error>> {
392 let Ok(selector) = selector else {
393 return Some(selector);
394 };
395 match_component_moniker_against_selector(moniker.as_slice(), selector)
396 .map(|is_match| if is_match { Some(selector) } else { None })
397 .transpose()
398 })
399}
400
401fn match_moniker_against_component_selectors<'a, S, T>(
407 moniker: &[T],
408 selectors: &'a [S],
409) -> Result<Vec<&'a ComponentSelector>, anyhow::Error>
410where
411 S: Borrow<ComponentSelector> + 'a,
412 T: AsRef<str> + std::string::ToString,
413{
414 if moniker.is_empty() {
415 return Err(format_err!(
416 "Cannot have empty monikers, at least the component name is required."
417 ));
418 }
419
420 let component_selectors = selectors
421 .iter()
422 .map(|selector| {
423 let component_selector = selector.borrow();
424 component_selector.validate()?;
425 Ok(component_selector)
426 })
427 .collect::<Result<Vec<&ComponentSelector>, anyhow::Error>>();
428
429 component_selectors?
430 .iter()
431 .filter_map(|selector| {
432 match_moniker_against_component_selector(moniker.iter(), selector)
433 .map(|is_match| if is_match { Some(*selector) } else { None })
434 .transpose()
435 })
436 .collect::<Result<Vec<&ComponentSelector>, anyhow::Error>>()
437}
438
439pub fn matches_selectors(moniker: &ExtendedMoniker, selectors: &[ComponentSelector]) -> bool {
445 match moniker {
446 ExtendedMoniker::ComponentManager => selectors.iter().any(|s| {
447 match_moniker_against_component_selector(
448 once(EXTENDED_MONIKER_COMPONENT_MANAGER_STR),
449 s,
450 )
451 .unwrap()
452 }),
453 ExtendedMoniker::ComponentInstance(moniker) => {
454 if moniker.is_root() {
455 selectors.iter().any(|s| {
456 match_moniker_against_component_selector(once(ROOT_SEGMENT), s).unwrap()
457 })
458 } else {
459 selectors.iter().any(|s| {
460 match_moniker_against_component_selector(moniker.into_iter(), s).unwrap()
461 })
462 }
463 }
464 }
465}
466
467pub struct SelectorDisplayOptions {
470 allow_wrapper_quotes: bool,
471}
472
473impl std::default::Default for SelectorDisplayOptions {
474 fn default() -> Self {
475 Self { allow_wrapper_quotes: true }
476 }
477}
478
479impl SelectorDisplayOptions {
480 pub fn never_wrap_in_quotes() -> Self {
482 Self { allow_wrapper_quotes: false }
483 }
484}
485
486pub fn selector_to_string(
496 selector: &Selector,
497 opts: SelectorDisplayOptions,
498) -> Result<String, anyhow::Error> {
499 fn contains_chars_requiring_wrapper_quotes(segment: &str) -> bool {
500 segment.contains('/') || segment.contains('*')
501 }
502
503 selector.validate()?;
504
505 let component_selector = selector
506 .component_selector
507 .as_ref()
508 .ok_or_else(|| format_err!("component selector missing"))?;
509 let (node_path, maybe_property_selector) = match selector
510 .tree_selector
511 .as_ref()
512 .ok_or_else(|| format_err!("tree selector missing"))?
513 {
514 TreeSelector::SubtreeSelector(SubtreeSelector { node_path, .. }) => (node_path, None),
515 TreeSelector::PropertySelector(PropertySelector {
516 node_path, target_properties, ..
517 }) => (node_path, Some(target_properties)),
518 _ => return Err(format_err!("unknown tree selector type")),
519 };
520
521 let mut needs_to_be_quoted = false;
522 let result = component_selector
523 .moniker_segments
524 .as_ref()
525 .ok_or_else(|| format_err!("moniker segments missing in component selector"))?
526 .iter()
527 .map(|segment| match segment {
528 StringSelector::StringPattern(p) => {
529 needs_to_be_quoted = true;
530 Ok(p)
531 }
532 StringSelector::ExactMatch(s) => {
533 needs_to_be_quoted |= contains_chars_requiring_wrapper_quotes(s);
534 Ok(s)
535 }
536 fdiagnostics::StringSelectorUnknown!() => {
537 Err(format_err!("uknown StringSelector variant"))
538 }
539 })
540 .collect::<Result<Vec<_>, _>>()?
541 .into_iter()
542 .join("/");
543
544 let mut result = sanitize_moniker_for_selectors(&result);
545
546 let mut tree_selector_str = node_path
547 .iter()
548 .map(|segment| {
549 Ok(match segment {
550 StringSelector::StringPattern(p) => {
551 needs_to_be_quoted = true;
552 p.to_string()
553 }
554 StringSelector::ExactMatch(s) => {
555 needs_to_be_quoted |= contains_chars_requiring_wrapper_quotes(s);
556 sanitize_string_for_selectors(s).to_string()
557 }
558 fdiagnostics::StringSelectorUnknown!() => {
559 return Err(format_err!("uknown StringSelector variant"));
560 }
561 })
562 })
563 .collect::<Result<Vec<String>, _>>()?
564 .into_iter()
565 .join("/");
566
567 if let Some(target_property) = maybe_property_selector {
568 tree_selector_str.push(':');
569 tree_selector_str.push_str(&match target_property {
570 StringSelector::StringPattern(p) => {
571 needs_to_be_quoted = true;
572 p.to_string()
573 }
574 StringSelector::ExactMatch(s) => {
575 needs_to_be_quoted |= contains_chars_requiring_wrapper_quotes(s);
576 sanitize_string_for_selectors(s).to_string()
577 }
578 fdiagnostics::StringSelectorUnknown!() => {
579 return Err(format_err!("uknown StringSelector variant"));
580 }
581 });
582 }
583
584 tree_selector_str = match &selector.tree_names {
585 None => tree_selector_str,
586 Some(names) => match names {
587 TreeNames::Some(names) => {
588 let list = names
589 .iter()
590 .filter_map(|name| {
591 if name == DEFAULT_TREE_NAME {
592 return None;
593 }
594
595 for c in name.chars() {
596 if !(c.is_alphanumeric() || c == '-' || c == '_') {
597 return Some(format!(r#"name="{name}""#));
598 }
599 }
600
601 Some(format!("name={name}"))
602 })
603 .join(",");
604
605 if list.is_empty() {
606 tree_selector_str
607 } else {
608 needs_to_be_quoted = true;
609 format!("[{list}]{tree_selector_str}")
610 }
611 }
612 TreeNames::All(_) => {
613 needs_to_be_quoted = true;
614 format!("[...]{tree_selector_str}")
615 }
616 fdiagnostics::TreeNamesUnknown!() => {
617 return Err(format_err!("unknown TreeNames variant"));
618 }
619 },
620 };
621
622 result.push_str(&format!(":{tree_selector_str}"));
623
624 if needs_to_be_quoted && opts.allow_wrapper_quotes {
625 Ok(format!(r#""{result}""#))
626 } else {
627 Ok(result)
628 }
629}
630
631pub fn match_string(selector: &StringSelector, target: impl AsRef<str>) -> bool {
633 match selector {
634 StringSelector::ExactMatch(s) => s == target.as_ref(),
635 StringSelector::StringPattern(pattern) => match_pattern(pattern, target.as_ref()),
636 _ => false,
637 }
638}
639
640fn match_pattern(pattern: &str, target: &str) -> bool {
641 let mut pattern_tokens = vec![];
643 let mut token = TokenBuilder::new(pattern);
644 let mut chars = pattern.char_indices();
645
646 while let Some((index, curr_char)) = chars.next() {
647 token.maybe_init(index);
648
649 match curr_char {
651 '\\' => {
652 match chars.next() {
653 Some((i, c)) => {
654 token.turn_into_string();
655 token.push(c, i);
656 }
657 None => return false,
660 }
661 }
662 '*' => {
663 if !token.is_empty() {
664 pattern_tokens.push(token.take());
665 }
666 token = TokenBuilder::new(pattern);
667 }
668 c => {
669 token.push(c, index);
670 }
671 }
672 }
673
674 if !token.is_empty() {
676 pattern_tokens.push(token.take());
677 }
678
679 if pattern_tokens.is_empty() && !pattern.is_empty() {
681 return true;
682 }
683
684 if !pattern.starts_with('*') && !target.starts_with(pattern_tokens[0].as_ref()) {
687 return false;
688 }
689
690 if !pattern.ends_with('*')
693 && pattern.chars().rev().nth(1) != Some('\\')
694 && !target.ends_with(pattern_tokens[pattern_tokens.len() - 1].as_ref())
695 {
696 return false;
697 }
698
699 let mut cur_string = target;
702 for pattern in pattern_tokens.iter() {
703 match cur_string.find(pattern.as_ref()) {
704 Some(i) => {
705 cur_string = &cur_string[i + pattern.len()..];
706 }
707 None => {
708 return false;
709 }
710 }
711 }
712
713 true
714}
715
716#[derive(Debug)]
719enum TokenBuilder<'a> {
720 Init(&'a str),
721 Slice { string: &'a str, start: usize, end: Option<usize> },
722 String(String),
723}
724
725impl<'a> TokenBuilder<'a> {
726 fn new(string: &'a str) -> Self {
727 Self::Init(string)
728 }
729
730 fn maybe_init(&mut self, start_index: usize) {
731 let Self::Init(s) = self else {
732 return;
733 };
734 *self = Self::Slice { string: s, start: start_index, end: None };
735 }
736
737 fn turn_into_string(&mut self) {
738 if let Self::Slice { string, start, end } = self {
739 if let Some(end) = end {
740 *self = Self::String(string[*start..=*end].to_string());
741 } else {
742 *self = Self::String(String::new());
745 }
746 }
747 }
748
749 fn push(&mut self, c: char, index: usize) {
750 match self {
751 Self::Slice { end, .. } => {
752 *end = Some(index);
753 }
754 Self::String(s) => s.push(c),
755 Self::Init(_) => unreachable!(),
756 }
757 }
758
759 fn take(self) -> Cow<'a, str> {
760 match self {
761 Self::Slice { string, start, end: Some(end) } => Cow::Borrowed(&string[start..=end]),
762 Self::Slice { string, start, end: None } => Cow::Borrowed(&string[start..start]),
763 Self::String(s) => Cow::Owned(s),
764 Self::Init(_) => unreachable!(),
765 }
766 }
767
768 fn is_empty(&self) -> bool {
769 match self {
770 Self::Slice { start, end: Some(end), .. } => start > end,
771 Self::Slice { end: None, .. } => true,
772 Self::String(s) => s.is_empty(),
773 Self::Init(_) => true,
774 }
775 }
776}
777
778pub trait SelectorExt {
779 fn match_against_selectors<'a>(
780 &self,
781 selectors: impl IntoIterator<Item = &'a Selector>,
782 ) -> impl Iterator<Item = Result<&'a Selector, anyhow::Error>>;
783
784 fn match_against_selectors_and_tree_name<'a>(
786 &self,
787 tree_name: &str,
788 selectors: impl IntoIterator<Item = &'a Selector>,
789 ) -> impl Iterator<Item = &'a Selector>;
790
791 fn match_against_component_selectors<'a, S>(
792 &self,
793 selectors: &'a [S],
794 ) -> Result<Vec<&'a ComponentSelector>, anyhow::Error>
795 where
796 S: Borrow<ComponentSelector>;
797
798 fn into_component_selector(self) -> ComponentSelector;
799
800 fn matches_selector(&self, selector: &Selector) -> Result<bool, anyhow::Error>;
801
802 fn matches_component_selector(
803 &self,
804 selector: &ComponentSelector,
805 ) -> Result<bool, anyhow::Error>;
806
807 fn sanitized(&self) -> String;
808}
809
810impl SelectorExt for ExtendedMoniker {
811 fn match_against_selectors<'a>(
812 &self,
813 selectors: impl IntoIterator<Item = &'a Selector>,
814 ) -> impl Iterator<Item = Result<&'a Selector, anyhow::Error>> {
815 let s = match self {
816 ExtendedMoniker::ComponentManager => {
817 vec![EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string()]
818 }
819 ExtendedMoniker::ComponentInstance(moniker) => {
820 SegmentIterator::from(moniker).collect::<Vec<_>>()
821 }
822 };
823
824 match_component_moniker_against_selectors(s, selectors)
825 }
826
827 fn match_against_selectors_and_tree_name<'a>(
828 &self,
829 tree_name: &str,
830 selectors: impl IntoIterator<Item = &'a Selector>,
831 ) -> impl Iterator<Item = &'a Selector> {
832 let m = match self {
833 ExtendedMoniker::ComponentManager => {
834 vec![EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string()]
835 }
836 ExtendedMoniker::ComponentInstance(moniker) => {
837 SegmentIterator::from(moniker).collect::<Vec<_>>()
838 }
839 };
840
841 selectors
842 .into_iter()
843 .filter(move |s| match_component_and_tree_name(&m, tree_name, s).unwrap_or(false))
844 }
845
846 fn match_against_component_selectors<'a, S>(
847 &self,
848 selectors: &'a [S],
849 ) -> Result<Vec<&'a ComponentSelector>, anyhow::Error>
850 where
851 S: Borrow<ComponentSelector>,
852 {
853 match self {
854 ExtendedMoniker::ComponentManager => match_moniker_against_component_selectors(
855 &[EXTENDED_MONIKER_COMPONENT_MANAGER_STR],
856 selectors,
857 ),
858 ExtendedMoniker::ComponentInstance(moniker) => {
859 moniker.match_against_component_selectors(selectors)
860 }
861 }
862 }
863
864 fn matches_selector(&self, selector: &Selector) -> Result<bool, anyhow::Error> {
865 match self {
866 ExtendedMoniker::ComponentManager => match_component_moniker_against_selector(
867 [EXTENDED_MONIKER_COMPONENT_MANAGER_STR],
868 selector,
869 ),
870 ExtendedMoniker::ComponentInstance(moniker) => moniker.matches_selector(selector),
871 }
872 }
873
874 fn matches_component_selector(
875 &self,
876 selector: &ComponentSelector,
877 ) -> Result<bool, anyhow::Error> {
878 match self {
879 ExtendedMoniker::ComponentManager => match_moniker_against_component_selector(
880 [EXTENDED_MONIKER_COMPONENT_MANAGER_STR].into_iter(),
881 selector,
882 ),
883 ExtendedMoniker::ComponentInstance(moniker) => {
884 moniker.matches_component_selector(selector)
885 }
886 }
887 }
888
889 fn sanitized(&self) -> String {
890 match self {
891 ExtendedMoniker::ComponentManager => EXTENDED_MONIKER_COMPONENT_MANAGER_STR.to_string(),
892 ExtendedMoniker::ComponentInstance(moniker) => moniker.sanitized(),
893 }
894 }
895
896 fn into_component_selector(self) -> ComponentSelector {
897 ComponentSelector {
898 moniker_segments: Some(
899 match self {
900 ExtendedMoniker::ComponentManager => {
901 vec![EXTENDED_MONIKER_COMPONENT_MANAGER_STR.into()]
902 }
903 ExtendedMoniker::ComponentInstance(moniker) => {
904 moniker.path().iter().map(|value| value.to_string()).collect()
905 }
906 }
907 .into_iter()
908 .map(StringSelector::ExactMatch)
909 .collect(),
910 ),
911 ..Default::default()
912 }
913 }
914}
915
916impl SelectorExt for Moniker {
917 fn match_against_selectors<'a>(
918 &self,
919 selectors: impl IntoIterator<Item = &'a Selector>,
920 ) -> impl Iterator<Item = Result<&'a Selector, anyhow::Error>> {
921 let s = SegmentIterator::from(self).collect::<Vec<_>>();
922 match_component_moniker_against_selectors(s, selectors)
923 }
924
925 fn match_against_selectors_and_tree_name<'a>(
926 &self,
927 tree_name: &str,
928 selectors: impl IntoIterator<Item = &'a Selector>,
929 ) -> impl Iterator<Item = &'a Selector> {
930 let m = SegmentIterator::from(self).collect::<Vec<_>>();
931
932 selectors
933 .into_iter()
934 .filter(move |s| match_component_and_tree_name(&m, tree_name, s).unwrap_or(false))
935 }
936
937 fn match_against_component_selectors<'a, S>(
938 &self,
939 selectors: &'a [S],
940 ) -> Result<Vec<&'a ComponentSelector>, anyhow::Error>
941 where
942 S: Borrow<ComponentSelector>,
943 {
944 let s = SegmentIterator::from(self).collect::<Vec<_>>();
945 match_moniker_against_component_selectors(&s, selectors)
946 }
947
948 fn matches_selector(&self, selector: &Selector) -> Result<bool, anyhow::Error> {
949 let s = SegmentIterator::from(self).collect::<Vec<_>>();
950 match_component_moniker_against_selector(&s, selector)
951 }
952
953 fn matches_component_selector(
954 &self,
955 selector: &ComponentSelector,
956 ) -> Result<bool, anyhow::Error> {
957 match_moniker_against_component_selector(SegmentIterator::from(self), selector)
958 }
959
960 fn sanitized(&self) -> String {
961 SegmentIterator::from(self)
962 .map(|s| sanitize_string_for_selectors(&s).into_owned())
963 .collect::<Vec<String>>()
964 .join("/")
965 }
966
967 fn into_component_selector(self) -> ComponentSelector {
968 ComponentSelector {
969 moniker_segments: Some(
970 self.path()
971 .iter()
972 .map(|value| StringSelector::ExactMatch(value.to_string()))
973 .collect(),
974 ),
975 ..Default::default()
976 }
977 }
978}
979
980enum SegmentIterator<'a> {
981 Iter { path: Arc<[&'a BorrowedChildName]>, current_index: usize },
982 Root(bool),
983}
984
985impl<'a> From<&'a Moniker> for SegmentIterator<'a> {
986 fn from(moniker: &'a Moniker) -> Self {
987 if moniker.is_root() {
988 return SegmentIterator::Root(false);
989 }
990 SegmentIterator::Iter { path: moniker.path().into(), current_index: 0 }
991 }
992}
993
994impl Iterator for SegmentIterator<'_> {
995 type Item = String;
996 fn next(&mut self) -> Option<Self::Item> {
997 match self {
998 Self::Iter { path, current_index } => {
999 let segment = path.get(*current_index)?;
1000 let result = segment.to_string();
1001 *self = Self::Iter { path: path.clone(), current_index: *current_index + 1 };
1002 Some(result)
1003 }
1004 Self::Root(true) => None,
1005 Self::Root(done) => {
1006 *done = true;
1007 Some(ROOT_SEGMENT.to_string())
1008 }
1009 }
1010 }
1011}
1012
1013#[cfg(test)]
1014mod tests {
1015 use super::*;
1016 use std::fs::File;
1017 use std::io::prelude::*;
1018 use std::path::PathBuf;
1019 use std::str::FromStr;
1020 use tempfile::TempDir;
1021 use test_case::test_case;
1022
1023 pub fn parse_selectors<E>(directory: &Path) -> Result<Vec<Selector>, Error>
1025 where
1026 E: for<'a> ParsingError<'a>,
1027 {
1028 let path: PathBuf = directory.to_path_buf();
1029 let mut selector_vec: Vec<Selector> = Vec::new();
1030 for entry in fs::read_dir(path)? {
1031 let entry = entry?;
1032 if entry.path().is_dir() {
1033 return Err(Error::NonFlatDirectory);
1034 } else {
1035 selector_vec.append(&mut parse_selector_file::<E>(&entry.path())?);
1036 }
1037 }
1038 Ok(selector_vec)
1039 }
1040
1041 #[fuchsia::test]
1042 fn successful_selector_parsing() {
1043 let tempdir = TempDir::new().expect("failed to create tmp dir");
1044 File::create(tempdir.path().join("a.txt"))
1045 .expect("create file")
1046 .write_all(
1047 b"a:b:c
1048
1049",
1050 )
1051 .expect("writing test file");
1052 File::create(tempdir.path().join("b.txt"))
1053 .expect("create file")
1054 .write_all(b"a*/b:c/d/*:*")
1055 .expect("writing test file");
1056
1057 File::create(tempdir.path().join("c.txt"))
1058 .expect("create file")
1059 .write_all(
1060 b"// this is a comment
1061a:b:c
1062",
1063 )
1064 .expect("writing test file");
1065 File::create(tempdir.path().join("d.txt"))
1066 .expect("create file")
1067 .write_all(
1068 b"foo:bar
1069// This is a multi line comment.
1070//
1071// The blank comment line above is allowed.
1072foo:baz
1073",
1074 )
1075 .expect("writing test file");
1076
1077 assert_matches::assert_matches!(parse_selectors::<VerboseError>(tempdir.path()), Ok(_));
1078 }
1079
1080 #[fuchsia::test]
1081 fn unsuccessful_selector_parsing_bad_selector() {
1082 let tempdir = TempDir::new().expect("failed to create tmp dir");
1083 File::create(tempdir.path().join("a.txt"))
1084 .expect("create file")
1085 .write_all(b"a:b:c")
1086 .expect("writing test file");
1087 File::create(tempdir.path().join("b.txt"))
1088 .expect("create file")
1089 .write_all(b"**:**:**")
1090 .expect("writing test file");
1091
1092 assert!(parse_selectors::<VerboseError>(tempdir.path()).is_err());
1093 }
1094
1095 #[fuchsia::test]
1096 fn unsuccessful_selector_parsing_nonflat_dir() {
1097 let tempdir = TempDir::new().expect("failed to create tmp dir");
1098 File::create(tempdir.path().join("a.txt"))
1099 .expect("create file")
1100 .write_all(b"a:b:c")
1101 .expect("writing test file");
1102 File::create(tempdir.path().join("b.txt"))
1103 .expect("create file")
1104 .write_all(b"**:**:**")
1105 .expect("writing test file");
1106
1107 std::fs::create_dir_all(tempdir.path().join("nested")).expect("make nested");
1108 File::create(tempdir.path().join("nested/c.txt"))
1109 .expect("create file")
1110 .write_all(b"**:**:**")
1111 .expect("writing test file");
1112 assert!(parse_selectors::<VerboseError>(tempdir.path()).is_err());
1113 }
1114
1115 #[fuchsia::test]
1116 fn component_selector_match_test() {
1117 let passing_test_cases = vec![
1120 (r#"echo:*:*"#, vec!["echo"]),
1121 (r#"*/echo:*:*"#, vec!["abc", "echo"]),
1122 (r#"ab*/echo:*:*"#, vec!["abc", "echo"]),
1123 (r#"ab*/echo:*:*"#, vec!["abcde", "echo"]),
1124 (r#"*/ab*/echo:*:*"#, vec!["123", "abcde", "echo"]),
1125 (r#"echo*:*:*"#, vec!["echo"]),
1126 (r#"a/echo*:*:*"#, vec!["a", "echo1"]),
1127 (r#"a/echo*:*:*"#, vec!["a", "echo"]),
1128 (r#"ab*/echo:*:*"#, vec!["ab", "echo"]),
1129 (r#"a/**:*:*"#, vec!["a", "echo"]),
1130 (r#"a/**:*:*"#, vec!["a", "b", "echo"]),
1131 ];
1132
1133 for (selector, moniker) in passing_test_cases {
1134 let parsed_selector = parse_selector::<VerboseError>(selector).unwrap();
1135 assert!(
1136 match_component_moniker_against_selector(&moniker, &parsed_selector).unwrap(),
1137 "Selector {selector:?} failed to match {moniker:?}"
1138 );
1139 }
1140
1141 let failing_test_cases = vec![
1144 (r#"*:*:*"#, vec!["a", "echo"]),
1145 (r#"*/echo:*:*"#, vec!["123", "abc", "echo"]),
1146 (r#"a/**:*:*"#, vec!["b", "echo"]),
1147 (r#"e/**:*:*"#, vec!["echo"]),
1148 ];
1149
1150 for (selector, moniker) in failing_test_cases {
1151 let parsed_selector = parse_selector::<VerboseError>(selector).unwrap();
1152 assert!(
1153 !match_component_moniker_against_selector(&moniker, &parsed_selector).unwrap(),
1154 "Selector {selector:?} matched {moniker:?}, but was expected to fail"
1155 );
1156 }
1157 }
1158
1159 #[fuchsia::test]
1160 fn multiple_component_selectors_match_test() {
1161 let selectors = vec![r#"*/echo"#, r#"ab*/echo"#, r#"abc/m*"#];
1162 let moniker = vec!["abc".to_string(), "echo".to_string()];
1163
1164 let component_selectors = selectors
1165 .into_iter()
1166 .map(|selector| parse_component_selector::<VerboseError>(selector).unwrap())
1167 .collect::<Vec<_>>();
1168
1169 let match_res =
1170 match_moniker_against_component_selectors(moniker.as_slice(), &component_selectors[..]);
1171 assert!(match_res.is_ok());
1172 assert_eq!(match_res.unwrap().len(), 2);
1173 }
1174
1175 #[test_case("a/b:c:d", "a/b:c:d" ; "no_wrap_with_basic_full_selector")]
1176 #[test_case("a/b:c", "a/b:c" ; "no_wrap_with_basic_partial_selector")]
1177 #[test_case(r"a/b:c/d\/e:f", r#"a/b:c/d\/e:f"# ; "no_wrap_with_escaped_forward_slash")]
1178 #[test_case(r"a/b:[name=root]c:d", "a/b:c:d" ; "no_wrap_with_default_name")]
1179 #[test_case(r"a/b:[name=cd-e]f:g", r#"a/b:[name=cd-e]f:g"# ; "no_wrap_with_non_default_name")]
1180 #[test_case(
1181 r#"a:[name="bc-d"]e:f"#,
1182 r"a:[name=bc-d]e:f"
1183 ; "no_wrap_with_unneeded_name_quotes"
1184 )]
1185 #[test_case(
1186 r#"a:[name="b[]c"]d:e"#,
1187 r#"a:[name="b[]c"]d:e"#
1188 ; "no_wrap_with_needed_name_quotes"
1189 )]
1190 #[test_case("a/b:[...]c:d", r#"a/b:[...]c:d"# ; "no_wrap_with_all_names")]
1191 #[test_case(
1192 r#"a/b:[name=c, name="d", name="f[]g"]h:i"#,
1193 r#"a/b:[name=c,name=d,name="f[]g"]h:i"#
1194 ; "no_wrap_with_name_list"
1195 )]
1196 #[test_case(r"a\:b/c:d:e", r"a\:b/c:d:e" ; "no_wrap_with_collection")]
1197 #[test_case(r"a/b/c*d:e:f", r#"a/b/c*d:e:f"# ; "no_wrap_with_wildcard_component")]
1198 #[test_case(r"a/b:c*/d:e", r#"a/b:c*/d:e"# ; "no_wrap_with_wildcard_tree")]
1199 #[test_case(r"a/b:c\*/d:e", r#"a/b:c\*/d:e"# ; "no_wrap_with_escaped_wildcard_tree")]
1200 #[test_case(r"a/b/c/d:e/f:g*", r#"a/b/c/d:e/f:g*"# ; "no_wrap_with_wildcard_property")]
1201 #[test_case(r"a/b/c/d:e/f:g*", r#"a/b/c/d:e/f:g*"# ; "no_wrap_with_escaped_wildcard_property")]
1202 #[test_case("a/b/c/d:e/f/g/h:k", "a/b/c/d:e/f/g/h:k" ; "no_wrap_with_deep_nesting")]
1203 #[fuchsia::test]
1204 fn selector_to_string_test_never_wrap(input: &str, expected: &str) {
1205 let selector = parse_verbose(input).unwrap();
1206 assert_eq!(
1207 selector_to_string(&selector, SelectorDisplayOptions::never_wrap_in_quotes()).unwrap(),
1208 expected,
1209 "left: actual, right: expected"
1210 );
1211 }
1212
1213 #[test_case("a/b:c:d", "a/b:c:d" ; "with_basic_full_selector")]
1214 #[test_case("a/b:c", "a/b:c" ; "with_basic_partial_selector")]
1215 #[test_case(r"a/b:c/d\/e:f", r#""a/b:c/d\/e:f""# ; "with_escaped_forward_slash")]
1216 #[test_case(r"a/b:[name=root]c:d", "a/b:c:d" ; "with_default_name")]
1217 #[test_case(r"a/b:[name=cd-e]f:g", r#""a/b:[name=cd-e]f:g""# ; "with_non_default_name")]
1218 #[test_case(r#"a:[name="bc-d"]e:f"#, r#""a:[name=bc-d]e:f""# ; "with_unneeded_name_quotes")]
1219 #[test_case(r#"a:[name="b[]c"]d:e"#, r#""a:[name="b[]c"]d:e""# ; "with_needed_name_quotes")]
1220 #[test_case("a/b:[...]c:d", r#""a/b:[...]c:d""# ; "with_all_names")]
1221 #[test_case(
1222 r#"a/b:[name=c, name="d", name="f[]g"]h:i"#,
1223 r#""a/b:[name=c,name=d,name="f[]g"]h:i""#
1224 ; "with_name_list"
1225 )]
1226 #[test_case(r"a\:b/c:d:e", r"a\:b/c:d:e" ; "with_collection")]
1227 #[test_case(r"a/b/c*d:e:f", r#""a/b/c*d:e:f""# ; "with_wildcard_component")]
1228 #[test_case(r"a/b:c*/d:e", r#""a/b:c*/d:e""# ; "with_wildcard_tree")]
1229 #[test_case(r"a/b:c\*/d:e", r#""a/b:c\*/d:e""# ; "with_escaped_wildcard_tree")]
1230 #[test_case(r"a/b/c/d:e/f:g*", r#""a/b/c/d:e/f:g*""# ; "with_wildcard_property")]
1231 #[test_case(r"a/b/c/d:e/f:g*", r#""a/b/c/d:e/f:g*""# ; "with_escaped_wildcard_property")]
1232 #[test_case("a/b/c/d:e/f/g/h:k", "a/b/c/d:e/f/g/h:k" ; "with_deep_nesting")]
1233 #[fuchsia::test]
1234 fn selector_to_string_test_default(input: &str, expected: &str) {
1235 let selector = parse_verbose(input).unwrap();
1236 assert_eq!(
1237 selector_to_string(&selector, SelectorDisplayOptions::default()).unwrap(),
1238 expected,
1239 "left: actual, right: expected"
1240 );
1241 }
1242
1243 #[test_case("a*", r"a\*" ; "when_star_not_leading")]
1244 #[test_case("a:", r"a\:" ; "when_colon_not_leading")]
1245 #[test_case(":", r"\:" ; "when_colon_leading")]
1246 #[test_case("*", r"\*" ; "when_star_leading")]
1247 #[test_case(r"*:\abc", r"\*\:\\abc" ; "when_mixed_with_leading_special_chars")]
1248 #[fuchsia::test]
1249 fn sanitize_string_for_selectors_works(input: &str, expected: &str) {
1250 assert_eq!(sanitize_string_for_selectors(input), expected);
1251 }
1252
1253 #[fuchsia::test]
1254 fn sanitize_moniker_for_selectors_result_is_usable() {
1255 let selector = parse_selector::<VerboseError>(&format!(
1256 "{}:root",
1257 sanitize_moniker_for_selectors("foo/coll:bar/baz")
1258 ))
1259 .unwrap();
1260 let component_selector = selector.component_selector.as_ref().unwrap();
1261 let moniker = ["foo", "coll:bar", "baz"];
1262 assert!(
1263 match_moniker_against_component_selector(moniker.iter(), component_selector).unwrap()
1264 );
1265 }
1266
1267 #[fuchsia::test]
1268 fn escaped_spaces() {
1269 let selector_str = "foo:bar\\ baz/a*\\ b:quux";
1270 let selector = parse_selector::<VerboseError>(selector_str).unwrap();
1271 assert_eq!(
1272 selector,
1273 Selector {
1274 component_selector: Some(ComponentSelector {
1275 moniker_segments: Some(vec![StringSelector::ExactMatch("foo".into()),]),
1276 ..Default::default()
1277 }),
1278 tree_selector: Some(TreeSelector::PropertySelector(PropertySelector {
1279 node_path: vec![
1280 StringSelector::ExactMatch("bar baz".into()),
1281 StringSelector::StringPattern("a* b".into()),
1282 ],
1283 target_properties: StringSelector::ExactMatch("quux".into())
1284 })),
1285 ..Default::default()
1286 }
1287 );
1288 }
1289
1290 #[fuchsia::test]
1291 fn match_string_test() {
1292 assert!(match_string(&StringSelector::ExactMatch("foo".into()), "foo"));
1294
1295 assert!(match_string(&StringSelector::StringPattern("*foo*".into()), "hellofoobye"));
1297 assert!(match_string(&StringSelector::StringPattern("bar*foo".into()), "barxfoo"));
1298 assert!(match_string(&StringSelector::StringPattern("bar*foo".into()), "barfoo"));
1299 assert!(match_string(&StringSelector::StringPattern("bar*foo".into()), "barxfoo"));
1300 assert!(match_string(&StringSelector::StringPattern("foo*".into()), "foobar"));
1301 assert!(match_string(&StringSelector::StringPattern("*".into()), "foo"));
1302 assert!(match_string(&StringSelector::StringPattern("bar*baz*foo".into()), "barxzybazfoo"));
1303 assert!(match_string(&StringSelector::StringPattern("foo*bar*baz".into()), "foobazbarbaz"));
1304
1305 assert!(match_string(&StringSelector::StringPattern("foo\\*".into()), "foo*"));
1307
1308 assert!(!match_string(&StringSelector::StringPattern("foo\\".into()), "foo\\"));
1310 assert!(!match_string(&StringSelector::StringPattern("bar*foo".into()), "barxfoox"));
1311 assert!(!match_string(&StringSelector::StringPattern("m*".into()), "echo.csx"));
1312 assert!(!match_string(&StringSelector::StringPattern("*foo*".into()), "xbary"));
1313 assert!(!match_string(
1314 &StringSelector::StringPattern("foo*bar*baz*qux".into()),
1315 "foobarbaazqux"
1316 ));
1317 }
1318
1319 #[fuchsia::test]
1320 fn test_log_interest_selector() {
1321 assert_eq!(
1322 parse_log_interest_selector("core/network#FATAL").unwrap(),
1323 LogInterestSelector {
1324 selector: parse_component_selector::<VerboseError>("core/network").unwrap(),
1325 interest: Interest { min_severity: Some(Severity::Fatal), ..Default::default() }
1326 }
1327 );
1328 assert_eq!(
1329 parse_log_interest_selector("any/component#INFO").unwrap(),
1330 LogInterestSelector {
1331 selector: parse_component_selector::<VerboseError>("any/component").unwrap(),
1332 interest: Interest { min_severity: Some(Severity::Info), ..Default::default() }
1333 }
1334 );
1335 assert_eq!(
1336 parse_log_interest_selector("any/coll:instance/foo#INFO").unwrap(),
1337 LogInterestSelector {
1338 selector: parse_component_selector::<VerboseError>("any/coll\\:instance/foo")
1339 .unwrap(),
1340 interest: Interest { min_severity: Some(Severity::Info), ..Default::default() }
1341 }
1342 );
1343 assert_eq!(
1344 parse_log_interest_selector("any/coll:*/foo#INFO").unwrap(),
1345 LogInterestSelector {
1346 selector: parse_component_selector::<VerboseError>("any/coll\\:*/foo").unwrap(),
1347 interest: Interest { min_severity: Some(Severity::Info), ..Default::default() }
1348 }
1349 );
1350 }
1351 #[test]
1352 fn test_log_interest_selector_error() {
1353 assert!(parse_log_interest_selector("anything////#FATAL").is_err());
1354 assert!(parse_log_interest_selector("core/network").is_err());
1355 assert!(parse_log_interest_selector("core/network#FAKE").is_err());
1356 assert!(parse_log_interest_selector("core/network\\:foo#FAKE").is_err());
1357 }
1358
1359 #[test]
1360 fn test_moniker_to_selector() {
1361 assert_eq!(
1362 Moniker::from_str("a/b/c").unwrap().into_component_selector(),
1363 parse_component_selector::<VerboseError>("a/b/c").unwrap()
1364 );
1365 assert_eq!(
1366 ExtendedMoniker::ComponentManager.into_component_selector(),
1367 parse_component_selector::<VerboseError>("<component_manager>").unwrap()
1368 );
1369 assert_eq!(
1370 ExtendedMoniker::ComponentInstance(Moniker::from_str("a/b/c").unwrap())
1371 .into_component_selector(),
1372 parse_component_selector::<VerboseError>("a/b/c").unwrap()
1373 );
1374 assert_eq!(
1375 ExtendedMoniker::ComponentInstance(Moniker::from_str("a/coll:id/c").unwrap())
1376 .into_component_selector(),
1377 parse_component_selector::<VerboseError>("a/coll\\:id/c").unwrap()
1378 );
1379 }
1380
1381 #[test]
1382 fn test_parse_log_interest_or_severity() {
1383 for (severity_str, severity) in [
1384 ("TRACE", Severity::Trace),
1385 ("DEBUG", Severity::Debug),
1386 ("INFO", Severity::Info),
1387 ("WARN", Severity::Warn),
1388 ("ERROR", Severity::Error),
1389 ("FATAL", Severity::Fatal),
1390 ] {
1391 assert_eq!(
1392 parse_log_interest_selector_or_severity(severity_str).unwrap(),
1393 LogInterestSelector {
1394 selector: parse_component_selector::<VerboseError>("**").unwrap(),
1395 interest: Interest { min_severity: Some(severity), ..Default::default() }
1396 }
1397 );
1398 }
1399
1400 assert_eq!(
1401 parse_log_interest_selector_or_severity("foo/bar#DEBUG").unwrap(),
1402 LogInterestSelector {
1403 selector: parse_component_selector::<VerboseError>("foo/bar").unwrap(),
1404 interest: Interest { min_severity: Some(Severity::Debug), ..Default::default() }
1405 }
1406 );
1407
1408 assert!(parse_log_interest_selector_or_severity("RANDOM").is_err());
1409 assert!(parse_log_interest_selector_or_severity("core/foo#NO#YES").is_err());
1410 }
1411
1412 #[test]
1413 fn test_parse_tree_selector() {
1414 let selector = parse_tree_selector::<VerboseError>("root/node*/nested:prop").unwrap();
1415 assert_eq!(
1416 selector,
1417 TreeSelector::PropertySelector(PropertySelector {
1418 node_path: vec![
1419 StringSelector::ExactMatch("root".into()),
1420 StringSelector::StringPattern("node*".into()),
1421 StringSelector::ExactMatch("nested".into()),
1422 ],
1423 target_properties: StringSelector::ExactMatch("prop".into())
1424 }),
1425 );
1426 }
1427
1428 #[test]
1429 fn test_monikers_against_selectors_and_tree_name() {
1430 let selectors = &[
1431 parse_selector::<VerboseError>("core/foo:root:prop").unwrap(),
1432 parse_selector::<VerboseError>("core/*:[name=root]root:prop").unwrap(),
1433 parse_selector::<VerboseError>("core/baz:[name=baz]root:prop").unwrap(),
1434 parse_selector::<VerboseError>("core/baz:[name=root]root:prop").unwrap(),
1435 parse_selector::<VerboseError>("core/*:[...]root:prop").unwrap(),
1436 parse_selector::<VerboseError>("<component_manager>:root:prop").unwrap(),
1437 ];
1438
1439 {
1440 let foo = ExtendedMoniker::try_from("core/foo").unwrap();
1441
1442 let actual = foo
1443 .match_against_selectors_and_tree_name("root", selectors.iter())
1444 .collect::<Vec<_>>();
1445 assert_eq!(actual, vec![&selectors[0], &selectors[1], &selectors[4]]);
1446
1447 let foo = Moniker::try_from("core/foo").unwrap();
1448
1449 let actual = foo
1450 .match_against_selectors_and_tree_name("root", selectors.iter())
1451 .collect::<Vec<_>>();
1452 assert_eq!(actual, vec![&selectors[0], &selectors[1], &selectors[4]]);
1453 }
1454
1455 {
1456 let baz = ExtendedMoniker::try_from("core/baz").unwrap();
1457
1458 let actual = baz
1459 .match_against_selectors_and_tree_name("root", selectors.iter())
1460 .collect::<Vec<_>>();
1461 assert_eq!(actual, vec![&selectors[1], &selectors[3], &selectors[4]]);
1462
1463 let baz = Moniker::try_from("core/baz").unwrap();
1464
1465 let actual = baz
1466 .match_against_selectors_and_tree_name("root", selectors.iter())
1467 .collect::<Vec<_>>();
1468 assert_eq!(actual, vec![&selectors[1], &selectors[3], &selectors[4]]);
1469 }
1470
1471 {
1472 let baz = ExtendedMoniker::try_from("core/baz").unwrap();
1473
1474 let actual = baz
1475 .match_against_selectors_and_tree_name("baz", selectors.iter())
1476 .collect::<Vec<_>>();
1477 assert_eq!(actual, vec![&selectors[2], &selectors[4]]);
1478
1479 let baz = Moniker::try_from("core/baz").unwrap();
1480
1481 let actual = baz
1482 .match_against_selectors_and_tree_name("baz", selectors.iter())
1483 .collect::<Vec<_>>();
1484 assert_eq!(actual, vec![&selectors[2], &selectors[4]]);
1485 }
1486
1487 {
1488 let qux = ExtendedMoniker::try_from("core/qux").unwrap();
1489
1490 let actual = qux
1491 .match_against_selectors_and_tree_name("qux", selectors.iter())
1492 .collect::<Vec<_>>();
1493 assert_eq!(actual, vec![&selectors[4]]);
1494
1495 let qux = Moniker::try_from("core/qux").unwrap();
1496
1497 let actual = qux
1498 .match_against_selectors_and_tree_name("qux", selectors.iter())
1499 .collect::<Vec<_>>();
1500 assert_eq!(actual, vec![&selectors[4]]);
1501 }
1502
1503 {
1504 let cm = ExtendedMoniker::try_from(EXTENDED_MONIKER_COMPONENT_MANAGER_STR).unwrap();
1505
1506 let actual = cm
1507 .match_against_selectors_and_tree_name("root", selectors.iter())
1508 .collect::<Vec<_>>();
1509 assert_eq!(actual, vec![&selectors[5]]);
1510 }
1511 }
1512}