// 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::{
        builtin::{process_launcher::ProcessLauncher, runner::BuiltinRunnerFactory},
        config::RuntimeConfig,
        model::{
            policy::{PolicyError, ScopedPolicyChecker},
            runner::{Runner, RunnerError},
        },
    },
    anyhow::{format_err, Context as _, Error},
    async_trait::async_trait,
    clonable_error::ClonableError,
    fidl::endpoints::{Proxy, ServerEnd},
    fidl_fuchsia_component as fcomp, fidl_fuchsia_component_runner as fcrunner,
    fidl_fuchsia_data as fdata,
    fidl_fuchsia_io::{DirectoryMarker, NodeMarker, OPEN_RIGHT_READABLE, OPEN_RIGHT_WRITABLE},
    fidl_fuchsia_process as fproc,
    fidl_fuchsia_process_lifecycle::{LifecycleMarker, LifecycleProxy},
    fuchsia_async as fasync,
    fuchsia_component::client,
    fuchsia_runtime::{duplicate_utc_clock_handle, job_default, HandleInfo, HandleType},
    fuchsia_zircon::{
        self as zx, AsHandleRef, Clock, HandleBased, Job, Process, ProcessInfo, Task,
    },
    futures::{
        channel::oneshot,
        future::{BoxFuture, FutureExt},
    },
    log::{error, warn},
    runner::component::{ChannelEpitaph, Controllable},
    std::convert::TryFrom,
    std::{convert::TryInto, path::Path, sync::Arc},
    thiserror::Error,
    vfs::{
        directory::entry::DirectoryEntry, directory::immutable::simple as pfs,
        execution_scope::ExecutionScope, file::pcb::asynchronous::read_only_static,
        path::Path as fvfsPath, tree_builder::TreeBuilder,
    },
};

// Simple directory type which is used to implement `ComponentStartInfo.runtime_directory`.
type RuntimeDirectory = Arc<pfs::Simple>;

// Minimum timer slack amount and default mode. The amount should be large enough to allow for some
// coalescing of timers, but small enough to ensure applications don't miss deadlines.
//
// TODO(fxbug.dev/43934): For now, set the value to 50us to avoid delaying performance-critical
// timers in Scenic and other system services.
const TIMER_SLACK_DURATION: zx::Duration = zx::Duration::from_micros(50);

/// Errors produced by `ElfRunner`.
#[derive(Debug, Clone, Error)]
pub enum ElfRunnerError {
    #[error("failed to retrieve process koid for component with url \"{}\": {}", url, err)]
    ComponentProcessIdError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to retrieve job koid for component with url \"{}\": {}", url, err)]
    ComponentJobIdError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to set job policy for component with url \"{}\": {}", url, err)]
    ComponentJobPolicyError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to create job for component with url \"{}\": {}", url, err)]
    ComponentJobCreationError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to duplicate job for component with url \"{}\": {}", url, err)]
    ComponentJobDuplicationError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to mark main process as critical for component with url \"{}\": {}", url, err)]
    ComponentCriticalMarkingError {
        url: String,
        #[source]
        err: ClonableError,
    },
    #[error("failed to add runtime/elf directory for component with url \"{}\"", url)]
    ComponentElfDirectoryError { url: String },
    #[error("program key \"{}\" invalid for component with url \"{}\"", key, url)]
    ProgramDictionaryError { key: String, url: String },
    #[error("{err}")]
    SecurityPolicyError {
        #[from]
        err: PolicyError,
    },
    #[error("{err}")]
    GenericRunnerError {
        #[from]
        err: RunnerError,
    },
    #[error("failed to duplicate UTC clock for component with url \"{}\": {}", url, status)]
    DuplicateUtcClockError { url: String, status: zx::Status },
}

impl ElfRunnerError {
    pub fn component_process_id_error(
        url: impl Into<String>,
        err: impl Into<Error>,
    ) -> ElfRunnerError {
        ElfRunnerError::ComponentProcessIdError { url: url.into(), err: err.into().into() }
    }

    pub fn component_job_id_error(url: impl Into<String>, err: impl Into<Error>) -> ElfRunnerError {
        ElfRunnerError::ComponentJobIdError { url: url.into(), err: err.into().into() }
    }

    pub fn component_job_policy_error(
        url: impl Into<String>,
        err: impl Into<Error>,
    ) -> ElfRunnerError {
        ElfRunnerError::ComponentJobPolicyError { url: url.into(), err: err.into().into() }
    }

    pub fn component_job_creation_error(
        url: impl Into<String>,
        err: impl Into<Error>,
    ) -> ElfRunnerError {
        ElfRunnerError::ComponentJobCreationError { url: url.into(), err: err.into().into() }
    }

    pub fn component_job_duplication_error(
        url: impl Into<String>,
        err: impl Into<Error>,
    ) -> ElfRunnerError {
        ElfRunnerError::ComponentJobDuplicationError { url: url.into(), err: err.into().into() }
    }

    pub fn component_critical_marking_error(
        url: impl Into<String>,
        err: impl Into<Error>,
    ) -> ElfRunnerError {
        ElfRunnerError::ComponentCriticalMarkingError { url: url.into(), err: err.into().into() }
    }

    pub fn component_elf_directory_error(url: impl Into<String>) -> ElfRunnerError {
        ElfRunnerError::ComponentElfDirectoryError { url: url.into() }
    }

    pub fn program_dictionary_error(
        key: impl Into<String>,
        url: impl Into<String>,
    ) -> ElfRunnerError {
        ElfRunnerError::ProgramDictionaryError { key: key.into(), url: url.into() }
    }

    pub fn as_zx_status(&self) -> zx::Status {
        match self {
            ElfRunnerError::GenericRunnerError { err } => err.as_zx_status(),
            ElfRunnerError::SecurityPolicyError { .. } => zx::Status::ACCESS_DENIED,
            _ => zx::Status::INTERNAL,
        }
    }
}

// Builds and serves the runtime directory
struct RuntimeDirBuilder {
    args: Vec<String>,
    job_id: Option<u64>,
    process_id: Option<u64>,
    server_end: ServerEnd<NodeMarker>,
}

impl RuntimeDirBuilder {
    fn new(server_end: ServerEnd<DirectoryMarker>) -> Self {
        // Transform the server end to speak Node protocol only
        let server_end = ServerEnd::<NodeMarker>::new(server_end.into_channel());
        Self { args: vec![], job_id: None, process_id: None, server_end }
    }

    fn args(mut self, args: Vec<String>) -> Self {
        self.args = args;
        self
    }

