// 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.

use {
    cm_rust::{ChildDecl, ComponentDecl, EnvironmentDecl},
    moniker::PartialMoniker,
    routing::environment::{DebugRegistry, EnvironmentExtends, RunnerRegistry},
    serde::{Deserialize, Serialize},
    std::{
        collections::{HashMap, VecDeque},
        convert::Into,
        fmt,
        fmt::Display,
    },
    thiserror::Error,
};

/// Errors that may occur while building or operating on a `ComponentTree`.
#[derive(Debug, Error, PartialEq, Serialize, Deserialize)]
pub enum ComponentTreeError {
    #[error("no component declaration found for url `{0}` requested by node `{1}`")]
    ComponentDeclNotFound(String, String),
    #[error("invalid child declaration containing url `{0}` at node `{1}`")]
    InvalidChildDecl(String, String),
    #[error("no node found with path `{0}`")]
    ComponentNodeNotFound(String),
    #[error("environment `{0}` requested by child `{1}` not found at node `{2}`")]
    EnvironmentNotFound(String, String, String),
}

/// A representation of a component's position in the component topology. The last segment of
/// a component's `NodePath` is its `PartialMoniker` 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<PartialMoniker>);

/// A representation of a v2 component containing a `ComponentDecl` as well as the `NodePath`s of
/// the component itself and of its parent and children (if any).
pub struct ComponentNode {
    pub decl: ComponentDecl,
    node_path: NodePath,
    url: String,
    parent: Option<NodePath>,
    children: Vec<NodePath>,
    environment: NodeEnvironment,
}

/// The environment of a v2 component.
pub struct NodeEnvironment {
    /// The name of this environment as defined by its creator. Should be `None` for the root
    /// environment.
    name: Option<String>,
    /// The relationship of this environment to that of the component instance's parent.
    extends: EnvironmentExtends,
    /// The runners available in this environment.
    runner_registry: RunnerRegistry,
    /// Protocols available in this environment as debug capabilities.
    debug_registry: DebugRegistry,
}

/// A representation of the set of all v2 components, together with their parent/child relationships.
#[derive(Default)]
pub struct ComponentTree {
    nodes: HashMap<NodePath, ComponentNode>,
}

#[derive(Default)]
pub struct BuildTreeResult {
    pub tree: Option<ComponentTree>,
    pub errors: Vec<ComponentTreeError>,
}

/// A builder which constructs a ComponentTree from a collection of component declarations indexed
/// by component URL.
pub struct ComponentTreeBuilder {
    decls_by_url: HashMap<String, ComponentDecl>,
    result: BuildTreeResult,
}

/// The `ComponentNodeVisitor` trait defines an interface for operating on a `ComponentNode`.
/// An error should be returned if the operation fails.
pub trait ComponentNodeVisitor {
    fn visit_node(&mut self, node: &ComponentNode) -> Result<(), anyhow::Error>;
}

/// The `ComponentTreeWalker` trait defines an interface for iteratively operating on nodes
/// of a `ComponentTree`, given a type implementing a per-node operation via the
/// `ComponentNodeVisitor` trait.
pub trait ComponentTreeWalker<'a> {
    /// Walks a `ComponentTree`, doing the operation implemented by `visitor` at each node.
    /// If the operation fails at a node, terminates the walk and propagates the error.
    fn walk<T: ComponentNodeVisitor>(
        &mut self,
        tree: &'a ComponentTree,
        visitor: &mut T,
    ) -> Result<(), anyhow::Error> {
        let mut node = tree.get_root_node()?;
        loop {
            visitor.visit_node(node)?;
            match self.get_next_node(tree)? {
                Some(ref next_node) => {
                    node = next_node;
                }
                None => {
                    return Ok(());
                }
            }
        }
    }

    /// Returns a `Some(next_node)` containing the node following `node` in some enumeration of a
    /// subset of a `ComponentTree`'s nodes, or returns `None` if `node` is the final node. If an
    /// error occurred while trying to get the next node, returns that error instead.
    fn get_next_node(
        &mut self,
        tree: &'a ComponentTree,
    ) -> Result<Option<&ComponentNode>, anyhow::Error>;
}

