blob: cf4c061e061e23587dd94dbfb44602acf789dca2 [file] [log] [blame]
// Copyright 2020 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.
mod collection;
mod collector;
mod controller;
use {
crate::verify::{
collector::component_tree::V2ComponentTreeDataCollector,
controller::build::VerifyBuildController,
controller::capability_routing::TreeMappingController,
},
scrutiny::prelude::*,
std::sync::Arc,
};
plugin!(
VerifyPlugin,
PluginHooks::new(
collectors! {
"V2ComponentTreeDataCollector" => V2ComponentTreeDataCollector::new(),
},
controllers! {
"/verify/build" => VerifyBuildController::default(),
"/verify/map_tree" => TreeMappingController::default(),
}
),
vec![PluginDescriptor::new("CorePlugin")]
);
#[cfg(test)]
mod tests {
use {
super::*,
crate::core::collection::{Component, Components, Manifest, ManifestData, Manifests},
anyhow::Result,
cm_rust::{ChildDecl, ComponentDecl, NativeIntoFidl},
fidl::encoding::encode_persistent,
fidl_fuchsia_sys2 as fsys2,
serde_json::json,
tempfile::tempdir,
};
fn data_model() -> Arc<DataModel> {
let store_dir = tempdir().unwrap();
let uri = store_dir.into_path().into_os_string().into_string().unwrap();
Arc::new(DataModel::connect(uri).unwrap())
}
fn new_child_decl(name: String, url: String) -> ChildDecl {
ChildDecl { name, url, startup: fsys2::StartupMode::Lazy, environment: None }
}
fn new_component_decl(children: Vec<ChildDecl>) -> ComponentDecl {
ComponentDecl {
program: None,
uses: vec![],
exposes: vec![],
offers: vec![],
capabilities: vec![],
children,
collections: vec![],
facets: None,
environments: vec![],
}
}
fn make_v2_component(id: i32, url: String) -> Component {
Component { id, url, version: 2, inferred: false }
}
fn make_v2_manifest(component_id: i32, decl: ComponentDecl) -> Result<Manifest> {
let mut decl_fidl: fsys2::ComponentDecl = decl.native_into_fidl();
let decl_base64 = base64::encode(&encode_persistent(&mut decl_fidl)?);
Ok(Manifest { component_id, manifest: ManifestData::Version2(decl_base64), uses: vec![] })
}
fn single_v2_component_model() -> Result<Arc<DataModel>> {
let model = data_model();
let root_id = 0;
let root_component =
make_v2_component(root_id, "fuchsia-boot:///#meta/root.cm".to_string());
let root_manifest = make_v2_manifest(root_id, new_component_decl(vec![]))?;
model.set(Components::new(vec![root_component]))?;
model.set(Manifests::new(vec![root_manifest]))?;
Ok(model)
}
fn multi_v2_component_model() -> Result<Arc<DataModel>> {
let model = data_model();
let root_id = 0;
let foo_id = 1;
let bar_id = 2;
let baz_id = 3;
let root_url = "fuchsia-boot:///#meta/root.cm".to_string();
let foo_url = "fuchsia-boot:///#meta/foo.cm".to_string();
let bar_url = "fuchsia-boot:///#meta/bar.cm".to_string();
let baz_url = "fuchsia-boot:///#meta/baz.cm".to_string();
let root_component = make_v2_component(root_id, root_url.clone());
let foo_component = make_v2_component(foo_id, foo_url.clone());
let bar_component = make_v2_component(bar_id, bar_url.clone());
let baz_component = make_v2_component(baz_id, baz_url.clone());
let root_decl = new_component_decl(vec![
new_child_decl("foo".to_string(), foo_url),
new_child_decl("bar".to_string(), bar_url),
]);
let foo_decl = new_component_decl(vec![new_child_decl("baz".to_string(), baz_url)]);
let bar_decl = new_component_decl(vec![]);
let baz_decl = new_component_decl(vec![]);
let root_manifest = make_v2_manifest(root_id, root_decl)?;
let foo_manifest = make_v2_manifest(foo_id, foo_decl)?;
let bar_manifest = make_v2_manifest(bar_id, bar_decl)?;
let baz_manifest = make_v2_manifest(baz_id, baz_decl)?;
model.set(Components::new(vec![
root_component,
foo_component,
bar_component,
baz_component,
]))?;
model.set(Manifests::new(vec![root_manifest, foo_manifest, bar_manifest, baz_manifest]))?;
Ok(model)
}
#[test]
fn test_map_tree_single_node() -> Result<()> {
let model = single_v2_component_model()?;
V2ComponentTreeDataCollector::new().collect(model.clone())?;
let controller = TreeMappingController::default();
let response = controller.query(model.clone(), json!("{}"))?;
assert_eq!(
response,
json!({"route": [{"node": "/", "url": "fuchsia-boot:///#meta/root.cm"}]})
);
Ok(())
}
#[test]
fn test_map_tree_multi_node() -> Result<()> {
let model = multi_v2_component_model()?;
V2ComponentTreeDataCollector::new().collect(model.clone())?;
let controller = TreeMappingController::default();
let response = controller.query(model.clone(), json!("{}"))?;
assert!(
(response
== json!({"route": [{"node": "/", "url": "fuchsia-boot:///#meta/root.cm"},
{"node": "/foo","url": "fuchsia-boot:///#meta/foo.cm"},
{"node": "/bar", "url": "fuchsia-boot:///#meta/bar.cm"},
{"node": "/foo/baz", "url": "fuchsia-boot:///#meta/baz.cm"}]}))
| (response
== json!({"route": [{"node": "/", "url": "fuchsia-boot:///#meta/root.cm"},
{"node": "/bar","url": "fuchsia-boot:///#meta/bar.cm"},
{"node": "/foo", "url": "fuchsia-boot:///#meta/foo.cm"},
{"node": "/foo/baz", "url": "fuchsia-boot:///#meta/baz.cm"}]}))
);
Ok(())
}
}