    fn job_id(mut self, job_id: u64) -> Self {
        self.job_id = Some(job_id);
        self
    }

    fn process_id(mut self, process_id: u64) -> Self {
        self.process_id = Some(process_id);
        self
    }

    fn serve(mut self) -> RuntimeDirectory {
        // Create the runtime tree structure
        //
        // runtime
        // |- args
        // |  |- 0
        // |  |- 1
        // |  \- ...
        // \- elf
        //    |- job_id
        //    \- process_id
        let mut runtime_tree_builder = TreeBuilder::empty_dir();
        let mut count: u32 = 0;
        for arg in self.args.drain(..) {
            runtime_tree_builder
                .add_entry(["args", &count.to_string()], read_only_static(arg))
                .expect("Failed to add arg to runtime directory");
            count += 1;
        }

        if let Some(job_id) = self.job_id {
            runtime_tree_builder
                .add_entry(["elf", "job_id"], read_only_static(job_id.to_string()))
                .expect("Failed to add job_id to runtime/elf directory");
        }

        if let Some(process_id) = self.process_id {
            runtime_tree_builder
                .add_entry(["elf", "process_id"], read_only_static(process_id.to_string()))
                .expect("Failed to add process_id to runtime/elf directory");
        }

        let runtime_directory = runtime_tree_builder.build();

        // Serve the runtime directory
        runtime_directory.clone().open(
            ExecutionScope::new(),
            OPEN_RIGHT_READABLE | OPEN_RIGHT_WRITABLE,
            0,
            fvfsPath::empty(),
            self.server_end,
        );

        runtime_directory
    }
}

/// Runs components with ELF binaries.
pub struct ElfRunner {
    launcher_connector: ProcessLauncherConnector,
    utc_clock: Option<Arc<Clock>>,
}

impl ElfRunner {
    pub fn new(config: &RuntimeConfig, utc_clock: Option<Arc<Clock>>) -> ElfRunner {
        ElfRunner { launcher_connector: ProcessLauncherConnector::new(config), utc_clock }
    }

    async fn configure_launcher(
        &self,
        resolved_url: &String,
        start_info: fcrunner::ComponentStartInfo,
        job: zx::Job,
        launcher: &fidl_fuchsia_process::LauncherProxy,
        lifecycle_server: Option<zx::Channel>,
    ) -> Result<Option<(fidl_fuchsia_process::LaunchInfo, RuntimeDirBuilder)>, ElfRunnerError> {
        let bin_path = runner::get_program_binary(&start_info)
            .map_err(|e| RunnerError::invalid_args(resolved_url.clone(), e))?;

        let args = runner::get_program_args(&start_info)
            .map_err(|e| RunnerError::invalid_args(resolved_url.clone(), e))?;

        // TODO(fxbug.dev/45586): runtime_dir may be unavailable in tests. We should fix tests so
        // that we don't have to have this check here.
        let runtime_dir_builder = match start_info.runtime_dir {
            Some(dir) => RuntimeDirBuilder::new(dir).args(args.clone()),
            None => return Ok(None),
        };

        let name = Path::new(&resolved_url)
            .file_name()
            .ok_or(format_err!("invalid url"))
            .map_err(|e| RunnerError::invalid_args(resolved_url.clone(), e))?
            .to_str()
            .ok_or(format_err!("invalid url"))
            .map_err(|e| RunnerError::invalid_args(resolved_url.clone(), e))?;

        // Convert the directories into proxies, so we can find "/pkg" and open "lib" and bin_path
        let ns = runner::component::ComponentNamespace::try_from(
            start_info.ns.unwrap_or_else(|| vec![]),
        )
        .map_err(|e| RunnerError::invalid_args(resolved_url.clone(), e))?;

        let mut handle_infos = vec![];

        if let Some(outgoing_dir) = start_info.outgoing_dir {
            handle_infos.push(fproc::HandleInfo {
                handle: outgoing_dir.into_handle(),
                id: HandleInfo::new(HandleType::DirectoryRequest, 0).as_raw(),
            });
        }

        if let Some(lifecycle_chan) = lifecycle_server {
            handle_infos.push(fproc::HandleInfo {
                handle: lifecycle_chan.into_handle(),
                id: HandleInfo::new(HandleType::Lifecycle, 0).as_raw(),
            })
        };

        let clock_rights =
            zx::Rights::READ | zx::Rights::WAIT | zx::Rights::DUPLICATE | zx::Rights::TRANSFER;
        let utc_clock = if let Some(utc_clock) = &self.utc_clock {
            utc_clock.duplicate_handle(clock_rights)
        } else {
            duplicate_utc_clock_handle(clock_rights)
        }
        .map_err(|s| {
            RunnerError::component_launch_error(
                "failed to duplicate UTC clock",
                ElfRunnerError::DuplicateUtcClockError { url: resolved_url.clone(), status: s },
            )
        })?;

        handle_infos.push(fproc::HandleInfo {
            handle: utc_clock.into_handle(),
            id: HandleInfo::new(HandleType::ClockUtc, 0).as_raw(),
        });

        // Load the component
        let launch_info =
            runner::component::configure_launcher(runner::component::LauncherConfigArgs {
                bin_path: &bin_path,
                name: &name,
                args: Some(args),
                ns: ns,
                job: Some(job),
                handle_infos: Some(handle_infos),
                name_infos: None,
                environs: None,
                launcher: &launcher,
            })
            .await
            .map_err(|e| RunnerError::component_load_error(resolved_url.clone(), e))?;

        Ok(Some((launch_info, runtime_dir_builder)))
    }

    async fn start_component(
        &self,
        start_info: fcrunner::ComponentStartInfo,
        checker: &ScopedPolicyChecker,
    ) -> Result<Option<ElfComponent>, ElfRunnerError> {
        let resolved_url =
            runner::get_resolved_url(&start_info).map_err(|e| RunnerError::invalid_args("", e))?;

        // This also checks relevant security policy for config that it wraps using the provided
        // PolicyChecker.
        let program_config = start_info
            .program
            .as_ref()
            .map(|p| ElfProgramConfig::parse_and_check(p, &checker, &resolved_url))
            .transpose()?
            .unwrap_or_default();

        let url = resolved_url.clone();
        let main_process_critical = program_config.main_process_critical;
        let res: Result<Option<ElfComponent>, ElfRunnerError> =
            self.start_component_helper(start_info, resolved_url, program_config).await;
        match res {
            Err(e) if main_process_critical => {
                panic!("failed to launch component with a critical process ({:?}): {:?}", url, e)
            }
            x => x,
        }
    }

