// Copyright 2019 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 {
    anyhow::{format_err, Context as _, Error},
    component_events::events::EventSource,
    fidl_fuchsia_io as fio,
    fidl_fuchsia_sys::{
        ComponentControllerEvent, EnvironmentControllerEvent, EnvironmentControllerProxy,
        EnvironmentMarker, EnvironmentOptions, LauncherProxy,
    },
    fidl_fuchsia_sys2 as fsys,
    fuchsia_component::client::*,
    fuchsia_zircon as zx,
    futures::future,
    futures::stream::{StreamExt, TryStreamExt},
    rand::random,
    std::fs::*,
    std::path::PathBuf,
};

/// This static string is used by OpaqueTest to start Component Manager v2.
/// A fuchsia system is expected to have Component Manager v2 at this URL for
/// OpaqueTest::default to work correctly.
pub static COMPONENT_MANAGER_URL: &str =
    "fuchsia-pkg://fuchsia.com/component-manager#meta/component_manager.cmx";

/// This structure contains all elements responsible for a black-box test
/// of Component Manager v2. If this object is dropped, the component manager
/// will be killed, ending the test.
///
/// Any component using OpaqueTest must satisfy the following minimal requirements
/// in its manifest:
///
/// "sandbox": {
///     "features": [
///         "hub"
///     ],
///     "services": [
///         "fuchsia.process.Launcher",
///         "fuchsia.sys.Launcher",
///         "fuchsia.sys.Environment",
///         "fuchsia.logger.LogSink"
///     ]
/// }
///
/// Component manager requires the process.Launcher and LogSink services, so
/// OpaqueTest passes them into component manager from the parent component.
///
/// The Environment service is required to ensure hermeticity. This is important
/// for integration tests, where a single component runs multiple tests simultaneously.
/// There will be multiple component managers and they must all run in isolated environments.
///
/// The hub is required to access the Events FIDL service exposed by
/// component manager when the debug mode is enabled in component manager config.
///
/// Usage: /src/sys/component_manager/tests contains multiple tests such as
/// routing, base_resolver and shutdown which use this class.
pub struct OpaqueTest {
    /// The environment under which component manager runs
    pub env: EnvironmentControllerProxy,

    /// The app that handles component manager
    pub component_manager_app: App,

    /// URL for the component manager used for this test
    pub component_manager_url: String,

    /// URL of the root component given to this test's component manager
    pub root_component_url: String,

    /// Label give to this test's component manager in the hub
    pub label: String,
}

impl OpaqueTest {
    /// Creates a black box test with the default component manager URL and no
    /// additional directory handles that are passed in to component manager.
    /// The output of component manager is not redirected.
    ///
    /// At the end of this function call, a component manager has been created
    /// in a hermetic environment and its execution is halted.
    ///
    /// For greater control over test setup parameters, use [`OpaqueTestBuilder`].
    pub async fn default(root_component_url: &str) -> Result<Self, Error> {
        OpaqueTestBuilder::new(root_component_url).build().await
    }

    /// The path from Hub v1 to component manager.
    pub fn get_component_manager_path(&self) -> PathBuf {
        find_component_manager_in_hub(&self.component_manager_url, &self.label)
    }

    /// The path from Hub v1 to Hub v2
    /// To get this path, append "out/hub" to the component manager path.
    pub fn get_hub_v2_path(&self) -> PathBuf {
        let path = self.get_component_manager_path();
        path.join("out/hub")
    }

    /// The events FIDL service connected to component manager.
    /// An integration test can use this service to halt tasks of component manager
    /// at various points during its execution.
    pub async fn connect_to_event_source(&self) -> Result<EventSource, Error> {
        let path = self.get_component_manager_path();
        connect_to_event_source(&path).await
    }

    /// Connects to the `fuchsia.sys2.LifecycleController` protocol exposed by
    /// component manager and attempts to start the root component.
    pub async fn start_component_tree(&self) -> Result<(), Error> {
        let svc_path = self.get_component_manager_path().join("out/svc");
        let svc_path = svc_path.display().to_string();
        let lifecycle_controller =
            connect_to_protocol_at::<fsys::LifecycleControllerMarker>(&svc_path)?;
        lifecycle_controller
            .start("./")
            .await?
            .map_err(|e| format_err!("Starting root component failed: {:?}", e))?;
        Ok(())
    }
}

