// 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 {
    crate::events::EventSource,
    anyhow::{Context as _, Error},
    fidl_fuchsia_io::DirectoryProxy,
    fidl_fuchsia_sys::{
        ComponentControllerEvent, EnvironmentControllerEvent, EnvironmentControllerProxy,
        EnvironmentMarker, EnvironmentOptions, LauncherProxy,
    },
    fidl_fuchsia_sys2 as fsys, files_async,
    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 BlackBoxTest to start Component Manager v2.
/// A fuchsia system is expected to have Component Manager v2 at this URL for
/// BlackBoxTest::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 BlackBoxTest 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
/// BlackBoxTest 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" flag is passed in.
///
/// Usage: /src/sys/component_manager/tests contains multiple tests such as
/// routing, base_resolver and shutdown which use this class.
pub struct BlackBoxTest {
    /// 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 BlackBoxTest {
    /// 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 [`BlackBoxTestBuilder`].
    pub async fn default(root_component_url: &str) -> Result<Self, Error> {
        BlackBoxTestBuilder::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
    }
}

/// Configures a [`BlackBoxTest`].
pub struct BlackBoxTestBuilder {
    root_component_url: String,
    component_manager_url: Option<String>,
    dir_handles: Vec<(String, zx::Handle)>,
    config_file: Option<String>,
    extra_args: Vec<String>,
}

impl BlackBoxTestBuilder {
    /// Creates a new BlackBoxTestBuilder instance configured to launch the root component
    /// identified by the URL `root_component_url`.
    pub fn new(root_component_url: impl Into<String>) -> Self {
        BlackBoxTestBuilder {
            root_component_url: root_component_url.into(),
            component_manager_url: None,
            dir_handles: Vec::new(),
            config_file: 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
    }

    /// Sets the path to the configuration file for component manager.
    pub fn config_file(mut self, config_file: impl Into<String>) -> Self {
        self.config_file = Some(config_file.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 BlackBoxTest. Upon success, a component manager has been created
    /// in a hermetic environment and its execution is halted.
    pub async fn build(self) -> Result<BlackBoxTest, 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.root_component_url,
            self.dir_handles,
            self.config_file,
            self.extra_args,
        )
        .await?;

        Ok(BlackBoxTest {
            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_service::<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 debug flag. Blocks until the out directory of component
/// manager is set up.
async fn launch_component_manager(
    launcher: LauncherProxy,
    component_manager_url: &str,
    root_component_url: &str,
    dir_handles: Vec<(String, zx::Handle)>,
    config_file: 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![root_component_url.to_string(), "--debug".to_string()];
    if let Some(config_file) = config_file {
        args.extend(vec!["--config-file".to_string(), config_file]);
    }
    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_service_at::<fsys::BlockingEventSourceMarker>(path_to_svc)
        .context("could not connect to BlockingEventSource 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: &DirectoryProxy) -> Result<Vec<String>, Error> {
    let entries = files_async::readdir(&root_proxy).await?;
    let mut items = entries.iter().map(|entry| entry.name.clone()).collect::<Vec<String>>();
    items.sort();
    Ok(items)
}