/// A walker implementing breadth-first traversal of a full `ComponentTree`, starting at the root
/// node.
pub struct BreadthFirstWalker<'a> {
    discovered: VecDeque<&'a ComponentNode>,
}

impl NodePath {
    pub fn new(monikers: Vec<PartialMoniker>) -> Self {
        let mut node_path = NodePath::default();
        node_path.0 = monikers;
        node_path
    }

    /// Returns a new `NodePath` which extends `self` by appending `moniker` at the end of the path.
    pub fn extended(&self, moniker: PartialMoniker) -> Self {
        let mut node_path = NodePath::new(self.0.clone());
        node_path.0.push(moniker);
        node_path
    }
}

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 NodeEnvironment {
    pub fn name(&self) -> Option<&str> {
        self.name.as_deref()
    }

    pub fn extends(&self) -> &EnvironmentExtends {
        &self.extends
    }

    pub fn runner_registry(&self) -> &RunnerRegistry {
        &self.runner_registry
    }

    pub fn debug_registry(&self) -> &DebugRegistry {
        &self.debug_registry
    }

    // Defines an environment for the root node with the given `runner_registry` and `debug_registry`.
    fn new_root(runner_registry: RunnerRegistry, debug_registry: DebugRegistry) -> Self {
        Self { name: None, extends: EnvironmentExtends::None, runner_registry, debug_registry }
    }

    // Defines an environment inheriting the parent realm's environment without modification.
    fn new_inheriting() -> Self {
        Self {
            name: None,
            extends: EnvironmentExtends::Realm,
            runner_registry: RunnerRegistry::default(),
            debug_registry: DebugRegistry::default(),
        }
    }

    // Defines a named environment from a parent instance's `EnvironmentDecl`.
    fn from_decl(env_decl: &EnvironmentDecl) -> Self {
        Self {
            name: Some(env_decl.name.clone()),
            extends: env_decl.extends.into(),
            runner_registry: RunnerRegistry::from_decl(&env_decl.runners),
            debug_registry: env_decl.debug_capabilities.clone().into(),
        }
    }
}

impl ComponentNode {
    /// Returns a string representing the path to this `ComponentNode` from the root node.
    /// Each path segment is the `PartialMoniker` of a component relative to its parent.
    /// The root node is represented as "/".
    pub fn short_display(&self) -> String {
        self.node_path.to_string()
    }

    pub fn url(&self) -> String {
        self.url.clone()
    }

    pub fn moniker(&self) -> Option<&PartialMoniker> {
        self.node_path.0.last()
    }

    pub fn node_path(&self) -> NodePath {
        self.node_path.clone()
    }

    pub fn environment(&self) -> &NodeEnvironment {
        &self.environment
    }

    // Creates a new `ComponentNode` with the specified declaration, url, parent, moniker, and
    // environment. Does not populate the node's `children` field.
    fn new(
        decl: ComponentDecl,
        url: String,
        parent: Option<NodePath>,
        moniker: Option<PartialMoniker>,
        environment: NodeEnvironment,
    ) -> Self {
        ComponentNode {
            decl,
            node_path: ComponentNode::get_node_path(parent.clone(), moniker),
            url,
            parent,
            children: vec![],
            environment,
        }
    }

    fn get_node_path(parent: Option<NodePath>, moniker: Option<PartialMoniker>) -> NodePath {
        if let Some(postfix) = moniker {
            if let Some(prefix) = parent {
                return prefix.extended(postfix);
            } else {
                return NodePath::new(vec![postfix]);
            }
        }
        NodePath::default()
    }

    fn environment_for_child(
        &self,
        child_decl: &ChildDecl,
    ) -> Result<NodeEnvironment, ComponentTreeError> {
        match child_decl.environment.as_ref() {
            Some(child_env_name) => {
                let env_decl =
                    self.decl.environments.iter().find(|&env| &env.name == child_env_name).ok_or(
                        ComponentTreeError::EnvironmentNotFound(
                            child_env_name.clone(),
                            child_decl.name.clone(),
                            self.node_path().to_string(),
                        ),
                    )?;
                Ok(NodeEnvironment::from_decl(env_decl))
            }
            None => Ok(NodeEnvironment::new_inheriting()),
        }
    }
}

impl ComponentTree {
    pub fn len(&self) -> usize {
        self.nodes.len()
    }