    async fn start_component_helper(
        &self,
        start_info: fcrunner::ComponentStartInfo,
        resolved_url: String,
        program_config: ElfProgramConfig,
    ) -> Result<Option<ElfComponent>, ElfRunnerError> {
        let launcher = self
            .launcher_connector
            .connect()
            .context("failed to connect to launcher service")
            .map_err(|e| RunnerError::component_load_error(resolved_url.clone(), e))?;

        let component_job = job_default()
            .create_child_job()
            .map_err(|e| ElfRunnerError::component_job_creation_error(resolved_url.clone(), e))?;

        // Set timer slack.
        //
        // Why Late and not Center or Early? Timers firing a little later than requested is not
        // uncommon in non-realtime systems. Programs are generally tolerant of some
        // delays. However, timers firing before their deadline can be unexpected and lead to bugs.
        component_job
            .set_policy(zx::JobPolicy::TimerSlack(
                TIMER_SLACK_DURATION,
                zx::JobDefaultTimerMode::Late,
            ))
            .map_err(|e| ElfRunnerError::component_job_policy_error(resolved_url.clone(), e))?;

        // Prevent direct creation of processes.
        //
        // The kernel-level mechanisms for creating processes are very low-level. We require that
        // all processes be created via fuchsia.process.Launcher in order for the platform to
        // maintain change-control over how processes are created.
        component_job
            .set_policy(zx::JobPolicy::Basic(
                zx::JobPolicyOption::Absolute,
                vec![(zx::JobCondition::NewProcess, zx::JobAction::Deny)],
            ))
            .map_err(|e| ElfRunnerError::component_job_policy_error(resolved_url.clone(), e))?;

        // Default deny the job policy which allows ambiently marking VMOs executable, i.e. calling
        // vmo_replace_as_executable without an appropriate resource handle.
        if !program_config.ambient_mark_vmo_exec {
            component_job
                .set_policy(zx::JobPolicy::Basic(
                    zx::JobPolicyOption::Absolute,
                    vec![(zx::JobCondition::AmbientMarkVmoExec, zx::JobAction::Deny)],
                ))
                .map_err(|e| ElfRunnerError::component_job_policy_error(resolved_url.clone(), e))?;
        }

        let (lifecycle_client, lifecycle_server) = match program_config.notify_lifecycle_stop {
            true => {
                fidl::endpoints::create_proxy::<LifecycleMarker>().map(|(c, s)| (Some(c), Some(s)))
            }
            false => Ok((None, None)),
        }
        .map_err(|_| RunnerError::Unsupported)?;
        let lifecycle_server = lifecycle_server.map(|s| s.into_channel());

        let job_dup = component_job.duplicate_handle(zx::Rights::SAME_RIGHTS).map_err(|e| {
            ElfRunnerError::component_job_duplication_error(resolved_url.clone(), e)
        })?;

        let (mut launch_info, runtime_dir_builder) = match self
            .configure_launcher(&resolved_url, start_info, job_dup, &launcher, lifecycle_server)
            .await?
        {
            Some(s) => s,
            None => return Ok(None),
        };

        let job_koid = component_job
            .get_koid()
            .map_err(|e| ElfRunnerError::component_job_id_error(resolved_url.clone(), e))?
            .raw_koid();

        // Launch the component
        let (status, process) = launcher
            .launch(&mut launch_info)
            .await
            .map_err(|e| RunnerError::component_launch_error(&*resolved_url, e))?;
        zx::Status::ok(status).map_err(|s| {
            RunnerError::component_launch_error(
                resolved_url.clone(),
                format_err!("failed to launch component: {}", s),
            )
        })?;
        let process = process.ok_or(RunnerError::component_launch_error(
            resolved_url.clone(),
            format_err!("failed to launch component, no process"),
        ))?;
        if program_config.main_process_critical {
            job_default()
                .set_critical(zx::JobCriticalOptions::RETCODE_NONZERO, &process)
                .map_err(|s| {
                    ElfRunnerError::component_critical_marking_error(
                        resolved_url.clone(),
                        format_err!("failed to mark process as critical: {}", s),
                    )
                })
                .expect("failed to set process as critical");
        }
        let process_koid = process
            .get_koid()
            .map_err(|e| ElfRunnerError::component_process_id_error(resolved_url.clone(), e))?
            .raw_koid();
        let runtime_dir = runtime_dir_builder.job_id(job_koid).process_id(process_koid).serve();
        Ok(Some(ElfComponent::new(
            runtime_dir,
            Job::from(component_job),
            process,
            lifecycle_client,
            program_config.main_process_critical,
        )))
    }
}

/// Wraps ELF runner-specific keys in component's "program" dictionary.
#[derive(Default)]
struct ElfProgramConfig {
    notify_lifecycle_stop: bool,
    ambient_mark_vmo_exec: bool,
    main_process_critical: bool,
}

impl ElfProgramConfig {
    /// Parse the given dictionary into an ElfProgramConfig, checking it against security policy as
    /// needed.
    ///
    /// Checking against security policy is intentionally combined with parsing here, so that policy
    /// enforcement is as close to the point of parsing as possible and can't be inadvertently skipped.
    pub fn parse_and_check(
        program: &fdata::Dictionary,
        checker: &ScopedPolicyChecker,
        url: &str,
    ) -> Result<Self, ElfRunnerError> {
        const STOP_EVENT_KEY: &str = "lifecycle.stop_event";
        let notify_lifecycle_stop = match Self::find(program, STOP_EVENT_KEY) {
            Some(fdata::DictionaryValue::Str(str_val)) => match &str_val[..] {
                "notify" => Ok(true),
                "ignore" => Ok(false),
                _ => Err(()),
            },
            Some(_) => Err(()),
            None => Ok(false),
        }
        .map_err(|_| ElfRunnerError::program_dictionary_error(STOP_EVENT_KEY, url))?;

        const VMEX_KEY: &str = "job_policy_ambient_mark_vmo_exec";
        let ambient_mark_vmo_exec = match Self::find(program, VMEX_KEY) {
            Some(fdata::DictionaryValue::Str(str_val)) => match &str_val[..] {
                "true" => Ok(true),
                "false" => Ok(false),
                _ => Err(()),
            },
            Some(_) => Err(()),
            None => Ok(false),
        }
        .map_err(|_| ElfRunnerError::program_dictionary_error(VMEX_KEY, url))?;
        if ambient_mark_vmo_exec {
            checker.ambient_mark_vmo_exec_allowed()?;
        }

        const CRITICAL_KEY: &str = "main_process_critical";
        let main_process_critical = match Self::find(program, CRITICAL_KEY) {
            Some(fdata::DictionaryValue::Str(str_val)) => match &str_val[..] {
                "true" => Ok(true),
                "false" => Ok(false),
                _ => Err(()),
            },
            Some(_) => Err(()),
            None => Ok(false),
        }
        .map_err(|_| ElfRunnerError::program_dictionary_error(CRITICAL_KEY, url))?;
        if main_process_critical {
            checker.main_process_critical_allowed()?;
        }

        Ok(ElfProgramConfig { notify_lifecycle_stop, ambient_mark_vmo_exec, main_process_critical })
    }

