1use crate::above_root_capabilities::AboveRootCapabilitiesForTest;
6use crate::debug_data_processor::{DebugDataDirectory, DebugDataProcessor};
7use crate::error::TestManagerError;
8use crate::offers::map_offers;
9use crate::running_suite::{RunningSuite, enumerate_test_cases};
10use crate::self_diagnostics::RootDiagnosticNode;
11use crate::test_suite::{Suite, SuiteRealm};
12use crate::{constants, debug_data_server, facet};
13use fidl::Error;
14use fidl_fuchsia_component_resolution::ResolverProxy;
15use fidl_fuchsia_pkg::PackageResolverProxy;
16use fidl_fuchsia_test_manager as ftest_manager;
17use ftest_manager::LaunchError;
18use fuchsia_async::{self as fasync};
19use futures::prelude::*;
20use log::{error, warn};
21use std::sync::Arc;
22
23pub async fn serve_early_boot_profiles(
24 mut stream: ftest_manager::EarlyBootProfileRequestStream,
25) -> Result<(), TestManagerError> {
26 while let Some(req) = stream.try_next().await.map_err(TestManagerError::Stream)? {
27 match req {
28 ftest_manager::EarlyBootProfileRequest::RegisterWatcher {
29 iterator,
30 control_handle,
31 } => {
32 let iterator = iterator.into_stream();
33 if let Err(e) = debug_data_server::send_kernel_debug_data(iterator).await {
34 warn!("Err serving kernel profiles: {}", e);
35 control_handle.shutdown_with_epitaph(zx::Status::INTERNAL);
36 break;
37 }
38 }
39 ftest_manager::EarlyBootProfileRequest::_UnknownMethod {
40 ordinal,
41 control_handle,
42 ..
43 } => {
44 warn!("Unknown EarlyBootProfile request received: {}, closing connection", ordinal);
45 control_handle.shutdown_with_epitaph(zx::Status::NOT_SUPPORTED);
46 break;
47 }
48 }
49 }
50 Ok(())
51}
52
53pub async fn run_test_manager_test_case_enumerator_server(
55 mut stream: ftest_manager::TestCaseEnumeratorRequestStream,
56 resolver: Arc<ResolverProxy>,
57 pkg_resolver: Arc<PackageResolverProxy>,
58 above_root_capabilities_for_test: Arc<AboveRootCapabilitiesForTest>,
59 root_diagnostics: &RootDiagnosticNode,
60) -> Result<(), TestManagerError> {
61 while let Some(req) = stream.try_next().await.map_err(TestManagerError::Stream)? {
62 match req {
63 ftest_manager::TestCaseEnumeratorRequest::Enumerate {
64 test_suite_url,
65 options,
66 iterator,
67 responder,
68 } => {
69 let realm = if let Some(realm_options) = options.realm_options {
70 let realm_proxy = match realm_options
71 .realm
72 .map(|r| Ok(r.into_proxy()))
73 .unwrap_or(Err(Error::NotNullable))
74 {
75 Ok(r) => r,
76 Err(e) => {
77 warn!(
78 "Cannot enumerate test cases {}, invalid realm. Closing connection. error: {}",
79 test_suite_url, e
80 );
81 responder.send(Err(LaunchError::InvalidArgs)).ok();
82 break;
83 }
84 };
85 let offers = match realm_options
86 .offers
87 .map(map_offers)
88 .unwrap_or(Err(Error::NotNullable.into()))
89 {
90 Ok(offers) => offers,
91 Err(e) => {
92 warn!(
93 "Cannot enumerate test cases {}, invalid offers. error: {}",
94 test_suite_url, e
95 );
96 responder.send(Err(LaunchError::InvalidArgs)).ok();
97 break;
98 }
99 };
100 let test_collection = match realm_options.test_collection {
101 Some(test_collection) => test_collection,
102 None => {
103 warn!(
104 "Cannot enumerate test cases {}, missing test collection.",
105 test_suite_url
106 );
107 responder.send(Err(LaunchError::InvalidArgs)).ok();
108 break;
109 }
110 };
111 Some(SuiteRealm { realm_proxy, offers, test_collection })
112 } else {
113 None
114 };
115
116 let iterator = iterator.into_stream();
117 let (_processor, sender) = DebugDataProcessor::new(DebugDataDirectory::Isolated {
118 parent: constants::ISOLATED_TMP,
119 });
120 let diagnostics = root_diagnostics.child();
121 let launch_fut = facet::get_suite_facets(test_suite_url.clone(), resolver.clone())
122 .and_then(|facets| {
123 RunningSuite::launch(
124 &test_suite_url,
125 facets,
126 resolver.clone(),
127 pkg_resolver.clone(),
128 above_root_capabilities_for_test.clone(),
129 sender,
130 &diagnostics,
131 &realm,
132 false, )
134 });
135 match launch_fut.await {
136 Ok(suite_instance) => {
137 let suite = match suite_instance.connect_to_suite() {
138 Ok(proxy) => proxy,
139 Err(e) => {
140 responder.send(Err(e.into())).ok();
141 continue;
142 }
143 };
144 let enumeration_result = enumerate_test_cases(&suite, None).await;
145 let t = fasync::Task::spawn(suite_instance.destroy(diagnostics));
146 match enumeration_result {
147 Ok(invocations) => {
148 if let Ok(names) = invocations
149 .into_iter()
150 .map(|i| i.name.ok_or(()))
151 .collect::<Result<Vec<String>, ()>>()
152 {
153 responder.send(Ok(())).ok();
154 drain_test_case_names(iterator, names).await;
155 } else {
156 responder.send(Err(LaunchError::CaseEnumeration)).ok();
157 }
158 }
159 Err(err) => {
160 warn!(err:?; "cannot enumerate tests for {}", test_suite_url);
161 responder.send(Err(LaunchError::CaseEnumeration)).ok();
162 }
163 }
164 if let Err(err) = t.await {
165 warn!(err:?; "Error destroying test realm for {}", test_suite_url);
166 }
167 }
168 Err(e) => {
169 responder.send(Err(e.into())).ok();
170 }
171 }
172 }
173
174 ftest_manager::TestCaseEnumeratorRequest::_UnknownMethod {
175 ordinal,
176 control_handle,
177 ..
178 } => {
179 warn!("Unknown query request received: {}, closing connection", ordinal);
180 control_handle.shutdown_with_epitaph(zx::Status::NOT_SUPPORTED);
181 break;
182 }
183 };
184 }
185 Ok(())
186}
187
188async fn drain_test_case_names(
189 mut iterator: ftest_manager::TestCaseIteratorRequestStream,
190 names: Vec<String>,
191) {
192 const NAMES_CHUNK: usize = 50;
193 let mut names = names.chunks(NAMES_CHUNK);
194 while let Ok(Some(request)) = iterator.try_next().await {
195 match request {
196 ftest_manager::TestCaseIteratorRequest::GetNext { responder } => match names.next() {
197 Some(names) => {
198 responder
199 .send(
200 &names
201 .iter()
202 .map(|s| ftest_manager::TestCase {
203 name: Some(s.into()),
204 ..Default::default()
205 })
206 .collect::<Vec<_>>(),
207 )
208 .ok();
209 }
210 None => {
211 responder.send(&[]).ok();
212 }
213 },
214 }
215 }
216}
217
218pub async fn run_test_manager_suite_runner_server(
220 mut stream: ftest_manager::SuiteRunnerRequestStream,
221 resolver: Arc<ResolverProxy>,
222 pkg_resolver: Arc<PackageResolverProxy>,
223 above_root_capabilities_for_test: Arc<AboveRootCapabilitiesForTest>,
224 root_diagnostics: &RootDiagnosticNode,
225) -> Result<(), TestManagerError> {
226 while let Some(req) = stream.try_next().await.map_err(TestManagerError::Stream)? {
227 match req {
228 ftest_manager::SuiteRunnerRequest::Run {
229 test_suite_url,
230 mut options,
231 controller,
232 control_handle,
233 } => {
234 let realm = if let Some(realm_options) = options.realm_options.take() {
235 let realm_proxy = match realm_options
236 .realm
237 .map(|r| Ok(r.into_proxy()))
238 .unwrap_or(Err(Error::NotNullable))
239 {
240 Ok(r) => r,
241 Err(e) => {
242 warn!(
243 "Cannot run suite {}, invalid realm. Closing connection. error: {}",
244 test_suite_url, e
245 );
246 control_handle.shutdown_with_epitaph(zx::Status::INVALID_ARGS);
247 break;
248 }
249 };
250 let offers = match realm_options
251 .offers
252 .map(map_offers)
253 .unwrap_or(Err(Error::NotNullable.into()))
254 {
255 Ok(offers) => offers,
256 Err(e) => {
257 warn!(
258 "Cannot run suite {}, invalid offers. error: {}",
259 test_suite_url, e
260 );
261 control_handle.shutdown_with_epitaph(zx::Status::INVALID_ARGS);
262 break;
263 }
264 };
265 let test_collection = match realm_options.test_collection {
266 Some(test_collection) => test_collection,
267 None => {
268 warn!("Cannot run suite {}, missing test collection.", test_suite_url);
269 control_handle.shutdown_with_epitaph(zx::Status::INVALID_ARGS);
270 break;
271 }
272 };
273 Some(SuiteRealm { realm_proxy, offers, test_collection })
274 } else {
275 None
276 };
277
278 match options.logs_iterator_type {
280 Some(ftest_manager::LogsIteratorType::Batch)
281 | Some(ftest_manager::LogsIteratorType::Socket)
282 | None => {
283 }
285 Some(t) => {
286 error!("Unrecognized log iterator type {:?}.", t);
287 control_handle.shutdown_with_epitaph(zx::Status::INVALID_ARGS);
288 break;
289 }
290 }
291
292 let controller = controller.into_stream();
293 let accumulate_debug_data = options.accumulate_debug_data.unwrap_or(false);
294
295 let suite = Suite {
296 realm: realm.into(),
297 test_url: test_suite_url,
298 options,
299 controller,
300 resolver: resolver.clone(),
301 pkg_resolver: pkg_resolver.clone(),
302 above_root_capabilities_for_test: above_root_capabilities_for_test.clone(),
303 facets: facet::ResolveStatus::Unresolved,
304 };
305
306 let diagnostics = root_diagnostics.child();
307
308 suite.run(diagnostics, accumulate_debug_data).await;
309 }
310
311 ftest_manager::SuiteRunnerRequest::_UnknownMethod {
312 ordinal, control_handle, ..
313 } => {
314 warn!("Unknown run builder request received: {}, closing connection", ordinal);
315 control_handle.shutdown_with_epitaph(zx::Status::NOT_SUPPORTED);
316 break;
317 }
318 }
319 }
320 Ok(())
321}