    pub fn is_empty(&self) -> bool {
        self.nodes.is_empty()
    }

    /// Returns the node at `node_path`, or an error if there is no node at `node_path`.
    pub fn get_node(&self, node_path: &NodePath) -> Result<&ComponentNode, ComponentTreeError> {
        match self.nodes.get(node_path) {
            Some(ref node) => Ok(node),
            None => Err(ComponentTreeError::ComponentNodeNotFound(node_path.to_string())),
        }
    }

    /// Returns the root node, or an error if the root node is not found.
    pub fn get_root_node(&self) -> Result<&ComponentNode, ComponentTreeError> {
        self.get_node(&NodePath::new(vec![]))
    }

    /// Returns the parent of `node`, or returns `None` if `node` has no parent, or else returns an
    /// error if `node` contains an invalid `NodePath` as its parent identifier.
    pub fn try_get_parent(
        &self,
        node: &ComponentNode,
    ) -> Result<Option<&ComponentNode>, ComponentTreeError> {
        match node.parent {
            Some(ref parent) => Ok(Some(self.get_node(parent)?)),
            None => Ok(None),
        }
    }

    pub fn get_child_node(
        &self,
        node: &ComponentNode,
        moniker: PartialMoniker,
    ) -> Result<&ComponentNode, ComponentTreeError> {
        Ok(self.get_node(&node.node_path.extended(moniker))?)
    }

    /// Returns the children of `node`, or returns an error if `node` contains an invalid `NodePath` as
    /// one of its child identifier.
    pub fn get_children(
        &self,
        node: &ComponentNode,
    ) -> Result<Vec<&ComponentNode>, ComponentTreeError> {
        let mut children = Vec::new();
        for child in node.children.iter() {
            children.push(self.get_node(child)?);
        }
        Ok(children)
    }
}

impl ComponentTreeBuilder {
    /// Constructs a `ComponentTreeBuilder` from a map of component declarations keyed by
    /// component url.
    pub fn new(decls_by_url: HashMap<String, ComponentDecl>) -> Self {
        ComponentTreeBuilder { decls_by_url, result: BuildTreeResult::default() }
    }

    /// Constructs and returns a `ComponentTree` based at the component with url `root_url`,
    /// consuming the builder. Returns an error if `root_url` or the url of any subsequent
    /// child is not present in the builder's `decls_by_url` map, or if any `ComponentDecl`
    /// in `decls_by_url` contains an invalid `ChildDecl`.
    pub fn build<T: Into<String>>(mut self, root_url: T) -> BuildTreeResult {
        let mut tree = ComponentTree { nodes: HashMap::new() };

        let root_url = root_url.into();
        match self.decls_by_url.get(&root_url) {
            Some(root_decl) => {
                let mut root_node = ComponentNode::new(
                    root_decl.clone(),
                    root_url,
                    None,
                    None,
                    // TODO(pesk): probably runner_registry and debug_registry should be args
                    // to this method. What are they derived from?
                    NodeEnvironment::new_root(RunnerRegistry::default(), DebugRegistry::default()),
                );
                self.add_descendants(&mut tree, &mut root_node);
                tree.nodes.insert(root_node.node_path.clone(), root_node);
                self.result.tree = Some(tree)
            }
            None => self
                .result
                .errors
                .push(ComponentTreeError::ComponentDeclNotFound(root_url, "".to_string())),
        }
        self.result
    }

    fn add_descendants(&mut self, tree: &mut ComponentTree, node: &mut ComponentNode) {
        for child in node.decl.children.iter() {
            if child.name.is_empty() {
                self.result.errors.push(ComponentTreeError::InvalidChildDecl(
                    child.url.to_string(),
                    node.short_display(),
                ));
                continue;
            }
            match self.decls_by_url.get(&child.url) {
                Some(child_decl) => match node.environment_for_child(child) {
                    Ok(environment) => {
                        let mut child_node = ComponentNode::new(
                            child_decl.clone(),
                            child.url.clone(),
                            Some(node.node_path.clone()),
                            Some(PartialMoniker::new(child.name.clone(), None)),
                            environment,
                        );
                        self.add_descendants(tree, &mut child_node);
                        node.children.push(child_node.node_path.clone());
                        tree.nodes.insert(child_node.node_path.clone(), child_node);
                    }
                    Err(err) => self.result.errors.push(err),
                },
                None => self.result.errors.push(ComponentTreeError::ComponentDeclNotFound(
                    child.url.to_string(),
                    node.short_display(),
                )),
            }
        }
    }
}