    fn find<'a>(dict: &'a fdata::Dictionary, key: &str) -> Option<&'a fdata::DictionaryValue> {
        match &dict.entries {
            Some(entries) => {
                for entry in entries {
                    if entry.key == key {
                        return entry.value.as_ref().map(|val| &**val);
                    }
                }
                None
            }
            _ => None,
        }
    }
}

/// Structure representing a running elf component.
struct ElfComponent {
    /// Namespace directory for this component, kept just as a reference to
    /// keep the namespace alive.
    _runtime_dir: RuntimeDirectory,

    /// Job in which the underlying process that represents the component is
    /// running.
    job: Arc<Job>,

    /// Process made for the program binary defined for this component.
    process: Option<Arc<Process>>,

    /// Client end of the channel given to an ElfComponent which says it
    /// implements the Lifecycle protocol. If the component does not implement
    /// the protocol, this will be None.
    lifecycle_channel: Option<LifecycleProxy>,

    /// We need to remember if we marked the main process as critical, because if we're asked to
    /// kill a component that has such a marking it'll bring down everything.
    main_process_critical: bool,
}

impl ElfComponent {
    pub fn new(
        _runtime_dir: RuntimeDirectory,
        job: Job,
        process: Process,
        lifecycle_channel: Option<LifecycleProxy>,
        main_process_critical: bool,
    ) -> Self {
        Self {
            _runtime_dir,
            job: Arc::new(job),
            process: Some(Arc::new(process)),
            lifecycle_channel,
            main_process_critical,
        }
    }

    /// Return a pointer to the Process, returns None if the component has no
    /// Process.
    pub fn copy_process(&self) -> Option<Arc<Process>> {
        self.process.clone()
    }
}

#[async_trait]
impl Controllable for ElfComponent {
    async fn kill(mut self) {
        if self.main_process_critical {
            warn!("killing a component with 'main_process_critical', so this will also kill component_manager and all of its components");
        }
        let _ = self.job.kill().map_err(|e| error!("failed killing job during kill: {}", e));
    }

    fn stop<'a>(&mut self) -> BoxFuture<'a, ()> {
        if let Some(lifecycle_chan) = self.lifecycle_channel.take() {
            let _ = lifecycle_chan.stop();

            let job = self.job.clone();

            // If the component's main process is critical we must watch for
            // the main process to exit, otherwise we could end up killing that
            // process and therefore killing the root job.
            if self.main_process_critical {
                if self.process.is_none() {
                    // This is a bit strange because there's no process, but there is a lifecycle
                    // channel. Since there is no process it seems like killing it can't kill
                    // component manager.
                    warn!("killing job of component with 'main_process_critical' set because component has lifecycle channel, but no process main process.");
                    let _ = self.job.kill().map_err(|e| {
                        error!("failed killing job for component with no lifecycle channel: {}", e)
                    });
                    return async {}.boxed();
                }
                // Try to duplicate the Process handle so we can us it to wait for
                // process termination
                let proc_handle = self.process.take().unwrap();

                async move {
                    let _ = fasync::OnSignals::new(
                        &proc_handle.as_handle_ref(),
                        zx::Signals::PROCESS_TERMINATED,
                    )
                    .await
                    .map_err(|e| {
                        error!(
                        "killing component's job after failure waiting on process exit, err: {}",
                        e
                    )
                    });
                    let _ = job.kill().map_err(|e| {
                        error!("failed killing job in stop after lifecycle channel closed: {}", e)
                    });
                }
                .boxed()
            } else {
                async move {
                    let _ = lifecycle_chan.on_closed()
                    .await
                    .map_err(|e| {
                        error!(
                        "killing component's job after failure waiting on lifecycle channel, err: {}",
                        e
                        )
                    });
                    let _ = job.kill().map_err(|e| {
                        error!("failed killing job in stop after lifecycle channel closed: {}", e)
                    });
                }
                .boxed()
            }
        } else {
            let _ = self.job.kill().map_err(|e| {
                error!("failed killing job for component with no lifecycle channel: {}", e)
            });
            async {}.boxed()
        }
    }
}

impl Drop for ElfComponent {
    fn drop(&mut self) {
        // just in case we haven't killed the job already
        let _ = self.job.kill().map_err(|e| error!("failed to kill job in drop: {}", e));
    }
}

impl BuiltinRunnerFactory for ElfRunner {
    fn get_scoped_runner(self: Arc<Self>, checker: ScopedPolicyChecker) -> Arc<dyn Runner> {
        Arc::new(ScopedElfRunner { runner: self, checker })
    }
}

struct ScopedElfRunner {
    runner: Arc<ElfRunner>,
    checker: ScopedPolicyChecker,
}