/// Configures a [`OpaqueTest`].
pub struct OpaqueTestBuilder {
    config: String,
    root_component_url: String,
    component_manager_url: Option<String>,
    dir_handles: Vec<(String, zx::Handle)>,
    runtime_config: Option<String>,
    extra_args: Vec<String>,
}

impl OpaqueTestBuilder {
    /// Creates a new OpaqueTestBuilder instance configured to launch the root component
    /// identified by the URL `root_component_url`.
    pub fn new(root_component_url: impl Into<String>) -> Self {
        OpaqueTestBuilder {
            config: "/pkg/data/component_manager_debug_config".to_string(),
            root_component_url: root_component_url.into(),
            component_manager_url: None,
            dir_handles: Vec::new(),
            runtime_config: None,
            extra_args: Vec::new(),
        }
    }

    /// Changes the URL of the component manager used for the black box test from the
    /// default [`COMPONENT_MANAGER_URL`] to `url`.
    pub fn component_manager_url(mut self, url: impl Into<String>) -> Self {
        self.component_manager_url = Some(url.into());
        self
    }

    /// Adds a directory `handle` to be installed in the component manager's namespace at
    /// the given `path`. If an output file descriptor is supplied, it is attached to the
    /// component manager's output.
    pub fn add_dir_handle(mut self, path: impl Into<String>, handle: zx::Handle) -> Self {
        self.dir_handles.push((path.into(), handle));
        self
    }

    pub fn config(mut self, config: impl Into<String>) -> Self {
        self.config = config.into();
        self
    }

    /// Sets the path to the configuration file for component manager.
    pub fn runtime_config(mut self, runtime_config: impl Into<String>) -> Self {
        self.runtime_config = Some(runtime_config.into());
        self
    }

    /// Extends the set of directory handles to include those in `handles`. If an output file
    /// descriptor is supplied, it is attached to the component manager's output.
    pub fn extend_dir_handles(
        mut self,
        handles: impl IntoIterator<Item = (String, zx::Handle)>,
    ) -> Self {
        self.dir_handles.extend(handles);
        self
    }

    /// Adds an extra parameter to pass to the started component manager.
    pub fn add_extra_arg(mut self, arg: impl Into<String>) -> Self {
        self.extra_args.push(arg.into());
        self
    }

    /// Builds a OpaqueTest. Upon success, a component manager has been created
    /// in a hermetic environment and its execution is halted.
    pub async fn build(self) -> Result<OpaqueTest, Error> {
        // Use a random integer to identify this component manager
        let random_num = random::<u32>();
        let label = format!("test_{}", random_num);

        let (env, launcher) = create_isolated_environment(&label).await?;
        let component_manager_url =
            self.component_manager_url.unwrap_or_else(|| COMPONENT_MANAGER_URL.to_string());
        let component_manager_app = launch_component_manager(
            launcher,
            &component_manager_url,
            &self.config,
            &self.root_component_url,
            self.dir_handles,
            self.runtime_config,
            self.extra_args,
        )
        .await?;

        Ok(OpaqueTest {
            env,
            component_manager_app,
            component_manager_url,
            root_component_url: self.root_component_url,
            label,
        })
    }
}

/// Creates an isolated environment for component manager inside this component.
/// This isolated environment will be given the provided label so as to identify
/// it uniquely in the hub.
async fn create_isolated_environment(
    label: &str,
) -> Result<(EnvironmentControllerProxy, LauncherProxy), Error> {
    let env = connect_to_protocol::<EnvironmentMarker>()
        .context("could not connect to current environment")?;

    let (new_env, new_env_server_end) =
        fidl::endpoints::create_proxy().context("could not create proxy")?;
    let (controller, controller_server_end) =
        fidl::endpoints::create_proxy().context("could not create proxy")?;
    let (launcher, launcher_server_end) =
        fidl::endpoints::create_proxy().context("could not create proxy")?;

    // Component manager will run with these environment options
    let mut env_options = EnvironmentOptions {
        // This flag ensures that component manager gets all its required
        // services from the parent component
        inherit_parent_services: true,
        use_parent_runners: true,
        kill_on_oom: false,
        delete_storage_on_death: true,
    };

    env.create_nested_environment(
        new_env_server_end,
        controller_server_end,
        label,
        None,
        &mut env_options,
    )
    .context("could not create isolated environment")?;

    // Wait for the environment to be setup.
    // There is only one type of event (OnCreated) in this protocol, so just get the next one.
    let EnvironmentControllerEvent::OnCreated {} =
        controller.take_event_stream().next().await.unwrap().unwrap();

    // Get the launcher for this environment so it can be used to start component manager.
    new_env
        .get_launcher(launcher_server_end)
        .context("could not get isolated environment launcher")?;

    Ok((controller, launcher))
}