impl<'a> BreadthFirstWalker<'a> {
    pub fn new(tree: &'a ComponentTree) -> Result<Self, anyhow::Error> {
        let mut walker = BreadthFirstWalker { discovered: VecDeque::new() };
        walker.discover_child_nodes(&tree, tree.get_root_node()?)?;
        Ok(walker)
    }

    fn discover_child_nodes(
        &mut self,
        tree: &'a ComponentTree,
        node: &'a ComponentNode,
    ) -> Result<(), anyhow::Error> {
        let children = tree.get_children(node)?;
        self.discovered.reserve(children.len());
        for child in children {
            self.discovered.push_back(child);
        }
        Ok(())
    }
}

impl<'a> ComponentTreeWalker<'a> for BreadthFirstWalker<'a> {
    fn get_next_node(
        &mut self,
        tree: &'a ComponentTree,
    ) -> Result<Option<&'a ComponentNode>, anyhow::Error> {
        match self.discovered.pop_front() {
            Some(next_node) => {
                self.discover_child_nodes(tree, &next_node)?;
                Ok(Some(next_node))
            }
            None => Ok(None),
        }
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        cm_rust::{
            CapabilityName, ChildDecl, DebugProtocolRegistration, DebugRegistration,
            RegistrationSource, RunnerRegistration,
        },
        fidl_fuchsia_sys2::StartupMode,
    };

    fn display_nodes(nodes: Vec<&ComponentNode>) -> Vec<String> {
        nodes.iter().map(|x| x.short_display()).collect()
    }

    fn new_child_decl(name: String, url: String, environment: Option<String>) -> ChildDecl {
        ChildDecl { name, url, startup: StartupMode::Lazy, environment }
    }

    fn new_environment_decl(
        name: String,
        extends: fidl_fuchsia_sys2::EnvironmentExtends,
        runners: Vec<RunnerRegistration>,
        debug_capabilities: Vec<DebugRegistration>,
    ) -> EnvironmentDecl {
        EnvironmentDecl {
            name,
            extends,
            runners,
            resolvers: vec![],
            debug_capabilities,
            stop_timeout_ms: None,
        }
    }

    fn new_component_decl(
        children: Vec<ChildDecl>,
        environments: Vec<EnvironmentDecl>,
    ) -> ComponentDecl {
        ComponentDecl {
            program: None,
            uses: vec![],
            exposes: vec![],
            offers: vec![],
            capabilities: vec![],
            children,
            collections: vec![],
            facets: None,
            environments,
        }
    }

    // Builds a `ComponentTree` with a single node.
    fn build_single_node_tree() -> BuildTreeResult {
        let root_url = "root_url".to_string();
        let root_decl = new_component_decl(vec![], vec![]);
        let mut decls = HashMap::new();
        decls.insert(root_url.clone(), root_decl.clone());
        ComponentTreeBuilder::new(decls).build(root_url)
    }

    // Builds a `ComponentTree` with 4 nodes and the following structure:
    //
    //          root
    //         /    \
    //       foo    bar
    //       /
    //     baz
    //
    fn build_multi_node_tree() -> BuildTreeResult {
        let root_url = "root_url".to_string();
        let foo_url = "foo_url".to_string();
        let bar_url = "bar_url".to_string();
        let baz_url = "baz_url".to_string();

        let foo_name = "foo".to_string();
        let bar_name = "bar".to_string();
        let baz_name = "baz".to_string();

        let root_decl = new_component_decl(
            vec![
                new_child_decl(foo_name, foo_url.clone(), None),
                new_child_decl(bar_name, bar_url.clone(), None),
            ],
            vec![],
        );
        let foo_decl =
            new_component_decl(vec![new_child_decl(baz_name, baz_url.clone(), None)], vec![]);
        let bar_decl = new_component_decl(vec![], vec![]);
        let baz_decl = new_component_decl(vec![], vec![]);

        let mut decls = HashMap::new();
        decls.insert(root_url.to_string(), root_decl.clone());
        decls.insert(foo_url.to_string(), foo_decl.clone());
        decls.insert(bar_url.to_string(), bar_decl.clone());
        decls.insert(baz_url.to_string(), baz_decl.clone());

        ComponentTreeBuilder::new(decls).build(root_url)
    }

    // A test ComponentNodeVisitor which just records the path string of each ComponentNode visited.
    #[derive(Default)]
    struct RouteMappingVisitor {
        pub route: Vec<String>,
    }

    impl ComponentNodeVisitor for RouteMappingVisitor {
        fn visit_node(&mut self, node: &ComponentNode) -> Result<(), anyhow::Error> {
            self.route.push(node.short_display());
            Ok(())
        }
    }

    // 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 = PartialMoniker::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 = PartialMoniker::new("bar".to_string(), None);
        let bar_node_path = foo_node_path.extended(bar_moniker);
        assert_eq!(bar_node_path.to_string(), "/foo/bar");
    }

    // Builds `ComponentNode`s with and without parents and children and tests the
    // `short_display()` and `url()` methods.
    #[test]
    fn build_node() {
        let foo_moniker = PartialMoniker::new("foo".to_string(), None);
        let bar_moniker = PartialMoniker::new("bar".to_string(), None);

        let root_url = "root_url".to_string();
        let leaf_url = "leaf_url".to_string();

        let root_node = ComponentNode::new(
            new_component_decl(vec![], vec![]),
            root_url.clone(),
            None,
            None,
            NodeEnvironment::new_root(RunnerRegistry::default(), DebugRegistry::default()),
        );
        assert_eq!(root_node.short_display(), "/");
        assert_eq!(root_node.url(), root_url);

        let leaf_node = ComponentNode::new(
            new_component_decl(vec![], vec![]),
            leaf_url.clone(),
            Some(NodePath::new(vec![foo_moniker])),
            Some(bar_moniker),
            NodeEnvironment::new_inheriting(),
        );
        assert_eq!(leaf_node.short_display(), "/foo/bar");
        assert_eq!(leaf_node.url(), leaf_url);
    }

    // Builds a tree with a single node, retrieves the root node, and checks that `try_get_parent`
    // and `get_children` return OK but trivial results.
    #[test]
    fn single_node_tree() -> Result<(), ComponentTreeError> {
        let tree_result = build_single_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let root_node = tree.get_root_node()?;
        assert!(root_node.parent.is_none());
        assert!(root_node.children.is_empty());
        assert_eq!(root_node.short_display(), "/");

        let parent = tree.try_get_parent(&root_node)?;
        assert!(parent.is_none());

        let children = tree.get_children(&root_node)?;
        assert!(children.is_empty());

        Ok(())
    }

    // Checks that the expected error is returned when the ComponentTreeBuilder's
    // `build` method is called with an unrecognized component url.
    #[test]
    fn build_tree_root_url_not_found() {
        let root_url = "root_url".to_string();
        let other_url = "other_url".to_string();
        let mut decls = HashMap::new();
        decls.insert(root_url.clone(), new_component_decl(vec![], vec![]));
        let build_result = ComponentTreeBuilder::new(decls).build(other_url.clone());
        assert!(build_result.tree.is_none());
        assert_eq!(build_result.errors.len(), 1);
        assert_eq!(
            build_result.errors[0],
            ComponentTreeError::ComponentDeclNotFound(other_url, "".to_string())
        );
    }

    // Builds a tree with 4 nodes using `build_multi_node_tree()`. Checks that the `node_path`,
    // `parent`, and `children` fields of each node are populated correctly and can be looked up
    // by a sequence of PartialMonikers. Also checks that lookup fails with an invalid sequence
    // of PartialMonikers.
    #[test]
    fn build_tree_and_look_up_multi_node() -> Result<(), ComponentTreeError> {
        let tree_result = build_multi_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let foo_path = NodePath::new(vec![PartialMoniker::new("foo".to_string(), None)]);
        let bar_path = NodePath::new(vec![PartialMoniker::new("bar".to_string(), None)]);
        let baz_path = foo_path.extended(PartialMoniker::new("baz".to_string(), None));
        let other_path = NodePath::new(vec![PartialMoniker::new("other".to_string(), None)]);

        let root_node = tree.get_root_node()?;
        assert_eq!(root_node.node_path.to_string(), "/");
        assert!(root_node.parent.is_none());
        assert_eq!(root_node.children, vec![foo_path.clone(), bar_path.clone()]);

        let foo_node = tree.get_node(&foo_path)?;
        assert_eq!(foo_node.node_path.to_string(), "/foo");
        assert!(foo_node.parent.is_some());
        assert_eq!(foo_node.parent.as_ref().unwrap().to_string(), "/");
        assert_eq!(foo_node.children, vec![baz_path.clone()]);

        let bar_node = tree.get_node(&bar_path)?;
        assert_eq!(bar_node.node_path.to_string(), "/bar");
        assert!(bar_node.parent.is_some());
        assert_eq!(bar_node.parent.as_ref().unwrap().to_string(), "/");
        assert!(bar_node.children.is_empty());

        let baz_node = tree.get_node(&baz_path)?;
        assert_eq!(baz_node.node_path.to_string(), "/foo/baz");
        assert!(baz_node.parent.is_some());
        assert_eq!(baz_node.parent.as_ref().unwrap().to_string(), "/foo");
        assert!(baz_node.children.is_empty());

        let get_other_node_result = tree.get_node(&other_path);
        assert!(get_other_node_result.is_err());
        assert_eq!(
            get_other_node_result.err().unwrap(),
            ComponentTreeError::ComponentNodeNotFound(other_path.to_string())
        );

        Ok(())
    }

    // Builds a tree with a child node that inherits a named environment from
    // its parent. Checks that the child node's environment is correctly populated.
    #[test]
    fn build_tree_with_environment() -> Result<(), ComponentTreeError> {
        let root_url = "root_url".to_string();
        let foo_url = "foo_url".to_string();
        let foo_name = "foo".to_string();
        let foo_env_name = "foo_env".to_string();
        let foo_extends = fidl_fuchsia_sys2::EnvironmentExtends::Realm;
        let foo_runner_name = CapabilityName("foo_runner".to_string());
        let foo_debug_name = CapabilityName("foo_debug".to_string());
        let foo_runner = RunnerRegistration {
            source_name: foo_runner_name.clone(),
            target_name: foo_runner_name.clone(),
            source: RegistrationSource::Parent,
        };
        let foo_debug = DebugRegistration::Protocol(DebugProtocolRegistration {
            source_name: foo_debug_name.clone(),
            source: RegistrationSource::Parent,
            target_name: foo_debug_name.clone(),
        });

        let root_decl = new_component_decl(
            vec![new_child_decl(foo_name.clone(), foo_url.clone(), Some(foo_env_name.clone()))],
            vec![new_environment_decl(
                foo_env_name.clone(),
                foo_extends.clone(),
                vec![foo_runner],
                vec![foo_debug],
            )],
        );
        let foo_decl = new_component_decl(vec![], vec![]);

        let mut decls = HashMap::new();
        decls.insert(root_url.to_string(), root_decl);
        decls.insert(foo_url.to_string(), foo_decl);

        let build_result = ComponentTreeBuilder::new(decls).build(root_url);
        assert!(build_result.errors.is_empty());
        let tree = build_result.tree.unwrap();

        let foo_node = tree.get_node(&NodePath::new(vec![PartialMoniker::new(foo_name, None)]))?;
        assert_eq!(foo_node.environment().name(), Some(foo_env_name).as_deref());
        assert_eq!(foo_node.environment().extends(), &foo_extends.into());
        assert!(foo_node.environment().runner_registry().get_runner(&foo_runner_name).is_some());
        assert!(foo_node.environment().debug_registry().get_capability(&foo_debug_name).is_some());
        Ok(())
    }

    // Builds a tree with a child node that inherits a named environment from its parent,
    // but the parent does not declare that environment. Checks that the tree builder logs
    // an EnvironmentNotFound error describing the problem.
    #[test]
    fn build_tree_missing_environment() {
        let root_url = "root_url".to_string();
        let foo_url = "foo_url".to_string();
        let foo_name = "foo".to_string();
        let foo_env_name = "foo_env".to_string();

        let root_decl = new_component_decl(
            vec![new_child_decl(foo_name.clone(), foo_url.clone(), Some(foo_env_name.clone()))],
            vec![],
        );
        let foo_decl = new_component_decl(vec![], vec![]);

        let mut decls = HashMap::new();
        decls.insert(root_url.to_string(), root_decl);
        decls.insert(foo_url.to_string(), foo_decl);

        let build_result = ComponentTreeBuilder::new(decls).build(root_url);
        assert_eq!(build_result.errors.len(), 1);
        assert_eq!(
            build_result.errors[0],
            ComponentTreeError::EnvironmentNotFound(foo_env_name, foo_name, "/".to_string())
        );
    }

    // Builds a tree with 4 nodes using `build_multi_node_tree()` and checks that `try_get_parent`
    // returns the expected result for each node.
    #[test]
    fn try_get_parent() -> Result<(), ComponentTreeError> {
        let tree_result = build_multi_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let foo_path = NodePath::new(vec![PartialMoniker::new("foo".to_string(), None)]);
        let bar_path = NodePath::new(vec![PartialMoniker::new("bar".to_string(), None)]);
        let baz_path = foo_path.extended(PartialMoniker::new("baz".to_string(), None));

        let root_parent = tree.try_get_parent(tree.get_root_node()?)?;
        assert!(root_parent.is_none());

        let foo_parent = tree.try_get_parent(tree.get_node(&foo_path)?)?;
        assert_eq!(foo_parent.unwrap().short_display(), "/");

        let bar_parent = tree.try_get_parent(tree.get_node(&bar_path)?)?;
        assert_eq!(bar_parent.unwrap().short_display(), "/");

        let baz_parent = tree.try_get_parent(tree.get_node(&baz_path)?)?;
        assert_eq!(baz_parent.unwrap().short_display(), "/foo");

        Ok(())
    }

    // Builds a tree with 4 nodes using `build_multi_node_tree()` and checks that `get_children`
    // returns the expected result for each node.
    #[test]
    fn get_children() -> Result<(), ComponentTreeError> {
        let tree_result = build_multi_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let foo_path = NodePath::new(vec![PartialMoniker::new("foo".to_string(), None)]);
        let bar_path = NodePath::new(vec![PartialMoniker::new("bar".to_string(), None)]);
        let baz_path = foo_path.extended(PartialMoniker::new("baz".to_string(), None));

        let root_children = tree.get_children(tree.get_root_node()?)?;
        assert_eq!(display_nodes(root_children), vec!["/foo", "/bar"]);

        let foo_children = tree.get_children(tree.get_node(&foo_path)?)?;
        assert_eq!(display_nodes(foo_children), vec!["/foo/baz"]);

        let bar_children = tree.get_children(tree.get_node(&bar_path)?)?;
        assert!(bar_children.is_empty());

        let baz_children = tree.get_children(tree.get_node(&baz_path)?)?;
        assert!(baz_children.is_empty());

        Ok(())
    }

    // Checks that the BreadthFirstWalker visits each node once when the
    // ComponentTree has a single node.
    #[test]
    fn breadth_first_walker_single_node() -> Result<(), anyhow::Error> {
        let tree_result = build_single_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let mut walker = BreadthFirstWalker::new(&tree)?;
        let mut visitor = RouteMappingVisitor::default();
        assert!(walker.walk(&tree, &mut visitor).is_ok());
        assert_eq!(visitor.route, vec!["/"]);

        Ok(())
    }

    // Checks that the BreadthFirstWalker visits each node once in breadth-first
    // order when the ComponentTree has multiple nodes.
    #[test]
    fn breadth_first_walker_multi_node() -> Result<(), anyhow::Error> {
        let tree_result = build_multi_node_tree();
        assert!(tree_result.errors.is_empty());
        let tree = tree_result.tree.unwrap();

        let mut walker = BreadthFirstWalker::new(&tree)?;
        let mut visitor = RouteMappingVisitor::default();
        assert!(walker.walk(&tree, &mut visitor).is_ok());
        // Sibling nodes "/foo" and "/bar" may be visited in either order.
        assert!(
            (visitor.route == vec!["/", "/foo", "/bar", "/foo/baz"])
                | (visitor.route == vec!["/", "/bar", "/foo", "/foo/baz"])
        );

        Ok(())
    }
}