#[async_trait]
impl Runner for ScopedElfRunner {
    /// Starts a component by creating a new Job and Process for the component.
    /// The Runner also creates and hosts a namespace for the component. The
    /// namespace and other runtime state of the component will live until the
    /// Future returned is dropped or the `server_end` is sent either
    /// `ComponentController.Stop` or `ComponentController.Kill`. Sending
    /// `ComponentController.Stop` or `ComponentController.Kill` causes the
    /// Future to complete.
    async fn start(
        &self,
        start_info: fcrunner::ComponentStartInfo,
        server_end: ServerEnd<fcrunner::ComponentControllerMarker>,
    ) {
        // Start the component and move the Controller into a new async
        // execution context.
        let resolved_url = runner::get_resolved_url(&start_info).unwrap_or(String::new());
        match self.runner.start_component(start_info, &self.checker).await {
            Ok(Some(elf_component)) => {
                let (epitaph_tx, epitaph_rx) = oneshot::channel::<ChannelEpitaph>();
                // This function waits for something from the channel and
                // returns it or Error::Internal if the channel is closed
                let epitaph_fn = Box::pin(async move {
                    epitaph_rx
                        .await
                        .unwrap_or_else(|_| {
                            warn!("epitaph oneshot channel closed unexpectedly");
                            fcomp::Error::Internal.into()
                        })
                        .into()
                });

                let proc_copy = match elf_component.copy_process() {
                    Some(copy) => copy,
                    None => {
                        runner::component::report_start_error(
                            zx::Status::from_raw(
                                i32::try_from(fcomp::Error::InstanceCannotStart.into_primitive())
                                    .unwrap(),
                            ),
                            "Component unexpectedly had no process".to_string(),
                            &resolved_url,
                            server_end,
                        );
                        return;
                    }
                };

                // Spawn a future that watches for the process to exit
                fasync::Task::spawn(async move {
                    let _ = fasync::OnSignals::new(
                        &proc_copy.as_handle_ref(),
                        zx::Signals::PROCESS_TERMINATED,
                    )
                    .await;
                    // Process exit code '0' is considered a clean return.
                    // TODO (fxbug.dev/57024) If we create an epitaph that indicates
                    // intentional, non-zero exit, use that for all non-0 exit
                    // codes.
                    let exit_status: ChannelEpitaph = match proc_copy.info() {
                        Ok(ProcessInfo { return_code: 0, .. }) => {
                            zx::Status::OK.try_into().unwrap()
                        }
                        Ok(_) => fcomp::Error::InstanceDied.into(),
                        Err(e) => {
                            warn!("Unable to query process info: {}", e);
                            fcomp::Error::Internal.into()
                        }
                    };
                    let _ = epitaph_tx.send(exit_status);
                })
                .detach();

                // Create a future which owns and serves the controller
                // channel. The `epitaph_fn` future completes when the
                // component's main process exits. The controller then sets the
                // epitaph on the controller channel, closes it, and stops
                // serving the protocol.
                fasync::Task::spawn(async move {
                    let server_stream = match server_end.into_stream() {
                        Ok(s) => s,
                        Err(e) => {
                            warn!("Converting Controller channel to stream failed: {}", e);
                            return;
                        }
                    };
                    runner::component::Controller::new(elf_component, server_stream)
                        .serve(epitaph_fn)
                        .await
                        .unwrap_or_else(|e| warn!("serving ComponentController failed: {}", e));
                })
                .detach();
            }

            Ok(None) => {
                // TODO(fxbug.dev/): Should this signal an error?
            }
            Err(err) => {
                runner::component::report_start_error(
                    err.as_zx_status(),
                    format!("{}", err),
                    &resolved_url,
                    server_end,
                );
            }
        }
    }
}

/// Connects to the appropriate `fuchsia.process.Launcher` service based on the options provided in
/// `ProcessLauncherConnector::new`.
///
/// This exists so that callers can make a new connection to `fuchsia.process.Launcher` for each use
/// because the service is stateful per connection, so it is not safe to share a connection between
/// multiple asynchronous process launchers.
///
/// If `Arguments.use_builtin_process_launcher` is true, this will connect to the built-in
/// `fuchsia.process.Launcher` service using the provided `ProcessLauncher`. Otherwise, this connects
/// to the launcher service under /svc in component_manager's namespace.
struct ProcessLauncherConnector {
    use_builtin: bool,
}

impl ProcessLauncherConnector {
    pub fn new(config: &RuntimeConfig) -> Self {
        Self { use_builtin: config.use_builtin_process_launcher }
    }

    pub fn connect(&self) -> Result<fproc::LauncherProxy, Error> {
        let proxy = if self.use_builtin {
            let (proxy, stream) =
                fidl::endpoints::create_proxy_and_stream::<fproc::LauncherMarker>()?;
            fasync::Task::spawn(async move {
                let result = ProcessLauncher::serve(stream).await;
                if let Err(e) = result {
                    warn!("ProcessLauncherConnector.connect failed: {}", e);
                }
            })
            .detach();
            proxy
        } else {
            client::connect_to_service::<fproc::LauncherMarker>()
                .context("failed to connect to external launcher service")?
        };
        Ok(proxy)
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::config::{JobPolicyAllowlists, RuntimeConfig, SecurityPolicy},
        fdio,
        fidl::endpoints::{create_proxy, ClientEnd, Proxy},
        fidl_fuchsia_component as fcomp, fidl_fuchsia_data as fdata,
        fidl_fuchsia_io::DirectoryProxy,
        fuchsia_async as fasync, fuchsia_zircon as zx,
        futures::prelude::*,
        io_util,
        matches::assert_matches,
        moniker::AbsoluteMoniker,
        runner::component::Controllable,
        scoped_task,
        std::{convert::TryFrom, ffi::CString, task::Poll},
    };

    // Rust's test harness does not allow passing through arbitrary arguments, so to get coverage
    // for the different LibraryOpts configurations (which would normally be set based on
    // arguments) we switch based on the test binary name.
    fn should_use_builtin_process_launcher() -> bool {
        // This is somewhat fragile but intentionally so, so that this will fail if the binary
        // names change and get updated properly.
        let bin = std::env::args().next();
        match bin.as_ref().map(String::as_ref) {
            Some("/pkg/bin/component_manager_test") => false,
            Some("/pkg/bin/component_manager_boot_env_test") => true,
            _ => panic!("Unexpected test binary name {:?}", bin),
        }
    }

    fn hello_world_startinfo(
        runtime_dir: Option<ServerEnd<DirectoryMarker>>,
    ) -> fcrunner::ComponentStartInfo {
        // Get a handle to /pkg
        let pkg_path = "/pkg".to_string();
        let pkg_chan = io_util::open_directory_in_namespace("/pkg", OPEN_RIGHT_READABLE)
            .unwrap()
            .into_channel()
            .unwrap()
            .into_zx_channel();
        let pkg_handle = ClientEnd::new(pkg_chan);

        let ns = vec![fcrunner::ComponentNamespaceEntry {
            path: Some(pkg_path),
            directory: Some(pkg_handle),
            ..fcrunner::ComponentNamespaceEntry::EMPTY
        }];

        fcrunner::ComponentStartInfo {
            resolved_url: Some(
                "fuchsia-pkg://fuchsia.com/hello_world_hippo#meta/hello_world.cm".to_string(),
            ),
            program: Some(fdata::Dictionary {
                entries: Some(vec![
                    fdata::DictionaryEntry {
                        key: "args".to_string(),
                        value: Some(Box::new(fdata::DictionaryValue::StrVec(vec![
                            "foo".to_string(),
                            "bar".to_string(),
                        ]))),
                    },
                    fdata::DictionaryEntry {
                        key: "binary".to_string(),
                        value: Some(Box::new(fdata::DictionaryValue::Str(
                            "bin/hello_world".to_string(),
                        ))),
                    },
                ]),
                ..fdata::Dictionary::EMPTY
            }),
            ns: Some(ns),
            outgoing_dir: None,
            runtime_dir,
            ..fcrunner::ComponentStartInfo::EMPTY
        }
    }

