Revert "[cm_fidl_analyzer][scrutiny] Replace NodePath with AbsoluteMoniker"
This reverts commit a2bc51fd452d0cf85b3f770b7ae09c82e256737d.
Reason for revert: Disabled verification of routes at session scope, or
deeper.
Original change's description:
> [cm_fidl_analyzer][scrutiny] Replace NodePath with AbsoluteMoniker
>
> The `AbsoluteMoniker` type is now a 1:1 replacement for
> cm_fidl_analyzer's `NodePath` type (which was originally
> a workaround to avoid handling instance IDs).
>
> Bug: 102801
>
> Change-Id: I41406a0be450849c5093537609ef4eecbfd41e0a
> Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/688902
> Commit-Queue: Laura Peskin <pesk@google.com>
> Reviewed-by: Yaneury Fermin <yaneury@google.com>
Bug: 102801, 103259
Change-Id: I82adaa52266fb1d8ad1f51aa64db4c78e11e0f5a
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693704
Reviewed-by: Wez <wez@google.com>
Commit-Queue: Wez <wez@google.com>
Reviewed-by: RubberStamper 🤖 <android-build-ayeaye@system.gserviceaccount.com>
diff --git a/src/developer/ffx/plugins/scrutiny/verify/src/component_resolvers.rs b/src/developer/ffx/plugins/scrutiny/verify/src/component_resolvers.rs
index 7e99b35..a709a7b 100644
--- a/src/developer/ffx/plugins/scrutiny/verify/src/component_resolvers.rs
+++ b/src/developer/ffx/plugins/scrutiny/verify/src/component_resolvers.rs
@@ -11,33 +11,33 @@
std::{collections::HashSet, fs, path::PathBuf},
};
-type Moniker = String;
+type NodePath = String;
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct ComponentResolversRequest {
scheme: String,
- moniker: Moniker,
+ moniker: NodePath,
protocol: String,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
struct ComponentResolversResponse {
deps: HashSet<PathBuf>,
- monikers: Vec<Moniker>,
+ monikers: Vec<NodePath>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
struct AllowListEntry {
#[serde(flatten)]
query: ComponentResolversRequest,
- components: Vec<Moniker>,
+ components: Vec<NodePath>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
struct AllowList(Vec<AllowListEntry>);
impl AllowList {
- pub fn iter(&self) -> impl Iterator<Item = (ComponentResolversRequest, &[Moniker])> {
+ pub fn iter(&self) -> impl Iterator<Item = (ComponentResolversRequest, &[NodePath])> {
self.0.iter().map(|entry| (entry.query.clone(), entry.components.as_slice()))
}
}
@@ -49,7 +49,7 @@
fn query(
&self,
scheme: String,
- moniker: Moniker,
+ moniker: NodePath,
protocol: String,
) -> Result<ComponentResolversResponse>;
}
@@ -67,7 +67,7 @@
fn query(
&self,
scheme: String,
- moniker: Moniker,
+ moniker: NodePath,
protocol: String,
) -> Result<ComponentResolversResponse> {
let request = ComponentResolversRequest { scheme, moniker, protocol };
@@ -110,7 +110,7 @@
let mut deps = HashSet::new();
for (query, allowed_monikers) in allowlist.iter() {
- let allowed_monikers: HashSet<&Moniker> = allowed_monikers.into_iter().collect();
+ let allowed_monikers: HashSet<&NodePath> = allowed_monikers.into_iter().collect();
let response = scrutiny
.query(query.scheme.clone(), query.moniker.clone(), query.protocol.clone())
@@ -176,7 +176,7 @@
#[derive(Debug)]
struct MockQueryComponentResolvers {
- responses: HashMap<(String, Moniker, String), String>,
+ responses: HashMap<(String, NodePath, String), String>,
}
impl MockQueryComponentResolvers {
@@ -186,8 +186,8 @@
fn with_response(
self,
- query: (String, Moniker, String),
- response: Vec<Moniker>,
+ query: (String, NodePath, String),
+ response: Vec<NodePath>,
response_deps: Vec<String>,
) -> Self {
let raw_response = serde_json::to_string(&ComponentResolversResponse {
@@ -198,7 +198,11 @@
self.with_raw_response(query, raw_response)
}
- fn with_raw_response(mut self, query: (String, Moniker, String), response: String) -> Self {
+ fn with_raw_response(
+ mut self,
+ query: (String, NodePath, String),
+ response: String,
+ ) -> Self {
self.responses.insert(query, response);
self
}
@@ -208,7 +212,7 @@
fn query(
&self,
scheme: String,
- moniker: Moniker,
+ moniker: NodePath,
protocol: String,
) -> Result<ComponentResolversResponse> {
let key = (scheme, moniker, protocol);
diff --git a/src/security/scrutiny/plugins/src/verify/collector/component_model.rs b/src/security/scrutiny/plugins/src/verify/collector/component_model.rs
index 6fc386d..0accdf2 100644
--- a/src/security/scrutiny/plugins/src/verify/collector/component_model.rs
+++ b/src/security/scrutiny/plugins/src/verify/collector/component_model.rs
@@ -11,13 +11,12 @@
verify::collection::V2ComponentModel,
},
anyhow::{anyhow, Context, Result},
- cm_fidl_analyzer::component_model::ModelBuilderForAnalyzer,
+ cm_fidl_analyzer::{component_model::ModelBuilderForAnalyzer, node_path::NodePath},
cm_rust::{ComponentDecl, FidlIntoNative, RegistrationSource, RunnerRegistration},
fidl::encoding::decode_persistent,
fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_component_internal as component_internal,
fuchsia_url::{boot_url::BootUrl, AbsoluteComponentUrl},
log::{error, info, warn},
- moniker::AbsoluteMoniker,
once_cell::sync::Lazy,
routing::{
component_id_index::ComponentIdIndex, config::RuntimeConfig, environment::RunnerRegistry,
@@ -54,7 +53,7 @@
#[derive(Deserialize, Serialize)]
pub struct ComponentTreeConfig {
- pub dynamic_components: HashMap<AbsoluteMoniker, DynamicComponent>,
+ pub dynamic_components: HashMap<NodePath, DynamicComponent>,
}
pub struct V2ComponentModelDataCollector {}
@@ -178,7 +177,7 @@
fn load_dynamic_components(
component_tree_config_path: &Option<PathBuf>,
- ) -> Result<HashMap<AbsoluteMoniker, (AbsoluteComponentUrl, Option<String>)>> {
+ ) -> Result<HashMap<NodePath, (AbsoluteComponentUrl, Option<String>)>> {
if component_tree_config_path.is_none() {
return Ok(HashMap::new());
}
@@ -191,10 +190,9 @@
.context("Failed to parse component tree configuration file")?;
let mut dynamic_components = HashMap::new();
- for (abs_moniker, dynamic_component) in component_tree_config.dynamic_components.into_iter()
- {
+ for (node_path, dynamic_component) in component_tree_config.dynamic_components.into_iter() {
dynamic_components
- .insert(abs_moniker, (dynamic_component.url, dynamic_component.environment));
+ .insert(node_path, (dynamic_component.url, dynamic_component.environment));
}
Ok(dynamic_components)
}
diff --git a/src/security/scrutiny/plugins/src/verify/controller/component_resolvers.rs b/src/security/scrutiny/plugins/src/verify/controller/component_resolvers.rs
index 9ea725b..1bb13aa 100644
--- a/src/security/scrutiny/plugins/src/verify/controller/component_resolvers.rs
+++ b/src/security/scrutiny/plugins/src/verify/controller/component_resolvers.rs
@@ -24,7 +24,7 @@
/// ComponentResolversController
///
-/// A DataController which returns a list of absolute monikers of all
+/// A DataController which returns a list component node paths of all
/// components that, in their environment, contain a resolver with the
/// given moniker for a scheme with access to a protocol.
#[derive(Default)]
@@ -35,7 +35,7 @@
pub struct ComponentResolverRequest {
/// `resolver` URI scheme of interest
pub scheme: String,
- /// Absolute moniker of the `resolver`
+ /// Node path of the `resolver`
pub moniker: String,
/// Filter the results to components resolved with a `resolver` with access to a protocol
pub protocol: String,
@@ -50,10 +50,10 @@
pub monikers: Vec<String>,
}
-/// Walks the tree for the absolute monikers of all components that,
-/// in their environment, contain a resolver with the given moniker
-/// for a scheme with access to a protocol. `monikers` contains the
-/// components which match the `request` parameters.
+/// Walks the tree for component node paths of all components that, in their
+/// environment, contain a resolver with the given moniker for a scheme
+/// with access to a protocol.
+/// `monikers` contains the components which match the `request` parameters.
struct ComponentResolversVisitor {
request: ComponentResolverRequest,
monikers: Vec<String>,
@@ -156,13 +156,13 @@
}
fn usage(&self) -> String {
- "Finds the absolute monikers of all components that, in their environment,
- contain a resolver for `scheme`, provided by a component with the given `moniker`
- and with access to `protocol`.
+ "Finds the component node paths of all components that, in their
+environment, contain a resolver with the given moniker for scheme with
+access to protocol.
Required parameters:
--scheme: the resolver URI scheme to query
---moniker: the absolute moniker of the component providing the resolver capability
+--moniker: the node path of the resolver
--resolver: filter results to components resolved with a resolver that has access to the given protocol"
.to_string()
}
diff --git a/src/security/scrutiny/plugins/src/verify/controller/route_sources.rs b/src/security/scrutiny/plugins/src/verify/controller/route_sources.rs
index 28ef6df..c3e43f2 100644
--- a/src/security/scrutiny/plugins/src/verify/controller/route_sources.rs
+++ b/src/security/scrutiny/plugins/src/verify/controller/route_sources.rs
@@ -10,13 +10,13 @@
anyhow::{anyhow, Context, Error, Result},
cm_fidl_analyzer::{
component_model::ComponentModelForAnalyzer,
+ node_path::NodePath,
route::{CapabilityRouteError, RouteSegment, VerifyRouteResult},
},
cm_rust::{
CapabilityDecl, CapabilityName, CapabilityPath, CapabilityTypeName, ComponentDecl,
ExposeDecl, OfferDecl, UseDecl,
},
- moniker::AbsoluteMoniker,
routing::component_instance::ComponentInstanceInterface,
scrutiny::model::{controller::DataController, model::DataModel},
serde::{Deserialize, Serialize},
@@ -60,9 +60,8 @@
/// Each route must be listed, either to be verified or skipped by the verifier.
#[derive(Deserialize, Serialize)]
pub struct RouteSourcesSpec {
- /// TODO(fxbug.dev/102801): rename to `target_moniker`.
- /// `AbsoluteMoniker` of the component instance whose routes are to be verified.
- pub target_node_path: AbsoluteMoniker,
+ /// Absolute path to the component instance whose routes are to be verified.
+ pub target_node_path: NodePath,
/// Routes that are expected to be present, but do not require verification.
pub routes_to_skip: Vec<UseSpec>,
/// Route specification and route source matching information for routes
@@ -114,9 +113,9 @@
/// Input query type for matching a route source.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct SourceSpec {
- /// `AbsoluteMoniker` prefix expected at the source instance.
- #[serde(rename = "source_moniker")]
- abs_moniker: AbsoluteMoniker,
+ /// Node path prefix expected at the source instance.
+ #[serde(rename = "source_node_path")]
+ node_path: NodePath,
/// Capability declaration expected at the source instance.
#[serde(flatten)]
capability: SourceDeclSpec,
@@ -276,8 +275,8 @@
/// Output type: The source of a capability route.
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct Source {
- /// The `AbsoluteMoniker` of the declaring component instance.
- abs_moniker: AbsoluteMoniker,
+ /// The node path of the declaring component instance.
+ node_path: NodePath,
/// The capability declaration.
capability: CapabilityDecl,
}
@@ -288,7 +287,7 @@
pub enum RouteSourceError {
CapabilityRouteError(CapabilityRouteError),
RouteSegmentWithoutComponent(RouteSegment),
- RouteSegmentAbsMonikerNotFoundInTree(RouteSegment),
+ RouteSegmentNodePathNotFoundInTree(RouteSegment),
ComponentInstanceLookupByUrlFailed(String),
MultipleComponentsWithSameUrl(Vec<Component>),
RouteSegmentComponentFromUntrustedSource(RouteSegment, ComponentSource),
@@ -370,7 +369,7 @@
fn gather_routes<'a>(
component_routes: &'a RouteSourcesSpec,
component_decl: &'a ComponentDecl,
- abs_moniker: &'a AbsoluteMoniker,
+ node_path: &'a NodePath,
) -> Result<(Vec<&'a UseDecl>, Vec<Binding<'a>>)> {
let uses = &component_decl.uses;
let routes_to_skip = component_routes
@@ -416,26 +415,26 @@
uses.iter().filter(|use_decl| !deduped_matches.contains(use_decl)).collect();
if duped_matches.len() > 0 {
Err(anyhow!(
- "{}. {}; moniker: {} routes matched multiple times: {:#?}; unmatched routes: {:#?}",
+ "{}. {}; component node path: {} routes matched multiple times: {:#?}; unmatched routes: {:#?}",
ROUTE_LISTS_OVERLAP,
ROUTE_LISTS_INCOMPLETE,
- abs_moniker,
+ node_path,
duped_matches,
missed_routes
))
} else {
Err(anyhow!(
- "{}; moniker: {}; unmatched routes: {:#?}",
+ "{}; component node path: {}; unmatched routes: {:#?}",
ROUTE_LISTS_INCOMPLETE,
- abs_moniker,
+ node_path,
missed_routes
))
}
} else if duped_matches.len() > 0 {
Err(anyhow!(
- "{}; moniker: {}; routes matched multiple times: {:#?}",
+ "{}; component node path: {}; routes matched multiple times: {:#?}",
ROUTE_LISTS_OVERLAP,
- abs_moniker,
+ node_path,
duped_matches
))
} else {
@@ -448,15 +447,15 @@
component_model: &Arc<ComponentModelForAnalyzer>,
components: &Vec<Component>,
) -> Option<RouteSourceError> {
- let abs_moniker = route_segment.abs_moniker();
- if abs_moniker.is_none() {
+ let node_path = route_segment.node_path();
+ if node_path.is_none() {
return Some(RouteSourceError::RouteSegmentWithoutComponent(route_segment.clone()));
}
- let abs_moniker = abs_moniker.unwrap();
+ let node_path = node_path.unwrap();
- let get_instance_result = component_model.get_instance(abs_moniker);
+ let get_instance_result = component_model.get_instance(node_path);
if get_instance_result.is_err() {
- return Some(RouteSourceError::RouteSegmentAbsMonikerNotFoundInTree(route_segment.clone()));
+ return Some(RouteSourceError::RouteSegmentNodePathNotFoundInTree(route_segment.clone()));
}
let instance = get_instance_result.unwrap();
let instance_url_str = instance.url();
@@ -507,9 +506,9 @@
json_or_unformatted(&route.route_match.target, "route target")
)
})?;
- if let RouteSegment::DeclareBy { abs_moniker, capability } = route_source {
+ if let RouteSegment::DeclareBy { node_path, capability } = route_source {
let source =
- Source { abs_moniker: abs_moniker.clone(), capability: capability.clone() };
+ Source { node_path: node_path.clone(), capability: capability.clone() };
let matches_result: Result<Vec<bool>> = vec![
route.route_match.source.capability.matches(capability),
route.route_match.source.capability.matches(&route_details),
@@ -548,20 +547,24 @@
) -> Result<HashMap<String, Vec<VerifyRouteSourcesResult>>> {
let mut results = HashMap::new();
for component_routes in config.component_routes.iter() {
- let target_moniker = &component_routes.target_node_path;
- let target_instance = component_model.get_instance(target_moniker).context(format!(
- "{}; target instance: {}",
- MISSING_TARGET_INSTANCE,
- target_moniker.clone()
- ))?;
+ let target_node_path = &component_routes.target_node_path;
+ let target_instance =
+ component_model.get_instance(target_node_path).context(format!(
+ "{}; target instance: {}",
+ MISSING_TARGET_INSTANCE,
+ target_node_path.clone()
+ ))?;
- let (_, routes_to_verify) =
- gather_routes(component_routes, target_instance.decl_for_testing(), target_moniker)
- .context(format!(
- "{}; target instance: {}",
- GATHER_FAILED,
- target_moniker.clone()
- ))?;
+ let (_, routes_to_verify) = gather_routes(
+ component_routes,
+ target_instance.decl_for_testing(),
+ target_node_path,
+ )
+ .context(format!(
+ "{}; target instance: {}",
+ GATHER_FAILED,
+ target_node_path.clone()
+ ))?;
let mut component_results = Vec::new();
for route in routes_to_verify.into_iter() {
@@ -578,7 +581,7 @@
}
}
- results.insert(target_moniker.to_string(), component_results);
+ results.insert(format!("/{}", target_node_path.as_vec().join("/")), component_results);
}
Ok(results)
}
@@ -617,7 +620,9 @@
verify::{collection::V2ComponentModel, collector::component_model::DEFAULT_ROOT_URL},
},
anyhow::Result,
- cm_fidl_analyzer::{component_model::ModelBuilderForAnalyzer, route::RouteSegment},
+ cm_fidl_analyzer::{
+ component_model::ModelBuilderForAnalyzer, node_path::NodePath, route::RouteSegment,
+ },
cm_rust::{
Availability, CapabilityName, CapabilityPath, CapabilityTypeName, ChildDecl,
ComponentDecl, DependencyType, DirectoryDecl, ExposeDirectoryDecl, ExposeSource,
@@ -627,7 +632,6 @@
fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_io as fio,
fuchsia_merkle::{Hash, HASH_SIZE},
maplit::{hashmap, hashset},
- moniker::{AbsoluteMoniker, AbsoluteMonikerBase},
routing::{
component_id_index::ComponentIdIndex, config::RuntimeConfig,
environment::RunnerRegistry,
@@ -1009,7 +1013,7 @@
// Vacuous request: Confirms that @root_url uses no input capabilities.
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::root(),
+ target_node_path: NodePath::absolute_from_vec(vec![]),
routes_to_skip: vec![],
routes_to_verify: vec![],
}],
@@ -1030,7 +1034,7 @@
// Request checking routes of a component instance that does not exist.
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/does:0/not:1/exist:2").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["does:0", "not:1", "exist:2"]),
routes_to_skip: vec![],
routes_to_verify: vec![],
}],
@@ -1056,7 +1060,7 @@
// are listed in `routes_to_skip` + `routes_to_verify`.
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![],
}],
@@ -1079,7 +1083,7 @@
// @two_dir_user_url.
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1121,7 +1125,7 @@
// the corresponding component manifest.
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1163,7 +1167,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
// Skip @root_url -> @two_dir_user_url route.
UseSpec {
@@ -1185,7 +1189,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1210,7 +1214,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[0].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[0].routes_to_verify[0].source.abs_moniker.clone(),
+ node_path: config.component_routes[0].routes_to_verify[0].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("provider_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1235,7 +1239,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
// Skip @root_url -> @two_dir_user_url route.
UseSpec {
@@ -1257,7 +1261,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match partial path with some (not all) routed
// subdirs.
@@ -1282,7 +1286,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[0].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[0].routes_to_verify[0].source.abs_moniker.clone(),
+ node_path: config.component_routes[0].routes_to_verify[0].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("provider_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1307,7 +1311,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![
// config.component_routes[0].routes_to_verify[0]:
@@ -1319,7 +1323,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1344,7 +1348,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1368,7 +1372,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[0].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[0].routes_to_verify[0].source.abs_moniker.clone(),
+ node_path: config.component_routes[0].routes_to_verify[0].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("root_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1379,7 +1383,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[1].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[0].routes_to_verify[1].source.abs_moniker.clone(),
+ node_path: config.component_routes[0].routes_to_verify[1].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("provider_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1406,13 +1410,13 @@
component_routes: vec![
// Match empty set of routes used by @root_url.
RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::root(),
+ target_node_path: NodePath::absolute_from_vec(vec![]),
routes_to_skip: vec![],
routes_to_verify: vec![],
},
// Match all routes used by @two_dir_user_url.
RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![
// config.component_routes[1].routes_to_verify[0]:
@@ -1424,7 +1428,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str(
@@ -1450,8 +1454,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider")
- .unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str(
@@ -1476,7 +1479,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[1].routes_to_verify[0].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[1].routes_to_verify[0].source.abs_moniker.clone(),
+ node_path: config.component_routes[1].routes_to_verify[0].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("root_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1487,7 +1490,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[1].routes_to_verify[1].clone(),
result: Ok(Source {
- abs_moniker: config.component_routes[1].routes_to_verify[1].source.abs_moniker.clone(),
+ node_path: config.component_routes[1].routes_to_verify[1].source.node_path.clone(),
capability: DirectoryDecl{
name: CapabilityName("provider_dir".to_string()),
source_path: Some(CapabilityPath::from_str("/data/to/user").unwrap()),
@@ -1512,7 +1515,7 @@
let source_name = "routed_from_provider";
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1561,7 +1564,7 @@
let source_name = "routed_from_provider";
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1611,7 +1614,7 @@
let bad_path = format!("{}/{}", bad_dirname, bad_basename);
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1653,7 +1656,7 @@
let dup_name = "/data/from/root";
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1693,7 +1696,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![UseSpec {
type_name: CapabilityTypeName::Directory,
path: Some(CapabilityPath::from_str("/data/from/root").unwrap()),
@@ -1707,7 +1710,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str(
@@ -1728,7 +1731,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str("/data/to/user").unwrap(),
@@ -1757,7 +1760,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
UseSpec {
type_name: CapabilityTypeName::Directory,
@@ -1780,7 +1783,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str(
@@ -1812,7 +1815,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![
// Intentional error: No match for `/data/from/root`. That
// way number of routes to skip + number of routes to verify
@@ -1833,7 +1836,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
path_prefix: Some(
CapabilityPath::from_str(
@@ -1865,7 +1868,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![
// config.component_routes[0].routes_to_verify[0]:
@@ -1877,7 +1880,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1902,7 +1905,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1949,7 +1952,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![
// config.component_routes[0].routes_to_verify[0]:
@@ -1961,7 +1964,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -1986,7 +1989,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -2033,7 +2036,7 @@
let components = &data_model.get::<Components>()?.entries;
let config = RouteSourcesConfig {
component_routes: vec![RouteSourcesSpec {
- target_node_path: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ target_node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
routes_to_skip: vec![],
routes_to_verify: vec![
// config.component_routes[0].routes_to_verify[0]:
@@ -2045,7 +2048,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -2070,7 +2073,7 @@
name: None,
},
source: SourceSpec {
- abs_moniker: AbsoluteMoniker::parse_str("/one_dir_provider").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["one_dir_provider"]),
capability: SourceDeclSpec {
// Match complete path with routed subdirs.
path_prefix: Some(
@@ -2095,7 +2098,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[0].clone(),
result: Err(RouteSourceError::RouteSegmentComponentFromUntrustedSource(RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
capability: UseDirectoryDecl{
source: UseSource::Parent,
source_name: CapabilityName("routed_from_root".to_string()),
@@ -2110,7 +2113,7 @@
VerifyRouteSourcesResult{
query: config.component_routes[0].routes_to_verify[1].clone(),
result: Err(RouteSourceError::RouteSegmentComponentFromUntrustedSource(RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/two_dir_user").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["two_dir_user"]),
capability: UseDirectoryDecl{
source: UseSource::Parent,
source_name: CapabilityName("routed_from_provider".to_string()),
diff --git a/src/security/scrutiny/plugins/src/verify/mod.rs b/src/security/scrutiny/plugins/src/verify/mod.rs
index 6d1f8ca..1c15b6c 100644
--- a/src/security/scrutiny/plugins/src/verify/mod.rs
+++ b/src/security/scrutiny/plugins/src/verify/mod.rs
@@ -16,12 +16,15 @@
route_sources::RouteSourcesController,
},
},
- cm_fidl_analyzer::route::{CapabilityRouteError, RouteSegment},
+ cm_fidl_analyzer::{
+ node_path::NodePath,
+ route::{CapabilityRouteError, RouteSegment},
+ serde_ext::ErrorWithMessage,
+ },
cm_rust::{CapabilityName, CapabilityTypeName},
- moniker::AbsoluteMoniker,
scrutiny::prelude::*,
serde::{Deserialize, Serialize},
- std::{collections::HashSet, error::Error, path::PathBuf, sync::Arc},
+ std::{collections::HashSet, path::PathBuf, sync::Arc},
};
pub use controller::route_sources::{
@@ -45,44 +48,6 @@
vec![PluginDescriptor::new("CorePlugin")]
);
-/// Error for use with serialization: Stores both structured error and message,
-/// and assesses equality using structured error.
-#[derive(Clone, Default, Deserialize, Serialize)]
-pub struct ErrorWithMessage<E: Clone + Error + Serialize> {
- pub error: E,
- #[serde(default)]
- pub message: String,
-}
-
-impl<E: Clone + Error + PartialEq + Serialize> PartialEq<ErrorWithMessage<E>>
- for ErrorWithMessage<E>
-{
- fn eq(&self, other: &Self) -> bool {
- // Ignore `message` when comparing.
- self.error == other.error
- }
-}
-
-impl<'de, E> From<E> for ErrorWithMessage<E>
-where
- E: Clone + Deserialize<'de> + Error + Serialize,
-{
- fn from(error: E) -> Self {
- Self::from(&error)
- }
-}
-
-impl<'de, E> From<&E> for ErrorWithMessage<E>
-where
- E: Clone + Deserialize<'de> + Error + Serialize,
-{
- fn from(error: &E) -> Self {
- let message = error.to_string();
- let error = error.clone();
- Self { error, message }
- }
-}
-
/// Top-level result type for `CapabilityRouteController` query result.
#[derive(Deserialize, Serialize)]
pub struct CapabilityRouteResults {
@@ -112,7 +77,7 @@
/// Error-severity results from `CapabilityRouteController`.
#[derive(Clone, Deserialize, PartialEq, Serialize)]
pub struct ErrorResult {
- pub using_node: AbsoluteMoniker,
+ pub using_node: NodePath,
pub capability: CapabilityName,
pub error: ErrorWithMessage<CapabilityRouteError>,
}
@@ -120,7 +85,7 @@
/// Warning-severity results from `CapabilityRouteController`.
#[derive(Clone, Deserialize, Serialize)]
pub struct WarningResult {
- pub using_node: AbsoluteMoniker,
+ pub using_node: NodePath,
pub capability: CapabilityName,
pub warning: ErrorWithMessage<CapabilityRouteError>,
}
@@ -128,7 +93,7 @@
/// Ok-severity results from `CapabilityRouteController`.
#[derive(Clone, Deserialize, Serialize)]
pub struct OkResult {
- pub using_node: AbsoluteMoniker,
+ pub using_node: NodePath,
pub capability: CapabilityName,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub route: Vec<RouteSegment>,
@@ -1213,7 +1178,7 @@
"target_path": "/",
"type": "directory"
},
- "abs_moniker": "/child"
+ "node_path": "/child"
},
{
"action": "offer_by",
@@ -1233,7 +1198,7 @@
"target_name": "good_dir",
"type": "directory"
},
- "abs_moniker": "/"
+ "node_path": "/"
},
{
"action": "declare_by",
@@ -1243,7 +1208,7 @@
"source_path": null,
"type": "directory"
},
- "abs_moniker": "/"
+ "node_path": "/"
}
],
"using_node": "/child"
diff --git a/tools/lib/cm_fidl_analyzer/BUILD.gn b/tools/lib/cm_fidl_analyzer/BUILD.gn
index ca8ddf0..99b2d03 100644
--- a/tools/lib/cm_fidl_analyzer/BUILD.gn
+++ b/tools/lib/cm_fidl_analyzer/BUILD.gn
@@ -36,7 +36,9 @@
"src/component_model.rs",
"src/environment.rs",
"src/lib.rs",
+ "src/node_path.rs",
"src/route.rs",
+ "src/serde_ext.rs",
]
test_deps = [
"//src/sys/lib/cm_rust/testing",
diff --git a/tools/lib/cm_fidl_analyzer/src/component_instance.rs b/tools/lib/cm_fidl_analyzer/src/component_instance.rs
index 33d62133..4e137cc 100644
--- a/tools/lib/cm_fidl_analyzer/src/component_instance.rs
+++ b/tools/lib/cm_fidl_analyzer/src/component_instance.rs
@@ -6,12 +6,13 @@
crate::{
component_model::{BuildAnalyzerModelError, Child},
environment::EnvironmentForAnalyzer,
+ node_path::NodePath,
route::RouteMapper,
},
async_trait::async_trait,
cm_moniker::{InstancedAbsoluteMoniker, InstancedChildMoniker},
cm_rust::{CapabilityDecl, CollectionDecl, ComponentDecl, ExposeDecl, OfferDecl, UseDecl},
- moniker::{AbsoluteMoniker, AbsoluteMonikerBase, ChildMoniker},
+ moniker::{AbsoluteMoniker, AbsoluteMonikerBase, ChildMoniker, ChildMonikerBase},
routing::{
capability_source::{BuiltinCapabilities, NamespaceCapabilities},
component_id_index::ComponentIdIndex,
@@ -52,6 +53,13 @@
&self.decl
}
+ /// Returns a representation of the instance's position in the component instance tree.
+ pub fn node_path(&self) -> NodePath {
+ NodePath::absolute_from_vec(
+ self.abs_moniker.path().into_iter().map(|m| m.as_str()).collect(),
+ )
+ }
+
// Creates a new root component instance.
pub(crate) fn new_root(
decl: ComponentDecl,
diff --git a/tools/lib/cm_fidl_analyzer/src/component_model.rs b/tools/lib/cm_fidl_analyzer/src/component_model.rs
index ca393b5..a75822a 100644
--- a/tools/lib/cm_fidl_analyzer/src/component_model.rs
+++ b/tools/lib/cm_fidl_analyzer/src/component_model.rs
@@ -6,6 +6,7 @@
crate::{
component_instance::{ComponentInstanceForAnalyzer, TopInstanceForAnalyzer},
match_absolute_component_urls,
+ node_path::NodePath,
route::{RouteMap, RouteSegment, VerifyRouteResult},
PkgUrlMatch,
},
@@ -138,25 +139,27 @@
}
fn load_dynamic_components(
- input: HashMap<AbsoluteMoniker, (AbsoluteComponentUrl, Option<String>)>,
+ input: HashMap<NodePath, (AbsoluteComponentUrl, Option<String>)>,
) -> (HashMap<AbsoluteMoniker, Vec<Child>>, Vec<anyhow::Error>) {
let mut errors: Vec<anyhow::Error> = vec![];
let mut dynamic_components: HashMap<AbsoluteMoniker, Vec<Child>> = HashMap::new();
- for (abs_moniker, (url, environment)) in input.into_iter() {
- let mut moniker_vec = abs_moniker.path().clone();
- let child_moniker = moniker_vec.pop();
- if child_moniker.is_none() {
+ for (node_path, (url, environment)) in input.into_iter() {
+ let mut moniker_vec = node_path.as_vec();
+ let child_moniker_str = moniker_vec.pop();
+ if child_moniker_str.is_none() {
errors.push(
BuildAnalyzerModelError::DynamicComponentInvalidMoniker(url.to_string()).into(),
);
continue;
}
+ let child_moniker_str = child_moniker_str.unwrap();
- let child_moniker = child_moniker.unwrap();
+ let abs_moniker: AbsoluteMoniker = moniker_vec.into();
+ let child_moniker: ChildMoniker = child_moniker_str.into();
if child_moniker.collection.is_none() {
errors.push(
BuildAnalyzerModelError::DynamicComponentWithoutCollection(
- abs_moniker.to_string(),
+ node_path.to_string(),
url.to_string(),
)
.into(),
@@ -170,10 +173,11 @@
children.push(Child { child_moniker, url, environment });
}
Err(_) => {
+ let node_path: NodePath = abs_moniker.into();
errors.push(
BuildAnalyzerModelError::MalformedUrl(
url.to_string(),
- abs_moniker.to_string(),
+ node_path.to_string(),
)
.into(),
);
@@ -201,7 +205,7 @@
pub fn build_with_dynamic_components(
self,
- dynamic_components: HashMap<AbsoluteMoniker, (AbsoluteComponentUrl, Option<String>)>,
+ dynamic_components: HashMap<NodePath, (AbsoluteComponentUrl, Option<String>)>,
decls_by_url: HashMap<Url, ComponentDecl>,
runtime_config: Arc<RuntimeConfig>,
component_id_index: Arc<ComponentIdIndex>,
@@ -273,7 +277,9 @@
&mut result,
);
- model.instances.insert(root_instance.abs_moniker().clone(), root_instance);
+ model
+ .instances
+ .insert(NodePath::from(root_instance.abs_moniker().clone()), root_instance);
result.model = Some(Arc::new(model));
}
@@ -324,7 +330,7 @@
if child.child_moniker.name.is_empty() {
result.errors.push(anyhow!(BuildAnalyzerModelError::InvalidChildDecl(
absolute_url.to_string(),
- instance.abs_moniker().to_string(),
+ NodePath::from(instance.abs_moniker().clone()).to_string(),
)));
continue;
}
@@ -359,7 +365,7 @@
);
model.instances.insert(
- child_instance.abs_moniker().clone(),
+ NodePath::from(child_instance.abs_moniker().clone()),
child_instance,
);
}
@@ -372,7 +378,7 @@
result.errors.push(anyhow!(
BuildAnalyzerModelError::ComponentDeclNotFound(
absolute_url.to_string(),
- instance.abs_moniker().to_string(),
+ NodePath::from(instance.abs_moniker().clone()).to_string(),
)
));
}
@@ -393,7 +399,7 @@
) -> Result<Url, BuildAnalyzerModelError> {
let err = BuildAnalyzerModelError::MalformedUrl(
instance.url().to_string(),
- instance.abs_moniker().to_string(),
+ instance.node_path().to_string(),
);
match Url::parse(child_url) {
@@ -485,11 +491,11 @@
}
/// `ComponentModelForAnalyzer` owns a representation of the v2 component graph and
-/// supports lookup of component instances by `AbsoluteMoniker`.
+/// supports lookup of component instances by `NodePath`.
#[derive(Default)]
pub struct ComponentModelForAnalyzer {
top_instance: Arc<TopInstanceForAnalyzer>,
- instances: HashMap<AbsoluteMoniker, Arc<ComponentInstanceForAnalyzer>>,
+ instances: HashMap<NodePath, Arc<ComponentInstanceForAnalyzer>>,
policy_checker: GlobalPolicyChecker,
component_id_index: Arc<ComponentIdIndex>,
}
@@ -503,18 +509,20 @@
pub fn get_root_instance(
self: &Arc<Self>,
) -> Result<Arc<ComponentInstanceForAnalyzer>, ComponentInstanceError> {
- self.get_instance(&AbsoluteMoniker::root())
+ self.get_instance(&NodePath::absolute_from_vec(vec![]))
}
/// Returns the component instance corresponding to `id` if it is present in the model, or an
/// `InstanceNotFound` error if not.
pub fn get_instance(
self: &Arc<Self>,
- abs_moniker: &AbsoluteMoniker,
+ id: &NodePath,
) -> Result<Arc<ComponentInstanceForAnalyzer>, ComponentInstanceError> {
- match self.instances.get(abs_moniker) {
+ match self.instances.get(id) {
Some(instance) => Ok(Arc::clone(instance)),
- None => Err(ComponentInstanceError::instance_not_found(abs_moniker.clone())),
+ None => Err(ComponentInstanceError::instance_not_found(
+ AbsoluteMoniker::parse_str(&id.to_string()).unwrap(),
+ )),
}
}
@@ -682,7 +690,7 @@
Ok(()) => {
for route in routes.into_iter() {
results.push(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: capability.clone(),
result: Ok(route.into()),
});
@@ -690,14 +698,14 @@
}
Err(err) => {
results.push(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: capability.clone(),
result: Err(err.into()),
});
}
},
(Err(err), capability) => results.push(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: capability.clone(),
result: Err(err.into()),
}),
@@ -723,7 +731,7 @@
Err(err) => Err(AnalyzerModelError::from(err).into()),
};
Some(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: expose_decl.target_name().clone(),
result,
})
@@ -742,20 +750,20 @@
match program_decl.runner {
Some(ref runner) => {
let mut route = RouteMap::from_segments(vec![RouteSegment::RequireRunner {
- abs_moniker: target.abs_moniker().clone(),
+ node_path: target.node_path(),
runner: runner.clone(),
}]);
match Self::route_capability_sync(RouteRequest::Runner(runner.clone()), target) {
Ok((_source, mut segments)) => {
route.append(&mut segments);
Some(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: runner.clone(),
result: Ok(route.into()),
})
}
Err(err) => Some(VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: runner.clone(),
result: Err(AnalyzerModelError::from(err).into()),
}),
@@ -775,7 +783,7 @@
let url = Url::parse(target.url()).expect("failed to parse target URL");
let scheme = url.scheme();
let mut route = vec![RouteSegment::RequireResolver {
- abs_moniker: target.abs_moniker().clone(),
+ node_path: target.node_path(),
scheme: scheme.to_string(),
}];
@@ -786,12 +794,12 @@
&instance,
) {
Ok((_source, route)) => VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: resolver.resolver,
result: Ok(route.into()),
},
Err(err) => VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: resolver.resolver,
result: Err(AnalyzerModelError::from(err).into()),
},
@@ -803,25 +811,25 @@
let mut route = RouteMap::new();
route.push(RouteSegment::ProvideAsBuiltin { capability: decl });
VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: resolver.resolver,
result: Ok(route.into()),
}
}
Err(err) => VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: resolver.resolver,
result: Err(err.into()),
},
}
}
Ok(None) => VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: "".into(),
result: Err(AnalyzerModelError::MissingResolverForScheme(scheme.to_string()).into()),
},
Err(err) => VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: "".into(),
result: Err(AnalyzerModelError::from(err).into()),
},
@@ -835,7 +843,7 @@
Err(err) => Err(err.into()),
};
VerifyRouteResult {
- using_node: target.abs_moniker().clone(),
+ using_node: target.node_path(),
capability: check_route.capability,
result: check_result,
}
@@ -1088,7 +1096,7 @@
mod tests {
use {
super::ModelBuilderForAnalyzer,
- crate::{environment::BOOT_SCHEME, ComponentModelForAnalyzer},
+ crate::{environment::BOOT_SCHEME, node_path::NodePath, ComponentModelForAnalyzer},
anyhow::Result,
cm_moniker::InstancedAbsoluteMoniker,
cm_rust::{
@@ -1155,17 +1163,18 @@
let model = build_model_result.model.unwrap();
assert_eq!(model.len(), 2);
- let root_instance = model.get_instance(&AbsoluteMoniker::root()).expect("root instance");
+ let root_instance =
+ model.get_instance(&NodePath::absolute_from_vec(vec![])).expect("root instance");
let child_instance = model
- .get_instance(&AbsoluteMoniker::parse_str("/child").unwrap())
+ .get_instance(&NodePath::absolute_from_vec(vec!["child"]))
.expect("child instance");
- let other_moniker = AbsoluteMoniker::parse_str("/other").unwrap();
- let get_other_result = model.get_instance(&other_moniker);
+ let other_id = NodePath::absolute_from_vec(vec!["other"]);
+ let get_other_result = model.get_instance(&other_id);
assert_eq!(
get_other_result.err().unwrap().to_string(),
ComponentInstanceError::instance_not_found(
- AbsoluteMoniker::parse_str(&other_moniker.to_string()).unwrap()
+ AbsoluteMoniker::parse_str(&other_id.to_string()).unwrap()
)
.to_string()
);
@@ -1261,7 +1270,7 @@
assert_eq!(model.len(), 2);
let child_instance = model
- .get_instance(&AbsoluteMoniker::parse_str("/child").unwrap())
+ .get_instance(&NodePath::absolute_from_vec(vec!["child"]))
.expect("child instance");
assert_eq!(child_instance.url(), absolute_child_url.as_str());
@@ -1288,7 +1297,8 @@
let model = build_model_result.model.unwrap();
assert_eq!(model.len(), 1);
- let root_instance = model.get_instance(&AbsoluteMoniker::root()).expect("root instance");
+ let root_instance =
+ model.get_instance(&NodePath::absolute_from_vec(vec![])).expect("root instance");
// Panics if the future returned by `route_capability` was not ready immediately.
// If no panic, discard the result.
@@ -1327,7 +1337,8 @@
let model = build_model_result.model.unwrap();
assert_eq!(model.len(), 1);
- let root_instance = model.get_instance(&AbsoluteMoniker::root()).expect("root instance");
+ let root_instance =
+ model.get_instance(&NodePath::absolute_from_vec(vec![])).expect("root instance");
// Panics if the future returned by `route_storage_and_backing_directory` was not ready immediately.
// If no panic, discard the result.
@@ -1405,7 +1416,7 @@
assert_eq!(model.len(), 2);
let child_instance = model
- .get_instance(&AbsoluteMoniker::parse_str("/child").unwrap())
+ .get_instance(&NodePath::absolute_from_vec(vec!["child"]))
.expect("child instance");
let get_child_runner_result = child_instance
diff --git a/tools/lib/cm_fidl_analyzer/src/environment.rs b/tools/lib/cm_fidl_analyzer/src/environment.rs
index 9b05f50..51d1a60 100644
--- a/tools/lib/cm_fidl_analyzer/src/environment.rs
+++ b/tools/lib/cm_fidl_analyzer/src/environment.rs
@@ -6,6 +6,7 @@
crate::{
component_instance::{ComponentInstanceForAnalyzer, TopInstanceForAnalyzer},
component_model::{BuildAnalyzerModelError, Child},
+ node_path::NodePath,
},
cm_rust::{EnvironmentDecl, RegistrationSource, ResolverRegistration},
fidl_fuchsia_component_internal as component_internal,
@@ -151,7 +152,7 @@
.ok_or(BuildAnalyzerModelError::EnvironmentNotFound(
child_env_name.clone(),
child.child_moniker.name.clone(),
- parent.abs_moniker().to_string(),
+ NodePath::from(parent.abs_moniker().clone()).to_string(),
))?;
Self::new_from_decl(parent, env_decl)
}
diff --git a/tools/lib/cm_fidl_analyzer/src/lib.rs b/tools/lib/cm_fidl_analyzer/src/lib.rs
index eeffc33..350effd 100644
--- a/tools/lib/cm_fidl_analyzer/src/lib.rs
+++ b/tools/lib/cm_fidl_analyzer/src/lib.rs
@@ -5,7 +5,9 @@
pub mod component_instance;
pub mod component_model;
pub mod environment;
+pub mod node_path;
pub mod route;
+pub mod serde_ext;
use {
crate::{
@@ -223,7 +225,7 @@
&mut self,
instance: &Arc<ComponentInstanceForAnalyzer>,
) -> Result<(), anyhow::Error> {
- self.visited.push((instance.abs_moniker().to_string(), instance.url().to_string()));
+ self.visited.push((instance.node_path().to_string(), instance.url().to_string()));
Ok(())
}
}
diff --git a/tools/lib/cm_fidl_analyzer/src/node_path.rs b/tools/lib/cm_fidl_analyzer/src/node_path.rs
new file mode 100644
index 0000000..e3adb79
--- /dev/null
+++ b/tools/lib/cm_fidl_analyzer/src/node_path.rs
@@ -0,0 +1,83 @@
+// 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 {
+ moniker::{AbsoluteMoniker, AbsoluteMonikerBase, ChildMoniker, ChildMonikerBase},
+ std::{fmt, fmt::Display},
+};
+
+/// A representation of a component's position in the component topology. The last segment of
+/// a component's `NodePath` is its `ChildMoniker` as designated by its parent component,
+/// and the prefix is the parent component's `NodePath`.
+#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
+pub struct NodePath(Vec<ChildMoniker>);
+
+impl NodePath {
+ pub fn new(monikers: Vec<ChildMoniker>) -> Self {
+ let mut node_path = NodePath::default();
+ node_path.0 = monikers;
+ node_path
+ }
+
+ /// Construct NodePath from string references that correspond to parsable
+ /// `ChildMoniker` instances.
+ pub fn absolute_from_vec(vec: Vec<&str>) -> Self {
+ let abs_moniker: AbsoluteMoniker = vec.into();
+ Self::new(abs_moniker.path().clone())
+ }
+
+ /// Returns a new `NodePath` which extends `self` by appending `moniker` at the end of the path.
+ pub fn extended(&self, moniker: ChildMoniker) -> Self {
+ let mut node_path = NodePath::new(self.0.clone());
+ node_path.0.push(moniker);
+ node_path
+ }
+
+ /// Construct string references that correspond to underlying
+ /// `ChildMoniker` instances.
+ pub fn as_vec(&self) -> Vec<&str> {
+ self.0.iter().map(|moniker| moniker.as_str()).collect()
+ }
+}
+
+impl Display for NodePath {
+ // Displays a `NodePath` as a slash-separated path.
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.0.is_empty() {
+ return write!(f, "/");
+ }
+ let mut path_string = "".to_owned();
+ for moniker in self.0.iter() {
+ path_string.push('/');
+ path_string.push_str(moniker.as_str());
+ }
+ write!(f, "{}", path_string)
+ }
+}
+
+impl From<AbsoluteMoniker> for NodePath {
+ fn from(moniker: AbsoluteMoniker) -> Self {
+ Self::new(moniker.path().clone())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ // Tests the `extended()` and `to_string()` methods of `NodePath`.
+ #[test]
+ fn node_path_operations() {
+ let empty_node_path = NodePath::default();
+ assert_eq!(empty_node_path.to_string(), "/");
+
+ let foo_moniker = ChildMoniker::new("foo".to_string(), None);
+ let foo_node_path = empty_node_path.extended(foo_moniker);
+ assert_eq!(foo_node_path.to_string(), "/foo");
+
+ let bar_moniker = ChildMoniker::new("bar".to_string(), None);
+ let bar_node_path = foo_node_path.extended(bar_moniker);
+ assert_eq!(bar_node_path.to_string(), "/foo/bar");
+ }
+}
diff --git a/tools/lib/cm_fidl_analyzer/src/route.rs b/tools/lib/cm_fidl_analyzer/src/route.rs
index 6e7a0de..5c8c23f 100644
--- a/tools/lib/cm_fidl_analyzer/src/route.rs
+++ b/tools/lib/cm_fidl_analyzer/src/route.rs
@@ -3,7 +3,10 @@
// found in the LICENSE file.
use {
- crate::component_model::{AnalyzerModelError, BuildAnalyzerModelError},
+ crate::{
+ component_model::{AnalyzerModelError, BuildAnalyzerModelError},
+ node_path::NodePath,
+ },
cm_rust::{CapabilityDecl, CapabilityName, ExposeDecl, OfferDecl, UseDecl},
fuchsia_zircon_status as zx_status,
moniker::AbsoluteMoniker,
@@ -15,7 +18,7 @@
/// A summary of a specific capability route and the outcome of verification.
#[derive(Clone, Debug, PartialEq)]
pub struct VerifyRouteResult {
- pub using_node: AbsoluteMoniker,
+ pub using_node: NodePath,
pub capability: CapabilityName,
pub result: Result<Vec<RouteSegment>, CapabilityRouteError>,
}
@@ -25,55 +28,55 @@
pub enum RouteSegment {
/// A `ComponentNode` uses the routed capability.
UseBy {
- /// The `AbsoluteMoniker` of the using `ComponentNode`.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the using `ComponentNode`.
+ node_path: NodePath,
/// The use declaration from the `ComponentNode`'s manifest.
capability: UseDecl,
},
/// A `ComponentNode` requires a runner in its `ProgramDecl`.
RequireRunner {
- /// The `AbsoluteMoniker` of the component instance that requires the runner.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the component instance that requires the runner.
+ node_path: NodePath,
/// The name of the required runner.
runner: CapabilityName,
},
/// A `ComponentNode` requires the resolver capability to resolve a child component URL.
RequireResolver {
- /// The `AbsoluteMoniker` of the component node that requires the resolver.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the component node that requires the resolver.
+ node_path: NodePath,
/// The URL scheme of the resolver.
scheme: String,
},
/// A `ComponentNode` offers the routed capability.
OfferBy {
- /// The `AbsoluteMoniker` of the offering `ComponentNode`.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the offering `ComponentNode`.
+ node_path: NodePath,
/// The offer declaration from the `ComponentNode`'s manifest.
capability: OfferDecl,
},
/// A `ComponentNode` exposes the routed capability.
ExposeBy {
- /// The `AbsoluteMoniker` of the offering `ComponentNode`.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the offering `ComponentNode`.
+ node_path: NodePath,
/// The expose declaration from the `ComponentNode`'s manifest.
capability: ExposeDecl,
},
/// A `ComponentNode` declares the routed capability.
DeclareBy {
- /// The `AbsoluteMoniker` of the declaring `ComponentNode`.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the declaring `ComponentNode`.
+ node_path: NodePath,
/// The capability declaration from the `ComponentNode`'s manifest.
capability: CapabilityDecl,
},
RegisterBy {
- /// The `AbsoluteMoniker` of the `ComponentNode` that registered the capability.
- abs_moniker: AbsoluteMoniker,
+ /// The `NodePath` of the `ComponentNode` that registered the capability.
+ node_path: NodePath,
/// The registration declaration. For runner and resolver registrations, this
/// appears directly in the `ComponentNode`'s manifest. For storage-backing
/// directories, this is derived from the storage capability's `StorageDecl`.
@@ -104,15 +107,15 @@
}
impl RouteSegment {
- pub fn abs_moniker<'a>(&'a self) -> Option<&'a AbsoluteMoniker> {
+ pub fn node_path<'a>(&'a self) -> Option<&'a NodePath> {
match self {
- Self::UseBy { abs_moniker, .. }
- | Self::RequireRunner { abs_moniker, .. }
- | Self::RequireResolver { abs_moniker, .. }
- | Self::OfferBy { abs_moniker, .. }
- | Self::ExposeBy { abs_moniker, .. }
- | Self::DeclareBy { abs_moniker, .. }
- | Self::RegisterBy { abs_moniker, .. } => Some(abs_moniker),
+ Self::UseBy { node_path, .. }
+ | Self::RequireRunner { node_path, .. }
+ | Self::RequireResolver { node_path, .. }
+ | Self::OfferBy { node_path, .. }
+ | Self::ExposeBy { node_path, .. }
+ | Self::DeclareBy { node_path, .. }
+ | Self::RegisterBy { node_path, .. } => Some(node_path),
Self::ProvideFromFramework { .. }
| Self::ProvideAsBuiltin { .. }
| Self::ProvideFromNamespace { .. }
@@ -217,15 +220,24 @@
type RouteMap = RouteMap;
fn add_use(&mut self, abs_moniker: AbsoluteMoniker, use_decl: UseDecl) {
- self.route.push(RouteSegment::UseBy { abs_moniker, capability: use_decl })
+ self.route.push(RouteSegment::UseBy {
+ node_path: NodePath::from(abs_moniker),
+ capability: use_decl,
+ })
}
fn add_offer(&mut self, abs_moniker: AbsoluteMoniker, offer_decl: OfferDecl) {
- self.route.push(RouteSegment::OfferBy { abs_moniker, capability: offer_decl })
+ self.route.push(RouteSegment::OfferBy {
+ node_path: NodePath::from(abs_moniker),
+ capability: offer_decl,
+ })
}
fn add_expose(&mut self, abs_moniker: AbsoluteMoniker, expose_decl: ExposeDecl) {
- self.route.push(RouteSegment::ExposeBy { abs_moniker, capability: expose_decl })
+ self.route.push(RouteSegment::ExposeBy {
+ node_path: NodePath::from(abs_moniker),
+ capability: expose_decl,
+ })
}
fn add_registration(
@@ -233,7 +245,10 @@
abs_moniker: AbsoluteMoniker,
registration_decl: RegistrationDecl,
) {
- self.route.push(RouteSegment::RegisterBy { abs_moniker, capability: registration_decl })
+ self.route.push(RouteSegment::RegisterBy {
+ node_path: NodePath::from(abs_moniker),
+ capability: registration_decl,
+ })
}
fn add_component_capability(
@@ -241,7 +256,10 @@
abs_moniker: AbsoluteMoniker,
capability_decl: CapabilityDecl,
) {
- self.route.push(RouteSegment::DeclareBy { abs_moniker, capability: capability_decl })
+ self.route.push(RouteSegment::DeclareBy {
+ node_path: NodePath::from(abs_moniker),
+ capability: capability_decl,
+ })
}
fn add_framework_capability(&mut self, capability_name: CapabilityName) {
diff --git a/tools/lib/cm_fidl_analyzer/src/serde_ext.rs b/tools/lib/cm_fidl_analyzer/src/serde_ext.rs
new file mode 100644
index 0000000..4fcd242
--- /dev/null
+++ b/tools/lib/cm_fidl_analyzer/src/serde_ext.rs
@@ -0,0 +1,105 @@
+// 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 {
+ crate::node_path::NodePath,
+ serde::{
+ de::{self, Deserializer, Visitor},
+ Deserialize, Serialize, Serializer,
+ },
+ std::{error::Error, fmt},
+};
+
+/// Serialize `NodePath` into a path-like slash-separated a string
+/// representation of the underlying child monikers.
+//
+/// Example: "/alpha:2/beta:0/gamma:1".
+impl Serialize for NodePath {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ let path = format!("/{}", self.as_vec().join("/"));
+ serializer.serialize_str(&path)
+ }
+}
+
+struct NodePathVisitor;
+
+/// Deserialize `NodePath` from path-like slash-separated string of child
+/// monikers.
+impl<'de> Visitor<'de> for NodePathVisitor {
+ type Value = NodePath;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+ formatter.write_str("A component tree node path")
+ }
+
+ fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ Ok(NodePath::new(
+ value
+ .split("/")
+ .filter_map(
+ |component| {
+ if component.is_empty() {
+ None
+ } else {
+ Some(component.into())
+ }
+ },
+ )
+ .collect(),
+ ))
+ }
+}
+
+impl<'de> Deserialize<'de> for NodePath {
+ fn deserialize<D>(deserializer: D) -> Result<NodePath, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ deserializer.deserialize_str(NodePathVisitor)
+ }
+}
+
+/// Error for use with serialization: Stores both structured error and message,
+/// and assesses equality using structured error.
+#[derive(Clone, Default, Deserialize, Serialize)]
+pub struct ErrorWithMessage<E: Clone + Error + Serialize> {
+ pub error: E,
+ #[serde(default)]
+ pub message: String,
+}
+
+impl<E: Clone + Error + PartialEq + Serialize> PartialEq<ErrorWithMessage<E>>
+ for ErrorWithMessage<E>
+{
+ fn eq(&self, other: &Self) -> bool {
+ // Ignore `message` when comparing.
+ self.error == other.error
+ }
+}
+
+impl<'de, E> From<E> for ErrorWithMessage<E>
+where
+ E: Clone + Deserialize<'de> + Error + Serialize,
+{
+ fn from(error: E) -> Self {
+ Self::from(&error)
+ }
+}
+
+impl<'de, E> From<&E> for ErrorWithMessage<E>
+where
+ E: Clone + Deserialize<'de> + Error + Serialize,
+{
+ fn from(error: &E) -> Self {
+ let message = error.to_string();
+ let error = error.clone();
+ Self { error, message }
+ }
+}
diff --git a/tools/lib/cm_fidl_analyzer/tests/src/routing.rs b/tools/lib/cm_fidl_analyzer/tests/src/routing.rs
index 94a3cd2..7656052 100644
--- a/tools/lib/cm_fidl_analyzer/tests/src/routing.rs
+++ b/tools/lib/cm_fidl_analyzer/tests/src/routing.rs
@@ -10,6 +10,7 @@
component_instance::ComponentInstanceForAnalyzer,
component_model::{AnalyzerModelError, ComponentModelForAnalyzer, ModelBuilderForAnalyzer},
environment::{BOOT_RESOLVER_NAME, BOOT_SCHEME},
+ node_path::NodePath,
route::{CapabilityRouteError, RouteSegment, VerifyRouteResult},
},
cm_rust::{
@@ -468,14 +469,14 @@
type C = ComponentInstanceForAnalyzer;
async fn check_use(&self, moniker: AbsoluteMoniker, check: CheckUse) {
- let target = self.model.get_instance(&moniker).expect("target instance not found");
+ let target_id = NodePath::new(moniker.path().clone());
+ let target = self.model.get_instance(&target_id).expect("target instance not found");
let scope =
if let CheckUse::EventStream { path: _, ref scope, name: _, expected_res: _ } = check {
Some(scope.clone())
} else {
None
};
-
let (find_decl, expected) = self.find_matching_use(check, target.decl_for_testing());
// If `find_decl` is not OK, check that `expected` has a matching error.
@@ -524,7 +525,8 @@
}
async fn check_use_exposed_dir(&self, moniker: AbsoluteMoniker, check: CheckUse) {
- let target = self.model.get_instance(&moniker).expect("target instance not found");
+ let target =
+ self.model.get_instance(&NodePath::from(moniker)).expect("target instance not found");
let (find_decl, expected) = self.find_matching_expose(check, target.decl_for_testing());
@@ -569,7 +571,7 @@
&self,
moniker: &AbsoluteMoniker,
) -> Result<Arc<ComponentInstanceForAnalyzer>, anyhow::Error> {
- self.model.get_instance(&moniker).map_err(|err| anyhow!(err))
+ self.model.get_instance(&NodePath::from(moniker.clone())).map_err(|err| anyhow!(err))
}
// File and directory operations
@@ -1374,7 +1376,7 @@
let result = test.model.check_resolver(&b_component);
assert!(result.result.is_ok());
- assert_eq!(result.using_node, AbsoluteMoniker::parse_str("/b").unwrap());
+ assert_eq!(result.using_node, NodePath::absolute_from_vec(vec!["b"]));
assert_eq!(result.capability, "base");
}
@@ -1533,15 +1535,15 @@
route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_decl
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Protocol(protocol_decl)
}
]
@@ -1589,13 +1591,16 @@
assert_eq!(
route_map,
vec![
- RouteSegment::UseBy { abs_moniker: AbsoluteMoniker::root(), capability: use_decl },
+ RouteSegment::UseBy {
+ node_path: NodePath::absolute_from_vec(vec![]),
+ capability: use_decl
+ },
RouteSegment::ExposeBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: expose_decl
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: CapabilityDecl::Protocol(protocol_decl)
}
]
@@ -1630,9 +1635,12 @@
assert_eq!(
route_map,
vec![
- RouteSegment::UseBy { abs_moniker: AbsoluteMoniker::root(), capability: use_decl },
+ RouteSegment::UseBy {
+ node_path: NodePath::absolute_from_vec(vec![]),
+ capability: use_decl
+ },
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Protocol(protocol_decl)
}
]
@@ -1724,23 +1732,23 @@
route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/c").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["c"]),
capability: use_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: a_offer_decl
},
RouteSegment::ExposeBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: b_expose_decl
},
RouteSegment::ExposeBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b/d").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b", "d"]),
capability: d_expose_decl
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b/d").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b", "d"]),
capability: CapabilityDecl::Directory(directory_decl),
}
]
@@ -1803,15 +1811,15 @@
route_map,
vec![
RouteSegment::RequireRunner {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
runner: "hobbit".into(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Runner(runner_reg)
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Runner(runner_decl)
},
]
@@ -1881,15 +1889,15 @@
storage_route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_storage_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_storage_decl
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Storage(storage_decl.clone())
}
]
@@ -1898,11 +1906,11 @@
backing_directory_route_map,
vec![
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Storage(storage_decl.into())
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Directory(directory_decl)
}
]
@@ -1987,11 +1995,11 @@
event_route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_event_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_event_decl
},
RouteSegment::ProvideFromFramework { capability: "started".into() }
@@ -2008,11 +2016,11 @@
event_source_route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_event_source_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_event_source_decl
},
RouteSegment::ProvideAsBuiltin { capability: event_source_decl }
@@ -2071,11 +2079,11 @@
route_map,
vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_decl
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_decl
},
RouteSegment::ProvideFromNamespace { capability: capability_decl }
@@ -2142,25 +2150,25 @@
let route_map = test.model.check_resolver(&b_component);
- assert_eq!(route_map.using_node, AbsoluteMoniker::parse_str("/b").unwrap(),);
+ assert_eq!(route_map.using_node, NodePath::absolute_from_vec(vec!["b"]));
assert_eq!(route_map.capability, "base");
assert_eq!(
route_map.result.clone().expect("expected OK route"),
vec![
RouteSegment::RequireResolver {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
scheme: "base".to_string(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Resolver(registration_decl)
},
RouteSegment::ExposeBy {
- abs_moniker: AbsoluteMoniker::parse_str("/c").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["c"]),
capability: expose_decl
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::parse_str("/c").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["c"]),
capability: CapabilityDecl::Resolver(resolver_decl)
}
]
@@ -2220,21 +2228,21 @@
let route_map = test.model.check_resolver(&c_component);
- assert_eq!(route_map.using_node, AbsoluteMoniker::parse_str("/b/c").unwrap());
+ assert_eq!(route_map.using_node, NodePath::absolute_from_vec(vec!["b", "c"]));
assert_eq!(route_map.capability, "base");
assert_eq!(
route_map.result.clone().expect("expected OK route"),
vec![
RouteSegment::RequireResolver {
- abs_moniker: AbsoluteMoniker::parse_str("/b/c").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b", "c"]),
scheme: "base".to_string(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Resolver(registration_decl)
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Resolver(resolver_decl)
}
]
@@ -2275,13 +2283,13 @@
let route_map = test.model.check_resolver(&b_component);
- assert_eq!(route_map.using_node, AbsoluteMoniker::parse_str("/b").unwrap());
+ assert_eq!(route_map.using_node, NodePath::absolute_from_vec(vec!["b"]));
assert_eq!(route_map.capability, BOOT_RESOLVER_NAME);
assert_eq!(
route_map.result.clone().expect("expected OK route"),
vec![
RouteSegment::RequireResolver {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
scheme: BOOT_SCHEME.to_string(),
},
RouteSegment::ProvideAsBuiltin { capability: boot_resolver_decl }
@@ -2333,21 +2341,21 @@
let route_map = test.model.check_resolver(&b_component);
- assert_eq!(route_map.using_node, AbsoluteMoniker::parse_str("/b").unwrap());
+ assert_eq!(route_map.using_node, NodePath::absolute_from_vec(vec!["b"]));
assert_eq!(route_map.capability, "test");
assert_eq!(
route_map.result.clone().expect("expected OK route"),
vec![
RouteSegment::RequireResolver {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
scheme: "test".to_string(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Resolver(resolver_registration)
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Resolver(resolver_decl)
}
]
@@ -2386,7 +2394,7 @@
route_map,
vec![
RouteSegment::RequireRunner {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
runner: "elf".into(),
},
RouteSegment::ProvideAsBuiltin { capability: elf_runner_decl },
@@ -2522,19 +2530,19 @@
assert_eq!(
directories,
&vec![VerifyRouteResult {
- using_node: AbsoluteMoniker::parse_str("/b").unwrap(),
+ using_node: NodePath::absolute_from_vec(vec!["b"]),
capability: "bar_data".into(),
result: Ok(vec![
RouteSegment::UseBy {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
capability: use_directory_decl,
},
RouteSegment::OfferBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: offer_directory_decl,
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Directory(directory_decl),
}
])
@@ -2545,19 +2553,19 @@
assert_eq!(
runners,
&vec![VerifyRouteResult {
- using_node: AbsoluteMoniker::parse_str("/b").unwrap(),
+ using_node: NodePath::absolute_from_vec(vec!["b"]),
capability: "dwarf".into(),
result: Ok(vec![
RouteSegment::RequireRunner {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
runner: "dwarf".into(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Runner(runner_registration_decl)
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Runner(runner_decl)
}
])
@@ -2569,19 +2577,19 @@
assert_eq!(
resolvers,
&vec![VerifyRouteResult {
- using_node: AbsoluteMoniker::parse_str("/b").unwrap(),
+ using_node: NodePath::absolute_from_vec(vec!["b"]),
capability: "base_resolver".into(),
result: Ok(vec![
RouteSegment::RequireResolver {
- abs_moniker: AbsoluteMoniker::parse_str("/b").unwrap(),
+ node_path: NodePath::absolute_from_vec(vec!["b"]),
scheme: "base".to_string(),
},
RouteSegment::RegisterBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: RegistrationDecl::Resolver(resolver_registration_decl)
},
RouteSegment::DeclareBy {
- abs_moniker: AbsoluteMoniker::root(),
+ node_path: NodePath::absolute_from_vec(vec![]),
capability: CapabilityDecl::Resolver(resolver_decl)
}
])
@@ -2593,7 +2601,7 @@
assert_eq!(
protocols,
&vec![VerifyRouteResult {
- using_node: AbsoluteMoniker::parse_str("/b").unwrap(),
+ using_node: NodePath::absolute_from_vec(vec!["b"]),
capability: "bad_protocol".into(),
result: Err(CapabilityRouteError::AnalyzerModelError(
AnalyzerModelError::RoutingError(