/// Use the provided launcher from the isolated environment to startup component manager.
/// Attach any provided directory handles. Component manager is provided the URL of the
/// v2 component to start and the config. Blocks until the out directory of component
/// manager is set up.
async fn launch_component_manager(
    launcher: LauncherProxy,
    component_manager_url: &str,
    config: &str,
    root_component_url: &str,
    dir_handles: Vec<(String, zx::Handle)>,
    runtime_config: Option<String>,
    extra_args: Vec<String>,
) -> Result<App, Error> {
    let mut options = LaunchOptions::new();

    // Add in any provided directory handles to component manager's namespace
    for dir in dir_handles {
        options.add_handle_to_namespace(dir.0, dir.1);
    }

    let mut args = vec!["--config".to_string(), config.to_string(), root_component_url.to_string()];
    if let Some(runtime_config) = runtime_config {
        args.extend(vec!["--runtime-config".to_string(), runtime_config]);
    }
    args.extend(extra_args);

    let component_manager_app =
        launch_with_options(&launcher, component_manager_url.to_string(), Some(args), options)
            .context("could not launch component manager")?;

    // Wait for component manager to setup the out directory
    let event_stream = component_manager_app.controller().take_event_stream();
    event_stream
        .try_filter_map(|event| {
            let event = match event {
                ComponentControllerEvent::OnDirectoryReady {} => Some(event),
                _ => None,
            };
            future::ready(Ok(event))
        })
        .next()
        .await;

    Ok(component_manager_app)
}

/// Use the path to component manager's hub to find the events service
/// and connect to it
async fn connect_to_event_source(component_manager_path: &PathBuf) -> Result<EventSource, Error> {
    let path_to_svc = component_manager_path.join("out/svc");
    let path_to_svc = path_to_svc.to_str().expect("found invalid chars");
    let proxy = connect_to_protocol_at::<fsys::EventSourceMarker>(path_to_svc)
        .context("could not connect to EventSource service")?;
    Ok(EventSource::from_proxy(proxy))
}

/// Explore the hub to find the component manager running in the environment
/// marked by the provided label.
fn find_component_manager_in_hub(component_manager_url: &str, label: &str) -> PathBuf {
    let path_to_env = format!("/hub/r/{}", label);

    // Get the id for the environment
    let dir: Vec<DirEntry> = read_dir(path_to_env)
        // TODO convert this to an error instead of causing a panic
        .expect("could not open nested environment in the hub")
        .map(|x| x.expect("entry unreadable"))
        .collect();

    // There can only be one environment with this label.
    // So there should be only one id.
    assert_eq!(dir.len(), 1);

    // Since the component manager URL can be custom, we need to extract the
    // component name.
    let component_name = component_manager_url
        .split("/")
        .last()
        .expect("the URL for component manager must have at least one '/' character");

    let path_to_cm = dir[0].path().join("c").join(component_name);

    // Get the id for component manager
    let dir: Vec<DirEntry> = read_dir(path_to_cm)
        // TOOD convert this into an error instead of causing a panic
        .expect("could not open component manager in the hub")
        .map(|x| x.expect("entry unreadable"))
        .collect();

    // There can only be one component manager inside this environment.
    // So there should be only one id.
    assert_eq!(dir.len(), 1);

    dir[0].path()
}

/// Convenience method to lists the contents of a directory proxy as a sorted vector of strings.
pub async fn list_directory(root_proxy: &fio::DirectoryProxy) -> Result<Vec<String>, Error> {
    let entries = fuchsia_fs::directory::readdir(&root_proxy).await?;
    let mut items = entries.iter().map(|entry| entry.name.clone()).collect::<Vec<String>>();
    items.sort();
    Ok(items)
}