    /// Creates start info for a component which runs until told to exit. The
    /// ComponentController protocol can be used to stop the component when the
    /// test is done inspecting the launched component.
    fn lifecycle_startinfo(
        runtime_dir: Option<ServerEnd<DirectoryMarker>>,
    ) -> fcrunner::ComponentStartInfo {
        // Get a handle to /pkg
        let pkg_path = "/pkg".to_string();
        let pkg_chan = io_util::open_directory_in_namespace("/pkg", OPEN_RIGHT_READABLE)
            .unwrap()
            .into_channel()
            .unwrap()
            .into_zx_channel();
        let pkg_handle = ClientEnd::new(pkg_chan);

        let ns = vec![fcrunner::ComponentNamespaceEntry {
            path: Some(pkg_path),
            directory: Some(pkg_handle),
            ..fcrunner::ComponentNamespaceEntry::EMPTY
        }];

        fcrunner::ComponentStartInfo {
            resolved_url: Some(
                "fuchsia-pkg://fuchsia.com/lifecycle_full#meta/lifecycle_full.cm".to_string(),
            ),
            program: Some(fdata::Dictionary {
                entries: Some(vec![
                    fdata::DictionaryEntry {
                        key: "args".to_string(),
                        value: Some(Box::new(fdata::DictionaryValue::StrVec(vec![
                            "foo".to_string(),
                            "bar".to_string(),
                        ]))),
                    },
                    fdata::DictionaryEntry {
                        key: "binary".to_string(),
                        value: Some(Box::new(fdata::DictionaryValue::Str(
                            "bin/lifecycle_full".to_string(),
                        ))),
                    },
                    fdata::DictionaryEntry {
                        key: "lifecycle.stop_event".to_string(),
                        value: Some(Box::new(fdata::DictionaryValue::Str("notify".to_string()))),
                    },
                ]),
                ..fdata::Dictionary::EMPTY
            }),
            ns: Some(ns),
            outgoing_dir: None,
            runtime_dir,
            ..fcrunner::ComponentStartInfo::EMPTY
        }
    }

    fn create_dummy_process(
        job: &scoped_task::Scoped<Job>,
        raw_path: &str,
        name_for_builtin: &str,
    ) -> Process {
        if !should_use_builtin_process_launcher() {
            scoped_task::spawn(
                job,
                fdio::SpawnOptions::CLONE_ALL,
                &CString::new(raw_path).expect("could not make cstring"),
                &[&CString::new(raw_path).expect("could not make cstring")],
            )
            .expect("failed to spawn process")
            .into_inner()
        } else {
            let (process, _vmar) = job
                .create_child_process(name_for_builtin.as_bytes())
                .expect("could not create process");
            process
        }
    }

    fn make_default_elf_component(
        lifecycle_client: Option<LifecycleProxy>,
        critical: bool,
    ) -> (Job, ElfComponent) {
        let job = scoped_task::create_child_job().expect("failed to make child job");
        let dummy_process = create_dummy_process(&job, "/pkg/bin/run_indefinitely", "dummy");
        let job_copy = Job::from(
            job.as_handle_ref()
                .duplicate(zx::Rights::SAME_RIGHTS)
                .expect("job handle duplication failed"),
        );
        let component = ElfComponent::new(
            TreeBuilder::empty_dir().build(),
            job_copy,
            dummy_process,
            lifecycle_client,
            critical,
        );
        (job.into_inner(), component)
    }

