test_runners_elf_lib/
test_server.rs1use crate::launcher::ComponentLauncher;
6use async_trait::async_trait;
7use fidl_fuchsia_test::{
8 self as ftest, Invocation, Result_ as TestResult, RunListenerProxy, Status,
9};
10use fuchsia_async as fasync;
11use futures::future::{abortable, AbortHandle};
12use futures::prelude::*;
13use futures::TryStreamExt;
14use log::{debug, error};
15use std::sync::{Arc, Weak};
16use test_runners_lib::cases::TestCaseInfo;
17use test_runners_lib::elf::{Component, EnumeratedTestCases, KernelError, SuiteServer};
18use test_runners_lib::errors::*;
19use test_runners_lib::logs::SocketLogWriter;
20
21#[derive(Default)]
23pub struct TestServer<T: ComponentLauncher> {
24 pub launcher: T,
25}
26
27static PARALLEL_DEFAULT: u16 = 1;
28
29#[async_trait]
30impl<T: 'static> SuiteServer for TestServer<T>
31where
32 T: ComponentLauncher,
33{
34 async fn enumerate_tests(
39 &self,
40 _test_component: Arc<Component>,
41 ) -> Result<EnumeratedTestCases, EnumerationError> {
42 Ok(Arc::new(vec![TestCaseInfo { name: "main".to_string(), enabled: true }]))
43 }
44
45 async fn run_tests(
46 &self,
47 invocations: Vec<Invocation>,
48 run_options: ftest::RunOptions,
49 component: Arc<Component>,
50 run_listener: &RunListenerProxy,
51 ) -> Result<(), RunTestError> {
52 let num_parallel =
53 Self::get_parallel_count(run_options.parallel.unwrap_or(PARALLEL_DEFAULT));
54
55 let invocations = stream::iter(invocations);
56 invocations
57 .map(Ok)
58 .try_for_each_concurrent(num_parallel, |invocation| {
59 self.run_test(invocation, &run_options, component.clone(), run_listener)
60 })
61 .await
62 }
63
64 fn run(
66 self,
67 weak_component: Weak<Component>,
68 test_url: &str,
69 stream: ftest::SuiteRequestStream,
70 ) -> AbortHandle {
71 let test_url = test_url.to_owned();
72 let (fut, test_suite_abortable_handle) =
73 abortable(self.serve_test_suite(stream, weak_component));
74
75 fasync::Task::local(async move {
76 match fut.await {
77 Ok(result) => {
78 if let Err(e) = result {
79 error!("server failed for test {}: {:?}", test_url, e);
80 }
81 }
82 Err(e) => debug!("server aborted for test {}: {:?}", test_url, e),
83 }
84 debug!("Done running server for {}.", test_url);
85 })
86 .detach();
87 test_suite_abortable_handle
88 }
89}
90
91impl<T: 'static> TestServer<T>
92where
93 T: ComponentLauncher,
94{
95 pub fn new(launcher_: T) -> Self {
96 Self { launcher: launcher_ }
97 }
98
99 pub fn validate_args(_args: &Vec<String>) -> Result<(), ArgumentError> {
100 Ok(())
103 }
104
105 async fn run_test<'a>(
106 &'a self,
107 invocation: Invocation,
108 run_options: &ftest::RunOptions,
109 component: Arc<Component>,
110 run_listener: &RunListenerProxy,
111 ) -> Result<(), RunTestError> {
112 if "main" != *invocation.name.as_ref().ok_or(RunTestError::TestCaseName)? {
113 return Ok(());
115 }
116
117 let (test_stdout, stdout_client) = zx::Socket::create_stream();
118 let (test_stderr, stderr_client) = zx::Socket::create_stream();
119 let (case_listener_proxy, listener) =
120 fidl::endpoints::create_proxy::<fidl_fuchsia_test::CaseListenerMarker>();
121 run_listener
122 .on_test_case_started(
123 &invocation,
124 ftest::StdHandles {
125 out: Some(stdout_client),
126 err: Some(stderr_client),
127 ..Default::default()
128 },
129 listener,
130 )
131 .map_err(RunTestError::SendStart)?;
132 let mut test_stdout = SocketLogWriter::new(fasync::Socket::from_socket(test_stdout));
133 let mut test_stderr = SocketLogWriter::new(fasync::Socket::from_socket(test_stderr));
134
135 let mut args = component.args.clone();
136 if let Some(user_args) = &run_options.arguments {
137 args.extend(user_args.clone());
138 }
139
140 let (process, _job, stdout_logger, stderr_logger) =
142 self.launcher.launch_process(&component, args).await?;
143
144 let stdout_fut = stdout_logger.buffer_and_drain(&mut test_stdout);
146 let stderr_fut = stderr_logger.buffer_and_drain(&mut test_stderr);
148 let (ret1, ret2) = futures::future::join(stdout_fut, stderr_fut).await;
149 ret1?;
150 ret2?;
151
152 fasync::OnSignals::new(&process, zx::Signals::PROCESS_TERMINATED)
154 .await
155 .map_err(KernelError::ProcessExit)
156 .unwrap();
157 let process_info = process.info().map_err(RunTestError::ProcessInfo)?;
158
159 let status = match process_info.return_code {
161 0 => Status::Passed,
162 _ => Status::Failed,
163 };
164 case_listener_proxy
165 .finished(&TestResult { status: Some(status), ..Default::default() })
166 .map_err(RunTestError::SendFinish)?;
167 Ok(())
168 }
169}