test_runners_elf_lib/
launcher.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use async_trait::async_trait;
6use std::sync::LazyLock;
7use test_runners_lib::elf::{Component, KernelError};
8use test_runners_lib::errors::*;
9use test_runners_lib::launch;
10use test_runners_lib::logs::LoggerStream;
11use zx::{self as zx, HandleBased};
12use {fidl_fuchsia_process as fproc, fuchsia_runtime as runtime};
13
14static NEXT_VDSO: LazyLock<zx::Handle> = LazyLock::new(|| {
15    runtime::take_startup_handle(runtime::HandleInfo::new(runtime::HandleType::VdsoVmo, 0))
16        .expect("failed to take next vDSO handle")
17});
18
19#[async_trait]
20pub trait ComponentLauncher: Sized + Sync + Send {
21    /// Convenience wrapper around [`launch::launch_process`].
22    async fn launch_process(
23        &self,
24        component: &Component,
25        args: Vec<String>,
26    ) -> Result<(zx::Process, launch::ScopedJob, LoggerStream, LoggerStream), RunTestError>;
27}
28
29#[derive(Default)]
30pub struct ElfComponentLauncher {}
31
32#[async_trait]
33impl ComponentLauncher for ElfComponentLauncher {
34    /// Convenience wrapper around [`launch::launch_process`].
35    async fn launch_process(
36        &self,
37        component: &Component,
38        args: Vec<String>,
39    ) -> Result<(zx::Process, launch::ScopedJob, LoggerStream, LoggerStream), RunTestError> {
40        let (client_end, loader) = fidl::endpoints::create_endpoints();
41        component.loader_service(loader);
42        let executable_vmo = Some(component.executable_vmo()?);
43        let handle_infos = vec![fproc::HandleInfo {
44            handle: (*NEXT_VDSO)
45                .duplicate_handle(zx::Rights::SAME_RIGHTS)
46                .map_err(launch::LaunchError::DuplicateVdso)?,
47            id: runtime::HandleInfo::new(runtime::HandleType::VdsoVmo, 0).as_raw(),
48        }];
49
50        Ok(launch::launch_process_with_separate_std_handles(launch::LaunchProcessArgs {
51            bin_path: &component.binary,
52            process_name: &component.name,
53            job: Some(component.job.create_child_job().map_err(KernelError::CreateJob).unwrap()),
54            ns: component.ns.clone(),
55            args: Some(args),
56            name_infos: None,
57            environs: component.environ.clone(),
58            handle_infos: Some(handle_infos),
59            loader_proxy_chan: Some(client_end.into_channel()),
60            executable_vmo,
61            options: component.options,
62            config_vmo: component.config_vmo()?,
63            url: Some(component.url.clone()),
64            component_instance: component
65                .component_instance
66                .as_ref()
67                .map(|c| c.duplicate_handle(zx::Rights::SAME_RIGHTS).unwrap()),
68        })
69        .await?)
70    }
71}
72
73impl ElfComponentLauncher {
74    pub fn new() -> Self {
75        Self {}
76    }
77}