    // TODO(fsamuel): A variation of this is used in a couple of places. We should consider
    // refactoring this into a test util file.
    async fn read_file<'a>(root_proxy: &'a DirectoryProxy, path: &'a str) -> String {
        let file_proxy =
            io_util::open_file(&root_proxy, &Path::new(path), io_util::OPEN_RIGHT_READABLE)
                .expect("Failed to open file.");
        let res = io_util::read_file(&file_proxy).await;
        res.expect("Unable to read file.")
    }

    #[fasync::run_singlethreaded(test)]
    async fn args_test() -> Result<(), Error> {
        let (runtime_dir_client, runtime_dir_server) = zx::Channel::create()?;
        let start_info = lifecycle_startinfo(Some(ServerEnd::new(runtime_dir_server)));

        let runtime_dir_proxy = DirectoryProxy::from_channel(
            fasync::Channel::from_channel(runtime_dir_client).unwrap(),
        );

        let config = RuntimeConfig {
            use_builtin_process_launcher: should_use_builtin_process_launcher(),
            ..Default::default()
        };
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&Arc::new(config)),
            AbsoluteMoniker::root(),
        ));
        let (controller, server_controller) = create_proxy::<fcrunner::ComponentControllerMarker>()
            .expect("could not create component controller endpoints");

        runner.start(start_info, server_controller).await;

        // Verify that args are added to the runtime directory.
        assert_eq!("foo", read_file(&runtime_dir_proxy, "args/0").await);
        assert_eq!("bar", read_file(&runtime_dir_proxy, "args/1").await);

        // Process Id and Job Id will vary with every run of this test. Here we verify that
        // they exist in the runtime directory, they can be parsed as unsigned integers, they're
        // greater than zero and they are not the same value. Those are about the only invariants
        // we can verify across test runs.
        let process_id = read_file(&runtime_dir_proxy, "elf/process_id").await.parse::<u64>()?;
        let job_id = read_file(&runtime_dir_proxy, "elf/job_id").await.parse::<u64>()?;
        assert!(process_id > 0);
        assert!(job_id > 0);
        assert_ne!(process_id, job_id);

        controller.stop().expect("Stop request failed");
        // Wait for the process to exit so the test doesn't pagefault due to an invalid stdout
        // handle.
        controller.on_closed().await.expect("failed waiting for channel to close");
        Ok(())
    }

    // This test checks that starting a component fails if we use the wrong built-in process
    // launcher setting for the test environment. This helps ensure that the test above isn't
    // succeeding for an unexpected reason, e.g. that it isn't using a fuchsia.process.Launcher
    // from the test's namespace instead of serving and using a built-in one.
    #[fasync::run_singlethreaded(test)]
    async fn hello_world_fail_test() -> Result<(), Error> {
        let (_runtime_dir_client, runtime_dir_server) = zx::Channel::create()?;
        let start_info = hello_world_startinfo(Some(ServerEnd::new(runtime_dir_server)));

        // Note that value of should_use... is negated
        let config = RuntimeConfig {
            use_builtin_process_launcher: !should_use_builtin_process_launcher(),
            ..Default::default()
        };
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&Arc::new(config)),
            AbsoluteMoniker::root(),
        ));
        let (client_controller, server_controller) =
            create_proxy::<fcrunner::ComponentControllerMarker>()
                .expect("could not create component controller endpoints");

        runner.start(start_info, server_controller).await;
        assert_matches!(
            client_controller.take_event_stream().try_next().await,
            Err(fidl::Error::ClientChannelClosed { .. })
        );
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_kill_component() -> Result<(), Error> {
        let (job, component) = make_default_elf_component(None, false);

        let job_info = job.info()?;
        assert!(!job_info.exited);

        component.kill().await;

        let h = job.as_handle_ref();
        fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
            .await
            .expect("failed waiting for termination signal");

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    #[test]
    fn test_stop_critical_component() -> Result<(), Error> {
        let mut exec = fasync::Executor::new().expect("Unable to create new executor");
        // Presence of the Lifecycle channel isn't use by ElfComponent to sense
        // component exit, but it does modify the stop behavior and this is
        // what we want to test.
        let (lifecycle_client, _lifecycle_server) =
            fidl::endpoints::create_proxy_and_stream::<LifecycleMarker>()?;
        let (job, mut component) = make_default_elf_component(Some(lifecycle_client), true);
        let process = component.copy_process().unwrap();
        let job_info = job.info()?;
        assert!(!job_info.exited);

        // Ask the runner to stop the component, it returns a future which
        // completes when the component closes its side of the lifecycle
        // channel
        let mut completes_when_stopped = component.stop();

        // The returned future shouldn't complete because we're holding the
        // lifecycle channel open.
        match exec.run_until_stalled(&mut completes_when_stopped) {
            Poll::Ready(_) => {
                panic!("runner should still be waiting for lifecycle channel to stop");
            }
            _ => {}
        }
        assert_eq!(process.kill(), Ok(()));

        exec.run_singlethreaded(&mut completes_when_stopped);

        // Check that the runner killed the job hosting the exited component.
        let h = job.as_handle_ref();
        let termination_fut = async move {
            fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
                .await
                .expect("failed waiting for termination signal");
        };
        exec.run_singlethreaded(termination_fut);

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    #[test]
    fn test_stop_noncritical_component() -> Result<(), Error> {
        let mut exec = fasync::Executor::new().expect("Unable to create new executor");
        // Presence of the Lifecycle channel isn't use by ElfComponent to sense
        // component exit, but it does modify the stop behavior and this is
        // what we want to test.
        let (lifecycle_client, lifecycle_server) =
            fidl::endpoints::create_proxy_and_stream::<LifecycleMarker>()?;
        let (job, mut component) = make_default_elf_component(Some(lifecycle_client), false);

        let job_info = job.info()?;
        assert!(!job_info.exited);

        // Ask the runner to stop the component, it returns a future which
        // completes when the component closes its side of the lifecycle
        // channel
        let mut completes_when_stopped = component.stop();

        // The returned future shouldn't complete because we're holding the
        // lifecycle channel open.
        match exec.run_until_stalled(&mut completes_when_stopped) {
            Poll::Ready(_) => {
                panic!("runner should still be waiting for lifecycle channel to stop");
            }
            _ => {}
        }
        drop(lifecycle_server);

        match exec.run_until_stalled(&mut completes_when_stopped) {
            Poll::Ready(_) => {}
            _ => {
                panic!("runner future should have completed, lifecycle channel is closed.");
            }
        }
        // Check that the runner killed the job hosting the exited component.
        let h = job.as_handle_ref();
        let termination_fut = async move {
            fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
                .await
                .expect("failed waiting for termination signal");
        };
        exec.run_singlethreaded(termination_fut);

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    /// Stopping a component which doesn't have a lifecycle channel should be
    /// equivalent to killing a component directly.
    #[fasync::run_singlethreaded(test)]
    async fn test_stop_component_without_lifecycle() -> Result<(), Error> {
        let (job, mut component) = make_default_elf_component(None, false);

        let job_info = job.info()?;
        assert!(!job_info.exited);

        component.stop().await;

        let h = job.as_handle_ref();
        fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
            .await
            .expect("failed waiting for termination signal");

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_stop_critical_component_with_closed_lifecycle() -> Result<(), Error> {
        let (lifecycle_client, lifecycle_server) =
            fidl::endpoints::create_proxy_and_stream::<LifecycleMarker>()?;
        let (job, mut component) = make_default_elf_component(Some(lifecycle_client), true);
        let process = component.copy_process().unwrap();
        let job_info = job.info()?;
        assert!(!job_info.exited);

        // Close the lifecycle channel
        drop(lifecycle_server);
        // Kill the process because this is what ElfComponent monitors to
        // determine if the component exited.
        process.kill()?;
        component.stop().await;

        let h = job.as_handle_ref();
        fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
            .await
            .expect("failed waiting for termination signal");

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_stop_noncritical_component_with_closed_lifecycle() -> Result<(), Error> {
        let (lifecycle_client, lifecycle_server) =
            fidl::endpoints::create_proxy_and_stream::<LifecycleMarker>()?;
        let (job, mut component) = make_default_elf_component(Some(lifecycle_client), false);

        let job_info = job.info()?;
        assert!(!job_info.exited);

        // Close the lifecycle channel
        drop(lifecycle_server);
        // Kill the process because this is what ElfComponent monitors to
        // determine if the component exited.
        component.stop().await;

        let h = job.as_handle_ref();
        fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
            .await
            .expect("failed waiting for termination signal");

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    /// Dropping the component should kill the job hosting it.
    #[fasync::run_singlethreaded(test)]
    async fn test_drop() -> Result<(), Error> {
        let (job, component) = make_default_elf_component(None, false);

        let job_info = job.info()?;
        assert!(!job_info.exited);

        drop(component);

        let h = job.as_handle_ref();
        fasync::OnSignals::new(&h, zx::Signals::TASK_TERMINATED)
            .await
            .expect("failed waiting for termination signal");

        let job_info = job.info()?;
        assert!(job_info.exited);
        Ok(())
    }

    /// Modify the standard test StartInfo to request ambient_mark_vmo_exec job policy
    fn lifecycle_startinfo_mark_vmo_exec(
        runtime_dir: Option<ServerEnd<DirectoryMarker>>,
    ) -> fcrunner::ComponentStartInfo {
        let mut start_info = lifecycle_startinfo(runtime_dir);
        start_info.program.as_mut().map(|dict| {
            dict.entries.as_mut().map(|ent| {
                ent.push(fdata::DictionaryEntry {
                    key: "job_policy_ambient_mark_vmo_exec".to_string(),
                    value: Some(Box::new(fdata::DictionaryValue::Str("true".to_string()))),
                });
                ent
            })
        });
        start_info
    }

    // Modify the standard test StartInfo to add a main_process_critical request
    fn hello_world_startinfo_main_process_critical(
        runtime_dir: Option<ServerEnd<DirectoryMarker>>,
    ) -> fcrunner::ComponentStartInfo {
        let mut start_info = hello_world_startinfo(runtime_dir);
        start_info.program.as_mut().map(|dict| {
            dict.entries.as_mut().map(|ent| {
                ent.push(fdata::DictionaryEntry {
                    key: "main_process_critical".to_string(),
                    value: Some(Box::new(fdata::DictionaryValue::Str("true".to_string()))),
                });
                ent
            })
        });
        start_info
    }

    #[fasync::run_singlethreaded(test)]
    async fn vmex_security_policy_denied() -> Result<(), Error> {
        let start_info = lifecycle_startinfo_mark_vmo_exec(None);

        // Config does not allowlist any monikers to have access to the job policy.
        let config = RuntimeConfig {
            use_builtin_process_launcher: should_use_builtin_process_launcher(),
            ..Default::default()
        };
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&Arc::new(config)),
            AbsoluteMoniker::root(),
        ));
        let (controller, server_controller) = create_proxy::<fcrunner::ComponentControllerMarker>()
            .expect("could not create component controller endpoints");

        // Attempting to start the component should fail, which we detect by looking for an
        // ACCESS_DENIED epitaph on the ComponentController's event stream.
        runner.start(start_info, server_controller).await;
        assert_matches!(
            controller.take_event_stream().try_next().await,
            Err(fidl::Error::ClientChannelClosed { status: zx::Status::ACCESS_DENIED, .. })
        );

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn vmex_security_policy_allowed() -> Result<(), Error> {
        let (runtime_dir_client, runtime_dir_server) = zx::Channel::create()?;
        let start_info =
            lifecycle_startinfo_mark_vmo_exec(Some(ServerEnd::new(runtime_dir_server)));
        let runtime_dir_proxy = DirectoryProxy::from_channel(
            fasync::Channel::from_channel(runtime_dir_client).unwrap(),
        );

        let config = Arc::new(RuntimeConfig {
            security_policy: SecurityPolicy {
                job_policy: JobPolicyAllowlists {
                    ambient_mark_vmo_exec: vec![AbsoluteMoniker::from(vec!["foo:0"])],
                    ..Default::default()
                },
                ..Default::default()
            },
            use_builtin_process_launcher: should_use_builtin_process_launcher(),
            ..Default::default()
        });
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&config),
            AbsoluteMoniker::from(vec!["foo:0"]),
        ));
        let (controller, server_controller) = create_proxy::<fcrunner::ComponentControllerMarker>()
            .expect("could not create component controller endpoints");
        runner.start(start_info, server_controller).await;

        // Runtime dir won't exist if the component failed to start.
        let process_id = read_file(&runtime_dir_proxy, "elf/process_id").await.parse::<u64>()?;
        assert!(process_id > 0);
        // Component controller should get shutdown normally; no ACCESS_DENIED epitaph.
        controller.kill().expect("kill failed");

        // We expect the event stream to have closed, which is reported as an
        // error and the value of the error should match the epitaph for a
        // process that was killed.
        match controller.take_event_stream().try_next().await {
            Err(fidl::Error::ClientChannelClosed { status, .. }) => {
                assert_eq!(
                    status,
                    zx::Status::from_raw(
                        i32::try_from(fcomp::Error::InstanceDied.into_primitive()).unwrap()
                    )
                );
            }
            other => panic!("Expected channel closed error, got {:?}", other),
        }

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn critical_security_policy_denied() -> Result<(), Error> {
        let start_info = hello_world_startinfo_main_process_critical(None);

        // Config does not allowlist any monikers to be marked as critical
        let config = RuntimeConfig {
            use_builtin_process_launcher: should_use_builtin_process_launcher(),
            ..Default::default()
        };
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&Arc::new(config)),
            AbsoluteMoniker::root(),
        ));
        let (controller, server_controller) = create_proxy::<fcrunner::ComponentControllerMarker>()
            .expect("could not create component controller endpoints");

        // Attempting to start the component should fail, which we detect by looking for an
        // ACCESS_DENIED epitaph on the ComponentController's event stream.
        runner.start(start_info, server_controller).await;
        assert_matches!(
            controller.take_event_stream().try_next().await,
            Err(fidl::Error::ClientChannelClosed { status: zx::Status::ACCESS_DENIED, .. })
        );

        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    #[should_panic]
    async fn fail_to_launch_critical_component() {
        let mut start_info = hello_world_startinfo_main_process_critical(None);

        start_info.program = start_info.program.map(|mut program| {
            program.entries =
                Some(program.entries.unwrap().into_iter().filter(|e| &e.key != "binary").collect());
            program
        });

        // Config does not allowlist any monikers to be marked as critical
        let config = Arc::new(RuntimeConfig {
            use_builtin_process_launcher: should_use_builtin_process_launcher(),
            security_policy: SecurityPolicy {
                job_policy: JobPolicyAllowlists {
                    main_process_critical: vec![AbsoluteMoniker::from(vec![])],
                    ..Default::default()
                },
                ..Default::default()
            },
            ..Default::default()
        });
        let runner = Arc::new(ElfRunner::new(&config, None));
        let runner = runner.get_scoped_runner(ScopedPolicyChecker::new(
            Arc::downgrade(&config),
            AbsoluteMoniker::root(),
        ));
        let (controller, server_controller) = create_proxy::<fcrunner::ComponentControllerMarker>()
            .expect("could not create component controller endpoints");

        runner.start(start_info, server_controller).await;

        // Starting this component isn't actually possible, as start_info is missing the binary
        // field. We should panic before anything happens on the controller stream, because the
        // component is critical.
        let _ = controller.take_event_stream().try_next().await;
    }
}
