| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use { |
| fidl_fuchsia_diagnostics::Selector, |
| lazy_static::lazy_static, |
| selectors::{self, FastError}, |
| }; |
| |
| lazy_static! { |
| #[derive(Clone)] |
| static ref MONIKERS_TO_REWRITE: Vec<MonikerRewritePair> = vec![ |
| // Note: These are unparsed strings, not separated into moniker segments. |
| // legacy_str cannot contain slashes but modern_str can. |
| MonikerRewritePair { |
| legacy_str: "memory_monitor.cmx", |
| modern_str: "core/memory_monitor", |
| }, |
| MonikerRewritePair { |
| legacy_str: "wlanstack.cmx", |
| modern_str: "core/wlanstack", |
| }, |
| MonikerRewritePair { |
| legacy_str: "omaha-client-service.cmx", |
| modern_str: "core/omaha-client-service", |
| }, |
| MonikerRewritePair { |
| legacy_str: "cobalt_system_metrics.cmx", |
| modern_str: "core/cobalt_system_metrics" |
| } |
| ]; |
| } |
| |
| pub struct MonikerRewriter { |
| monikers: Vec<MonikerRewritePair>, |
| } |
| |
| #[derive(Clone, Debug)] |
| pub struct MonikerRewritePair { |
| legacy_str: &'static str, |
| modern_str: &'static str, |
| } |
| |
| impl MonikerRewriter { |
| pub(crate) fn new() -> Self { |
| Self { monikers: MONIKERS_TO_REWRITE.to_vec() } |
| } |
| |
| /// Checks whether any of the selectors needs rewriting. If so, it returns an OutputRewriter |
| /// that makes the corresponding change on the output. Otherwise, it returns None for the |
| /// rewriter. Either way, it returns the correct set of selectors. |
| pub(crate) fn rewrite_selectors( |
| &self, |
| mut selectors: Vec<Selector>, |
| ) -> (Option<Vec<Selector>>, Option<OutputRewriter>) { |
| let mut monikers_rewritten = Vec::new(); |
| for s in selectors.iter_mut() { |
| for pair in &self.monikers { |
| // Not expecting an error here, but if we get one, don't make any changes. |
| if selectors::match_component_moniker_against_selector(&[pair.legacy_str], s) |
| .unwrap_or(false) |
| { |
| if let Ok(selector) = |
| selectors::parse_component_selector::<FastError>(pair.modern_str) |
| { |
| s.component_selector = Some(selector); |
| monikers_rewritten.push(pair.clone()); |
| } |
| } |
| } |
| } |
| let rewriter = if monikers_rewritten.is_empty() { |
| None |
| } else { |
| Some(OutputRewriter { monikers: monikers_rewritten }) |
| }; |
| (Some(selectors), rewriter) |
| } |
| } |
| |
| #[derive(Debug)] |
| pub struct OutputRewriter { |
| monikers: Vec<MonikerRewritePair>, |
| } |
| |
| impl OutputRewriter { |
| pub(crate) fn rewrite_moniker(&self, moniker: String) -> String { |
| for pair in &self.monikers { |
| if pair.modern_str == moniker { |
| return pair.legacy_str.to_string(); |
| } |
| } |
| moniker |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use super::*; |
| use fidl_fuchsia_diagnostics::StringSelector; |
| use selectors::VerboseError; |
| |
| macro_rules! extract_moniker { |
| ($selector:expr) => { |
| extract_moniker!($selector, 0) |
| }; |
| ($selectors:expr, $index:expr) => { |
| $selectors.as_ref().unwrap()[$index] |
| .component_selector |
| .as_ref() |
| .unwrap() |
| .moniker_segments |
| .as_ref() |
| .unwrap() |
| }; |
| } |
| |
| #[fuchsia::test] |
| fn moniker_rewriter_works() { |
| let rewriter = MonikerRewriter::new(); |
| let legacy_selector = |
| selectors::parse_selector::<VerboseError>("memory_monitor.cmx:path/to:data").unwrap(); |
| let new_selector = |
| selectors::parse_selector::<VerboseError>("core/memory_monitor:path/to:data").unwrap(); |
| let irrelevant_selector = |
| selectors::parse_selector::<VerboseError>("foo/bar.baz:path/to:data").unwrap(); |
| |
| let (rewritten_legacy, legacy_rewriter) = rewriter.rewrite_selectors(vec![legacy_selector]); |
| let (rewritten_new, new_rewriter) = rewriter.rewrite_selectors(vec![new_selector]); |
| let (rewritten_irrelevant, irrelevant_rewriter) = |
| rewriter.rewrite_selectors(vec![irrelevant_selector]); |
| |
| assert_eq!( |
| extract_moniker!(rewritten_legacy), |
| &vec![ |
| StringSelector::ExactMatch("core".to_string()), |
| StringSelector::ExactMatch("memory_monitor".to_string()) |
| ] |
| ); |
| assert_eq!( |
| extract_moniker!(rewritten_new), |
| &vec![ |
| StringSelector::ExactMatch("core".to_string()), |
| StringSelector::ExactMatch("memory_monitor".to_string()) |
| ] |
| ); |
| assert_eq!( |
| extract_moniker!(rewritten_irrelevant), |
| &vec![ |
| StringSelector::ExactMatch("foo".to_string()), |
| StringSelector::ExactMatch("bar.baz".to_string()) |
| ] |
| ); |
| assert!(new_rewriter.is_none()); |
| assert!(irrelevant_rewriter.is_none()); |
| let rewriter = legacy_rewriter.unwrap(); |
| |
| assert_eq!(rewriter.rewrite_moniker("foo/bar.baz".to_string()), "foo/bar.baz".to_string()); |
| assert_eq!( |
| rewriter.rewrite_moniker("memory_monitor.cmx".to_string()), |
| "memory_monitor.cmx".to_string() |
| ); |
| assert_eq!( |
| rewriter.rewrite_moniker("core/memory_monitor".to_string()), |
| "memory_monitor.cmx".to_string() |
| ); |
| } |
| |
| #[fuchsia::test] |
| fn array_logic_works() { |
| let rewriter = MonikerRewriter { |
| monikers: vec![ |
| MonikerRewritePair { legacy_str: "legacy1", modern_str: "modern1" }, |
| MonikerRewritePair { legacy_str: "legacy2", modern_str: "modern2" }, |
| ], |
| }; |
| let legacy_selector1 = |
| selectors::parse_selector::<VerboseError>("legacy1:path/to:data").unwrap(); |
| let legacy_selector2 = |
| selectors::parse_selector::<VerboseError>("legacy2:path/to:data").unwrap(); |
| let irrelevant_selector = |
| selectors::parse_selector::<VerboseError>("irrelevant:path/to:data").unwrap(); |
| |
| let (rewritten_1_i, rewriter_1_i) = |
| rewriter.rewrite_selectors(vec![legacy_selector1.clone(), irrelevant_selector.clone()]); |
| let (rewritten_2_1, rewriter_2_1) = |
| rewriter.rewrite_selectors(vec![legacy_selector2.clone(), legacy_selector1.clone()]); |
| let rewriter_1_i = rewriter_1_i.unwrap(); |
| let rewriter_2_1 = rewriter_2_1.unwrap(); |
| |
| assert_eq!( |
| extract_moniker!(rewritten_1_i, 0), |
| &vec![StringSelector::ExactMatch("modern1".to_string()),] |
| ); |
| assert_eq!( |
| extract_moniker!(rewritten_1_i, 1), |
| &vec![StringSelector::ExactMatch("irrelevant".to_string()),] |
| ); |
| assert_eq!( |
| extract_moniker!(rewritten_2_1, 0), |
| &vec![StringSelector::ExactMatch("modern2".to_string()),] |
| ); |
| assert_eq!( |
| extract_moniker!(rewritten_2_1, 1), |
| &vec![StringSelector::ExactMatch("modern1".to_string()),] |
| ); |
| |
| assert_eq!(rewriter_1_i.rewrite_moniker("modern1".to_string()), "legacy1".to_string()); |
| assert_eq!(rewriter_1_i.rewrite_moniker("modern2".to_string()), "modern2".to_string()); |
| assert_eq!(rewriter_2_1.rewrite_moniker("modern1".to_string()), "legacy1".to_string()); |
| assert_eq!(rewriter_2_1.rewrite_moniker("modern2".to_string()), "legacy2".to_string()); |
| } |
| } |