1use anyhow::{Error, format_err};
6use fidl::endpoints::{ProtocolMarker, Proxy};
7use fuchsia_async::{MonotonicDuration, Task};
8use fuchsia_inspect::Inspector;
9use futures::channel::mpsc;
10use futures::channel::oneshot::{self, Canceled};
11use futures::{Future, FutureExt, StreamExt};
12use log::{error, info, warn};
13use std::pin::Pin;
14use wlan_ffi_transport::completers::Completer;
15use wlan_ffi_transport::{EthernetTx, WlanRx};
16use wlan_fidl_ext::{ResponderExt, SendResultExt, WithName};
17use wlan_mlme::device::DeviceOps;
18use wlan_mlme::{DriverEvent, DriverEventSink};
19use wlan_sme::serve::create_sme;
20use {
21 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_sme as fidl_sme,
22 fidl_fuchsia_wlan_softmac as fidl_softmac, wlan_trace as wtrace,
23};
24
25const INSPECT_VMO_SIZE_BYTES: usize = 1000 * 1024;
26
27pub async fn start_and_serve<F, D: DeviceOps + 'static>(
52 start_completer: Completer<F>,
53 device: D,
54) -> Result<(), zx::Status>
55where
56 F: FnOnce(zx::sys::zx_status_t) + 'static,
57{
58 wtrace::duration!("rust_driver::start_and_serve");
59 let (driver_event_sink, driver_event_stream) = DriverEventSink::new();
60
61 let (mlme_init_sender, mlme_init_receiver) = oneshot::channel();
62 let StartedDriver { softmac_ifc_bridge_request_stream, mlme, sme } =
63 match start(mlme_init_sender, driver_event_sink.clone(), driver_event_stream, device).await
64 {
65 Err(status) => {
66 start_completer.reply(Err(status));
67 return Err(status);
68 }
69 Ok(x) => x,
70 };
71
72 start_completer.reply(Ok(()));
73
74 serve(mlme_init_receiver, driver_event_sink, softmac_ifc_bridge_request_stream, mlme, sme).await
75}
76
77struct StartedDriver<Mlme, Sme> {
78 pub softmac_ifc_bridge_request_stream: fidl_softmac::WlanSoftmacIfcBridgeRequestStream,
79 pub mlme: Mlme,
80 pub sme: Sme,
81}
82
83async fn start<D: DeviceOps + 'static>(
91 mlme_init_sender: oneshot::Sender<()>,
92 driver_event_sink: DriverEventSink,
93 driver_event_stream: mpsc::UnboundedReceiver<DriverEvent>,
94 mut device: D,
95) -> Result<
96 StartedDriver<
97 Pin<Box<dyn Future<Output = Result<(), Error>>>>,
98 Pin<Box<impl Future<Output = Result<(), Error>>>>,
99 >,
100 zx::Status,
101> {
102 wtrace::duration!("rust_driver::start");
103
104 let (softmac_ifc_bridge_proxy, softmac_ifc_bridge_request_stream) =
105 fidl::endpoints::create_proxy_and_stream::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
106
107 let BootstrappedGenericSme { generic_sme_request_stream, legacy_privacy_support, inspector } =
109 bootstrap_generic_sme(&mut device, driver_event_sink, softmac_ifc_bridge_proxy).await?;
110
111 info!("Querying device information...");
112
113 let softmac_info = device.wlan_softmac_query_response().await?;
115 let sta_addr = softmac_info.sta_addr;
116 let device_info = match wlan_mlme::mlme_device_info_from_softmac(softmac_info) {
117 Ok(info) => info,
118 Err(e) => {
119 error!("Failed to get MLME device info: {}", e);
120 return Err(zx::Status::INTERNAL);
121 }
122 };
123
124 let security_support = device.security_support().await?;
125 let spectrum_management_support = device.spectrum_management_support().await?;
126
127 info!("Querying complete!");
128
129 let config = wlan_sme::Config {
130 wep_supported: legacy_privacy_support.wep_supported,
131 wpa1_supported: legacy_privacy_support.wpa1_supported,
132 };
133
134 let mlme_event_stream = match device.take_mlme_event_stream() {
137 Some(mlme_event_stream) => mlme_event_stream,
138 None => {
139 error!("Failed to take MLME event stream.");
140 return Err(zx::Status::INTERNAL);
141 }
142 };
143
144 let (mlme_request_stream, sme) = match create_sme(
146 config,
147 mlme_event_stream,
148 &device_info,
149 security_support,
150 spectrum_management_support,
151 inspector,
152 generic_sme_request_stream,
153 ) {
154 Ok((mlme_request_stream, sme)) => (mlme_request_stream, sme),
155 Err(e) => {
156 error!("Failed to create sme: {}", e);
157 return Err(zx::Status::INTERNAL);
158 }
159 };
160
161 let mlme: Pin<Box<dyn Future<Output = Result<(), Error>>>> = match device_info.role {
163 fidl_common::WlanMacRole::Client => {
164 info!("Running wlansoftmac with client role");
165 let config = wlan_mlme::client::ClientConfig {
166 ensure_on_channel_time: MonotonicDuration::from_millis(500).into_nanos(),
167 };
168 Box::pin(wlan_mlme::mlme_main_loop::<wlan_mlme::client::ClientMlme<D>>(
169 mlme_init_sender,
170 config,
171 device,
172 mlme_request_stream,
173 driver_event_stream,
174 ))
175 }
176 fidl_common::WlanMacRole::Ap => {
177 info!("Running wlansoftmac with AP role");
178 let sta_addr = match sta_addr {
179 Some(sta_addr) => sta_addr,
180 None => {
181 error!("Driver provided no STA address.");
182 return Err(zx::Status::INTERNAL);
183 }
184 };
185 let config = ieee80211::Bssid::from(sta_addr);
186 Box::pin(wlan_mlme::mlme_main_loop::<wlan_mlme::ap::Ap<D>>(
187 mlme_init_sender,
188 config,
189 device,
190 mlme_request_stream,
191 driver_event_stream,
192 ))
193 }
194 unsupported => {
195 error!("Unsupported mac role: {:?}", unsupported);
196 return Err(zx::Status::INTERNAL);
197 }
198 };
199
200 Ok(StartedDriver { softmac_ifc_bridge_request_stream, mlme, sme })
201}
202
203async fn serve(
216 mlme_init_receiver: oneshot::Receiver<()>,
217 driver_event_sink: DriverEventSink,
218 softmac_ifc_bridge_request_stream: fidl_softmac::WlanSoftmacIfcBridgeRequestStream,
219 mlme: Pin<Box<dyn Future<Output = Result<(), Error>>>>,
220 sme: Pin<Box<impl Future<Output = Result<(), Error>>>>,
221) -> Result<(), zx::Status> {
222 wtrace::duration!("rust_driver::serve");
223
224 let (bridge_exit_sender, bridge_exit_receiver) = oneshot::channel();
227 let bridge = Task::local(async move {
229 let _: Result<(), ()> = bridge_exit_sender
230 .send(
231 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream)
232 .await,
233 )
234 .map_err(|result| {
235 error!("Failed to send serve_wlan_softmac_ifc_bridge() result: {:?}", result)
236 });
237 });
238
239 let mut mlme = mlme.fuse();
240 let mut sme = sme.fuse();
241
242 let mut bridge_exit_receiver = bridge_exit_receiver.fuse();
247 let mut mlme_init_receiver = mlme_init_receiver.fuse();
248
249 info!("Starting MLME and waiting on MLME initialization to complete...");
250 {
258 wtrace::duration!("initialize MLME");
259 futures::select! {
260 mlme_result = mlme => {
261 match mlme_result {
262 Err(e) => {
263 error!("MLME future completed with error during initialization: {:?}", e);
264 std::mem::drop(bridge);
265 return Err(zx::Status::INTERNAL);
266 }
267 Ok(()) => {
268
269 match mlme_init_receiver.now_or_never() {
275 None | Some(Err(Canceled)) => {
276 error!("MLME future completed before signaling initialization complete.");
277 std::mem::drop(bridge);
278 return Err(zx::Status::INTERNAL);
279 }
280 Some(Ok(())) => {
281 warn!("SME never started. MLME future completed successfully just after initialization.");
282 std::mem::drop(bridge);
283 return Ok(());
284 }
285 }
286 }
287 }
288 }
289 init_result = mlme_init_receiver => {
290 match init_result {
291 Ok(()) => (),
292 Err(e) => {
293 error!("MLME dropped the initialization signaler: {}", e);
294 std::mem::drop(bridge);
295 return Err(zx::Status::INTERNAL);
296 }
297 }
298 },
299 }
300 }
301
302 info!("Starting SME and WlanSoftmacIfc servers...");
303
304 {
306 wtrace::duration!("run MLME and SME");
307 let mut mlme_future_complete = false;
327 loop {
328 futures::select! {
329 mlme_result = mlme => {
330 match mlme_result {
331 Ok(()) => {
332 info!("MLME shut down gracefully.");
333 mlme_future_complete = true;
334 },
335 Err(e) => {
336 error!("MLME shut down with error: {}", e);
337 break Err(zx::Status::INTERNAL)
338 }
339 }
340 }
341 bridge_result = bridge_exit_receiver => {
342 match bridge_result {
347 Err(Canceled) => {
348 error!("SoftmacIfcBridge result sender dropped unexpectedly.");
349 break Err(zx::Status::INTERNAL)
350 }
351 Ok(Err(e)) => {
352 error!("SoftmacIfcBridge server shut down with error: {}", e);
353 break Err(zx::Status::INTERNAL)
354 }
355 Ok(Ok(())) => info!("SoftmacIfcBridge server shut down gracefully"),
356 }
357 }
358 sme_result = sme => {
359 if mlme_future_complete {
360 match sme_result {
361 Err(e) => {
362 error!("SME shut down with error: {}", e);
363 break Err(zx::Status::INTERNAL)
364 }
365 Ok(()) => info!("SME shut down gracefully"),
366 }
367 } else {
368 error!("SME shut down before MLME: {:?}", sme_result);
369 break Err(zx::Status::INTERNAL)
370 }
371 }
372 complete => break Ok(())
373 }
374 }
375 }
376}
377
378struct BootstrappedGenericSme {
379 pub generic_sme_request_stream: fidl_sme::GenericSmeRequestStream,
380 pub legacy_privacy_support: fidl_sme::LegacyPrivacySupport,
381 pub inspector: Inspector,
382}
383
384async fn bootstrap_generic_sme<D: DeviceOps>(
391 device: &mut D,
392 driver_event_sink: DriverEventSink,
393 softmac_ifc_bridge_proxy: fidl_softmac::WlanSoftmacIfcBridgeProxy,
394) -> Result<BootstrappedGenericSme, zx::Status> {
395 wtrace::duration!("rust_driver::bootstrap_generic_sme");
396 info!("Bootstrapping GenericSme...");
397
398 let ifc_bridge = softmac_ifc_bridge_proxy.into_client_end().map_err(|_| {
399 error!(
400 "Failed to convert {} into client end.",
401 fidl_softmac::WlanSoftmacIfcBridgeMarker::DEBUG_NAME
402 );
403 zx::Status::INTERNAL
404 })?;
405
406 let usme_bootstrap_channel_via_iface_creation = match device
410 .start(
411 ifc_bridge,
412 EthernetTx::new(Box::new(driver_event_sink.clone())),
413 WlanRx::new(Box::new(driver_event_sink)),
414 )
415 .await
416 {
417 Ok(channel) => channel,
418 Err(status) => {
419 error!("Failed to receive a UsmeBootstrap handle: {}", status);
420 return Err(status);
421 }
422 };
423 info!("Bootstrap complete!");
424
425 let server = fidl::endpoints::ServerEnd::<fidl_sme::UsmeBootstrapMarker>::new(
426 usme_bootstrap_channel_via_iface_creation,
427 );
428 let mut usme_bootstrap_stream = server.into_stream();
429
430 let (generic_sme_server, legacy_privacy_support, responder) =
431 match usme_bootstrap_stream.next().await {
432 Some(Ok(fidl_sme::UsmeBootstrapRequest::Start {
433 generic_sme_server,
434 legacy_privacy_support,
435 responder,
436 ..
437 })) => (generic_sme_server, legacy_privacy_support, responder),
438 Some(Err(e)) => {
439 error!("Received an error on USME bootstrap request stream: {}", e);
440 return Err(zx::Status::BAD_STATE);
441 }
442 None => {
443 error!("USME bootstrap stream terminated unexpectedly");
446 return Err(zx::Status::BAD_STATE);
447 }
448 };
449
450 let inspector =
451 Inspector::new(fuchsia_inspect::InspectorConfig::default().size(INSPECT_VMO_SIZE_BYTES));
452
453 let inspect_vmo = match inspector.duplicate_vmo() {
454 Some(vmo) => vmo,
455 None => {
456 error!("Failed to duplicate inspect VMO");
457 return Err(zx::Status::INTERNAL);
458 }
459 };
460 if let Err(e) = responder.send(inspect_vmo).into() {
461 error!("Failed to respond to UsmeBootstrap.Start(): {}", e);
462 return Err(zx::Status::INTERNAL);
463 }
464 let generic_sme_request_stream = generic_sme_server.into_stream();
465
466 Ok(BootstrappedGenericSme { generic_sme_request_stream, legacy_privacy_support, inspector })
467}
468
469async fn serve_wlan_softmac_ifc_bridge(
470 driver_event_sink: DriverEventSink,
471 mut softmac_ifc_bridge_request_stream: fidl_softmac::WlanSoftmacIfcBridgeRequestStream,
472) -> Result<(), anyhow::Error> {
473 loop {
474 let request = match softmac_ifc_bridge_request_stream.next().await {
475 Some(Ok(request)) => request,
476 Some(Err(e)) => {
477 return Err(format_err!("WlanSoftmacIfcBridge stream failed: {}", e));
478 }
479 None => {
480 return Err(format_err!(
481 "WlanSoftmacIfcBridge stream terminated unexpectedly by client"
482 ));
483 }
484 };
485 match request {
486 fidl_softmac::WlanSoftmacIfcBridgeRequest::ReportTxResult { tx_result, responder } => {
487 let responder = driver_event_sink.unbounded_send_or_respond(
488 DriverEvent::TxResultReport { tx_result },
489 responder,
490 (),
491 )?;
492 responder.send().format_send_err_with_context("ReportTxResult")?;
493 }
494 fidl_softmac::WlanSoftmacIfcBridgeRequest::NotifyScanComplete {
495 payload,
496 responder,
497 } => {
498 let ((status, scan_id), responder) = responder.unpack_fields_or_respond((
499 payload.status.with_name("status"),
500 payload.scan_id.with_name("scan_id"),
501 ))?;
502 let status = zx::Status::from_raw(status);
503 let responder = driver_event_sink.unbounded_send_or_respond(
504 DriverEvent::ScanComplete { status, scan_id },
505 responder,
506 (),
507 )?;
508 responder.send().format_send_err_with_context("NotifyScanComplete")?;
509 }
510 fidl_softmac::WlanSoftmacIfcBridgeRequest::StopBridgedDriver { responder } => {
511 if let Err(e) = driver_event_sink.unbounded_send(DriverEvent::Stop { responder }) {
512 let error_string = e.to_string();
513 let event = e.into_inner();
514 let e = format_err!("Failed to queue {}: {}", event, error_string);
515 let DriverEvent::Stop { responder } = event else {
516 unreachable!();
517 };
518 responder.send().format_send_err_with_context("StopBridgedDriver")?;
519 return Err(e);
520 }
521 return Ok(());
522 }
523 }
524 }
525}
526
527#[cfg(test)]
528mod tests {
529 use super::*;
530 use anyhow::format_err;
531 use assert_matches::assert_matches;
532 use diagnostics_assertions::assert_data_tree;
533 use fuchsia_async::TestExecutor;
534 use fuchsia_inspect::InspectorConfig;
535 use futures::stream::FuturesUnordered;
536 use futures::task::Poll;
537 use std::pin::pin;
538 use test_case::test_case;
539 use wlan_mlme::device::test_utils::{FakeDevice, FakeDeviceConfig};
540 use zx::Vmo;
541
542 struct BootstrapGenericSmeTestHarness {
543 _softmac_ifc_bridge_request_stream: fidl_softmac::WlanSoftmacIfcBridgeRequestStream,
544 }
545
546 macro_rules! make_bootstrap_generic_sme_test_harness {
551 (&mut $fake_device:ident, $driver_event_sink:ident $(,)?) => {{
552 let (softmac_ifc_bridge_proxy, _softmac_ifc_bridge_request_stream) =
553 fidl::endpoints::create_proxy_and_stream::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
554 (
555 Box::pin(bootstrap_generic_sme(
556 &mut $fake_device,
557 $driver_event_sink,
558 softmac_ifc_bridge_proxy,
559 )),
560 BootstrapGenericSmeTestHarness {
561 _softmac_ifc_bridge_request_stream,
562 }
563 )
564 }};
565 }
566
567 #[fuchsia::test(allow_stalls = false)]
568 async fn bootstrap_generic_sme_fails_to_retrieve_usme_bootstrap_handle() {
569 let (mut fake_device, _fake_device_state) = FakeDevice::new_with_config(
570 FakeDeviceConfig::default().with_mock_start_result(Err(zx::Status::INTERRUPTED_RETRY)),
571 )
572 .await;
573 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
574
575 let (mut bootstrap_generic_sme_fut, _harness) =
576 make_bootstrap_generic_sme_test_harness!(&mut fake_device, driver_event_sink);
577 match TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await {
578 Poll::Ready(Err(zx::Status::INTERRUPTED_RETRY)) => (),
579 Poll::Ready(Err(status)) => panic!("Failed with wrong status: {}", status),
580 Poll::Ready(Ok(_)) => panic!("Succeeded unexpectedly"),
581 Poll::Pending => panic!("bootstrap_generic_sme() unexpectedly stalled"),
582 }
583 }
584
585 #[fuchsia::test(allow_stalls = false)]
586 async fn boostrap_generic_sme_fails_on_error_from_bootstrap_stream() {
587 let (mut fake_device, fake_device_state) =
588 FakeDevice::new_with_config(FakeDeviceConfig::default()).await;
589 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
590
591 let (mut bootstrap_generic_sme_fut, _harness) =
592 make_bootstrap_generic_sme_test_harness!(&mut fake_device, driver_event_sink);
593 assert!(matches!(
594 TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await,
595 Poll::Pending
596 ));
597
598 let usme_bootstrap_channel =
600 fake_device_state.lock().usme_bootstrap_client_end.take().unwrap().into_channel();
601 usme_bootstrap_channel.write(&[], &mut []).unwrap();
602
603 assert!(matches!(
604 TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await,
605 Poll::Ready(Err(zx::Status::BAD_STATE))
606 ));
607 }
608
609 #[fuchsia::test(allow_stalls = false)]
610 async fn boostrap_generic_sme_fails_on_closed_bootstrap_stream() {
611 let (mut fake_device, fake_device_state) =
612 FakeDevice::new_with_config(FakeDeviceConfig::default()).await;
613 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
614
615 let (mut bootstrap_generic_sme_fut, _harness) =
616 make_bootstrap_generic_sme_test_harness!(&mut fake_device, driver_event_sink);
617 assert!(matches!(
618 TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await,
619 Poll::Pending
620 ));
621
622 let _ = fake_device_state.lock().usme_bootstrap_client_end.take().unwrap();
624
625 assert!(matches!(
626 TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await,
627 Poll::Ready(Err(zx::Status::BAD_STATE))
628 ));
629 }
630
631 #[fuchsia::test(allow_stalls = false)]
632 async fn boostrap_generic_sme_succeeds() {
633 let (mut fake_device, fake_device_state) =
634 FakeDevice::new_with_config(FakeDeviceConfig::default()).await;
635 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
636
637 let (mut bootstrap_generic_sme_fut, _harness) =
638 make_bootstrap_generic_sme_test_harness!(&mut fake_device, driver_event_sink);
639 assert!(matches!(
640 TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await,
641 Poll::Pending
642 ));
643
644 let usme_bootstrap_proxy =
645 fake_device_state.lock().usme_bootstrap_client_end.take().unwrap().into_proxy();
646
647 let sent_legacy_privacy_support =
648 fidl_sme::LegacyPrivacySupport { wep_supported: false, wpa1_supported: false };
649 let (generic_sme_proxy, generic_sme_server) =
650 fidl::endpoints::create_proxy::<fidl_sme::GenericSmeMarker>();
651 let inspect_vmo_fut =
652 usme_bootstrap_proxy.start(generic_sme_server, &sent_legacy_privacy_support);
653 let mut inspect_vmo_fut = pin!(inspect_vmo_fut);
654 assert!(matches!(
655 TestExecutor::poll_until_stalled(&mut inspect_vmo_fut).await,
656 Poll::Pending
657 ));
658
659 let BootstrappedGenericSme {
660 mut generic_sme_request_stream,
661 legacy_privacy_support: received_legacy_privacy_support,
662 inspector,
663 } = match TestExecutor::poll_until_stalled(&mut bootstrap_generic_sme_fut).await {
664 Poll::Pending => panic!("bootstrap_generic_sme_fut() did not complete!"),
665 Poll::Ready(x) => x.unwrap(),
666 };
667 let inspect_vmo = match TestExecutor::poll_until_stalled(&mut inspect_vmo_fut).await {
668 Poll::Pending => panic!("Failed to receive an inspect VMO."),
669 Poll::Ready(x) => x.unwrap(),
670 };
671
672 let query_fut = generic_sme_proxy.query();
675 let mut query_fut = pin!(query_fut);
676 assert!(matches!(TestExecutor::poll_until_stalled(&mut query_fut).await, Poll::Pending));
677 let next_generic_sme_request_fut = generic_sme_request_stream.next();
678 let mut next_generic_sme_request_fut = pin!(next_generic_sme_request_fut);
679 assert!(matches!(
680 TestExecutor::poll_until_stalled(&mut next_generic_sme_request_fut).await,
681 Poll::Ready(Some(Ok(fidl_sme::GenericSmeRequest::Query { .. })))
682 ));
683
684 assert_eq!(received_legacy_privacy_support, sent_legacy_privacy_support);
685
686 let returned_inspector = Inspector::new(InspectorConfig::default().vmo(inspect_vmo));
688 let _a = inspector.root().create_child("a");
689 assert_data_tree!(returned_inspector, root: {
690 a: {},
691 });
692 }
693
694 struct StartTestHarness {
695 pub mlme_init_receiver: Pin<Box<oneshot::Receiver<()>>>,
696 #[allow(dead_code)]
698 pub driver_event_sink: DriverEventSink,
699 }
700
701 impl StartTestHarness {
702 fn new(
703 fake_device: FakeDevice,
704 ) -> (
705 impl Future<
706 Output = Result<
707 StartedDriver<
708 Pin<Box<dyn Future<Output = Result<(), Error>>>>,
709 Pin<Box<impl Future<Output = Result<(), Error>>>>,
710 >,
711 zx::Status,
712 >,
713 >,
714 Self,
715 ) {
716 let (mlme_init_sender, mlme_init_receiver) = oneshot::channel();
717 let (driver_event_sink, driver_event_stream) = DriverEventSink::new();
718
719 (
720 Box::pin(start(
721 mlme_init_sender,
722 driver_event_sink.clone(),
723 driver_event_stream,
724 fake_device,
725 )),
726 Self { mlme_init_receiver: Box::pin(mlme_init_receiver), driver_event_sink },
727 )
728 }
729 }
730
731 #[fuchsia::test(allow_stalls = false)]
732 async fn start_fails_on_bad_bootstrap() {
733 let (fake_device, _fake_device_state) = FakeDevice::new_with_config(
734 FakeDeviceConfig::default().with_mock_start_result(Err(zx::Status::INTERRUPTED_RETRY)),
735 )
736 .await;
737 let (mut start_fut, _harness) = StartTestHarness::new(fake_device);
738
739 assert!(matches!(
740 TestExecutor::poll_until_stalled(&mut start_fut).await,
741 Poll::Ready(Err(zx::Status::INTERRUPTED_RETRY))
742 ));
743 }
744
745 fn bootstrap_generic_sme_proxy_and_inspect_vmo(
746 usme_bootstrap_client_end: fidl::endpoints::ClientEnd<fidl_sme::UsmeBootstrapMarker>,
747 ) -> (fidl_sme::GenericSmeProxy, impl Future<Output = Result<Vmo, fidl::Error>>) {
748 let usme_client_proxy = usme_bootstrap_client_end.into_proxy();
749
750 let legacy_privacy_support =
751 fidl_sme::LegacyPrivacySupport { wep_supported: false, wpa1_supported: false };
752 let (generic_sme_proxy, generic_sme_server) =
753 fidl::endpoints::create_proxy::<fidl_sme::GenericSmeMarker>();
754 (generic_sme_proxy, usme_client_proxy.start(generic_sme_server, &legacy_privacy_support))
755 }
756
757 #[test_case(FakeDeviceConfig::default().with_mock_query_response(Err(zx::Status::IO_DATA_INTEGRITY)), zx::Status::IO_DATA_INTEGRITY)]
758 #[test_case(FakeDeviceConfig::default().with_mock_security_support(Err(zx::Status::IO_DATA_INTEGRITY)), zx::Status::IO_DATA_INTEGRITY)]
759 #[test_case(FakeDeviceConfig::default().with_mock_spectrum_management_support(Err(zx::Status::IO_DATA_INTEGRITY)), zx::Status::IO_DATA_INTEGRITY)]
760 #[test_case(FakeDeviceConfig::default().with_mock_mac_role(fidl_common::WlanMacRole::__SourceBreaking { unknown_ordinal: 0 }), zx::Status::INTERNAL)]
761 #[fuchsia::test(allow_stalls = false)]
762 async fn start_fails_on_query_error(
763 fake_device_config: FakeDeviceConfig,
764 expected_status: zx::Status,
765 ) {
766 let (fake_device, fake_device_state) =
767 FakeDevice::new_with_config(fake_device_config).await;
768 let (mut start_fut, _harness) = StartTestHarness::new(fake_device);
769
770 let usme_bootstrap_client_end =
771 fake_device_state.lock().usme_bootstrap_client_end.take().unwrap();
772 let (_generic_sme_proxy, _inspect_vmo_fut) =
773 bootstrap_generic_sme_proxy_and_inspect_vmo(usme_bootstrap_client_end);
774
775 match TestExecutor::poll_until_stalled(&mut start_fut).await {
776 Poll::Ready(Err(status)) => assert_eq!(status, expected_status),
777 Poll::Pending => panic!("start_fut still pending!"),
778 Poll::Ready(Ok(_)) => panic!("start_fut completed with Ok value"),
779 }
780 }
781
782 #[fuchsia::test(allow_stalls = false)]
783 async fn start_fail_on_dropped_mlme_event_stream() {
784 let (fake_device, fake_device_state) = FakeDevice::new().await;
785 let (mut start_fut, _harness) = StartTestHarness::new(fake_device);
786
787 let usme_bootstrap_client_end =
788 fake_device_state.lock().usme_bootstrap_client_end.take().unwrap();
789 let (_generic_sme_proxy, _inspect_vmo_fut) =
790 bootstrap_generic_sme_proxy_and_inspect_vmo(usme_bootstrap_client_end);
791
792 let _ = fake_device_state.lock().mlme_event_stream.take();
793 match TestExecutor::poll_until_stalled(&mut start_fut).await {
794 Poll::Ready(Err(status)) => assert_eq!(status, zx::Status::INTERNAL),
795 Poll::Pending => panic!("start_fut still pending!"),
796 Poll::Ready(Ok(_)) => panic!("start_fut completed with Ok value"),
797 }
798 }
799
800 #[fuchsia::test(allow_stalls = false)]
801 async fn start_succeeds() {
802 let (fake_device, fake_device_state) = FakeDevice::new_with_config(
803 FakeDeviceConfig::default()
804 .with_mock_sta_addr([2u8; 6])
805 .with_mock_mac_role(fidl_common::WlanMacRole::Client),
806 )
807 .await;
808 let (mut start_fut, mut harness) = StartTestHarness::new(fake_device);
809
810 let usme_bootstrap_client_end =
811 fake_device_state.lock().usme_bootstrap_client_end.take().unwrap();
812 let (generic_sme_proxy, _inspect_vmo_fut) =
813 bootstrap_generic_sme_proxy_and_inspect_vmo(usme_bootstrap_client_end);
814
815 let StartedDriver {
816 softmac_ifc_bridge_request_stream: _softmac_ifc_bridge_request_stream,
817 mut mlme,
818 sme,
819 } = match TestExecutor::poll_until_stalled(&mut start_fut).await {
820 Poll::Ready(Ok(x)) => x,
821 Poll::Ready(Err(status)) => {
822 panic!("start_fut unexpectedly failed; {}", status)
823 }
824 Poll::Pending => panic!("start_fut still pending!"),
825 };
826
827 assert_matches!(TestExecutor::poll_until_stalled(&mut mlme).await, Poll::Pending);
828 assert!(matches!(
829 TestExecutor::poll_until_stalled(&mut harness.mlme_init_receiver).await,
830 Poll::Ready(Ok(()))
831 ));
832
833 let resp_fut = generic_sme_proxy.query();
834 let mut resp_fut = pin!(resp_fut);
835 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
836
837 let sme_and_mlme = [sme, mlme].into_iter().collect::<FuturesUnordered<_>>();
838 let mut sme_and_mlme = pin!(sme_and_mlme);
839 assert!(matches!(
840 TestExecutor::poll_until_stalled(&mut sme_and_mlme.next()).await,
841 Poll::Pending
842 ));
843
844 assert!(matches!(
845 TestExecutor::poll_until_stalled(&mut resp_fut).await,
846 Poll::Ready(Ok(fidl_sme::GenericSmeQuery {
847 role: fidl_common::WlanMacRole::Client,
848 sta_addr: [2, 2, 2, 2, 2, 2],
849 factory_addr: [2, 2, 2, 2, 2, 2],
850 }))
851 ));
852 }
853
854 #[fuchsia::test(allow_stalls = false)]
855 async fn serve_wlansoftmac_ifc_bridge_fails_on_request_stream_error() {
856 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
857 let (softmac_ifc_bridge_client, softmac_ifc_bridge_server) =
858 fidl::endpoints::create_endpoints::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
859 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
860 let softmac_ifc_bridge_channel = softmac_ifc_bridge_client.into_channel();
861
862 let server_fut =
863 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream);
864 let mut server_fut = pin!(server_fut);
865 assert_matches!(TestExecutor::poll_until_stalled(&mut server_fut).await, Poll::Pending);
866
867 softmac_ifc_bridge_channel.write(&[], &mut []).unwrap();
868 assert_matches!(
869 TestExecutor::poll_until_stalled(&mut server_fut).await,
870 Poll::Ready(Err(_))
871 );
872 }
873
874 #[fuchsia::test(allow_stalls = false)]
875 async fn serve_wlansoftmac_ifc_bridge_exits_on_request_stream_end() {
876 let (driver_event_sink, _driver_event_stream) = DriverEventSink::new();
877 let (softmac_ifc_bridge_client, softmac_ifc_bridge_server) =
878 fidl::endpoints::create_endpoints::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
879 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
880
881 let server_fut =
882 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream);
883 let mut server_fut = pin!(server_fut);
884 assert_matches!(TestExecutor::poll_until_stalled(&mut server_fut).await, Poll::Pending);
885
886 drop(softmac_ifc_bridge_client);
887 assert_matches!(
888 TestExecutor::poll_until_stalled(&mut server_fut).await,
889 Poll::Ready(Err(_))
890 );
891 }
892
893 #[test_case(fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest {
894 status: None,
895 scan_id: Some(754),
896 ..Default::default()
897 })]
898 #[test_case(fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest {
899 status: Some(zx::Status::OK.into_raw()),
900 scan_id: None,
901 ..Default::default()
902 })]
903 #[fuchsia::test(allow_stalls = false)]
904 async fn serve_wlansoftmac_ifc_bridge_exits_on_invalid_notify_scan_complete_request(
905 request: fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest,
906 ) {
907 let (driver_event_sink, mut driver_event_stream) = DriverEventSink::new();
908 let (softmac_ifc_bridge_proxy, softmac_ifc_bridge_server) =
909 fidl::endpoints::create_proxy::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
910 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
911
912 let server_fut =
913 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream);
914 let mut server_fut = pin!(server_fut);
915
916 let resp_fut = softmac_ifc_bridge_proxy.notify_scan_complete(&request);
917 let mut resp_fut = pin!(resp_fut);
918 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
919 assert_matches!(
920 TestExecutor::poll_until_stalled(&mut server_fut).await,
921 Poll::Ready(Err(_))
922 );
923 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Ready(Ok(())));
924 assert!(matches!(driver_event_stream.try_next(), Ok(None)));
925 }
926
927 #[fuchsia::test(allow_stalls = false)]
928 async fn serve_wlansoftmac_ifc_bridge_enqueues_notify_scan_complete() {
929 let (driver_event_sink, mut driver_event_stream) = DriverEventSink::new();
930 let (softmac_ifc_bridge_proxy, softmac_ifc_bridge_server) =
931 fidl::endpoints::create_proxy::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
932 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
933
934 let server_fut =
935 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream);
936 let mut server_fut = pin!(server_fut);
937
938 let resp_fut = softmac_ifc_bridge_proxy.notify_scan_complete(
939 &fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest {
940 status: Some(zx::Status::OK.into_raw()),
941 scan_id: Some(754),
942 ..Default::default()
943 },
944 );
945 let mut resp_fut = pin!(resp_fut);
946 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
947 assert_matches!(TestExecutor::poll_until_stalled(&mut server_fut).await, Poll::Pending);
948 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Ready(Ok(())));
949
950 assert!(matches!(
951 driver_event_stream.try_next(),
952 Ok(Some(DriverEvent::ScanComplete { status: zx::Status::OK, scan_id: 754 }))
953 ));
954 }
955
956 struct ServeTestHarness {
957 pub mlme_init_sender: oneshot::Sender<()>,
958 pub driver_event_stream: mpsc::UnboundedReceiver<DriverEvent>,
959 pub softmac_ifc_bridge_proxy: fidl_softmac::WlanSoftmacIfcBridgeProxy,
960 pub complete_mlme_sender: oneshot::Sender<Result<(), anyhow::Error>>,
961 pub complete_sme_sender: oneshot::Sender<Result<(), anyhow::Error>>,
962 }
963
964 impl ServeTestHarness {
965 fn new() -> (Pin<Box<impl Future<Output = Result<(), zx::Status>>>>, ServeTestHarness) {
966 let (mlme_init_sender, mlme_init_receiver) = oneshot::channel();
967 let (driver_event_sink, driver_event_stream) = DriverEventSink::new();
968 let (softmac_ifc_bridge_proxy, softmac_ifc_bridge_server) =
969 fidl::endpoints::create_proxy::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
970 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
971 let (complete_mlme_sender, complete_mlme_receiver) = oneshot::channel();
972 let mlme = Box::pin(async { complete_mlme_receiver.await.unwrap() });
973 let (complete_sme_sender, complete_sme_receiver) = oneshot::channel();
974 let sme = Box::pin(async { complete_sme_receiver.await.unwrap() });
975
976 (
977 Box::pin(serve(
978 mlme_init_receiver,
979 driver_event_sink,
980 softmac_ifc_bridge_request_stream,
981 mlme,
982 sme,
983 )),
984 ServeTestHarness {
985 mlme_init_sender,
986 driver_event_stream,
987 softmac_ifc_bridge_proxy,
988 complete_mlme_sender,
989 complete_sme_sender,
990 },
991 )
992 }
993 }
994
995 #[fuchsia::test(allow_stalls = false)]
996 async fn serve_wlansoftmac_ifc_bridge_enqueues_report_tx_result() {
997 let (driver_event_sink, mut driver_event_stream) = DriverEventSink::new();
998 let (softmac_ifc_bridge_proxy, softmac_ifc_bridge_server) =
999 fidl::endpoints::create_proxy::<fidl_softmac::WlanSoftmacIfcBridgeMarker>();
1000 let softmac_ifc_bridge_request_stream = softmac_ifc_bridge_server.into_stream();
1001
1002 let server_fut =
1003 serve_wlan_softmac_ifc_bridge(driver_event_sink, softmac_ifc_bridge_request_stream);
1004 let mut server_fut = pin!(server_fut);
1005
1006 let resp_fut = softmac_ifc_bridge_proxy.report_tx_result(&fidl_common::WlanTxResult {
1007 tx_result_entry: [fidl_common::WlanTxResultEntry {
1008 tx_vector_idx: fidl_common::WLAN_TX_VECTOR_IDX_INVALID,
1009 attempts: 0,
1010 }; fidl_common::WLAN_TX_RESULT_MAX_ENTRY as usize],
1011 peer_addr: [3; 6],
1012 result_code: fidl_common::WlanTxResultCode::Failed,
1013 });
1014 let mut resp_fut = pin!(resp_fut);
1015 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
1016 assert_matches!(TestExecutor::poll_until_stalled(&mut server_fut).await, Poll::Pending);
1017 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Ready(Ok(())));
1018
1019 match driver_event_stream.try_next().unwrap().unwrap() {
1020 DriverEvent::TxResultReport { tx_result } => {
1021 assert_eq!(
1022 tx_result,
1023 fidl_common::WlanTxResult {
1024 tx_result_entry: [fidl_common::WlanTxResultEntry {
1025 tx_vector_idx: fidl_common::WLAN_TX_VECTOR_IDX_INVALID,
1026 attempts: 0
1027 };
1028 fidl_common::WLAN_TX_RESULT_MAX_ENTRY as usize],
1029 peer_addr: [3; 6],
1030 result_code: fidl_common::WlanTxResultCode::Failed,
1031 }
1032 );
1033 }
1034 _ => panic!("Unexpected DriverEvent!"),
1035 }
1036 }
1037
1038 #[fuchsia::test(allow_stalls = false)]
1039 async fn serve_exits_with_error_if_mlme_init_sender_dropped() {
1040 let (mut serve_fut, harness) = ServeTestHarness::new();
1041
1042 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1043 drop(harness.mlme_init_sender);
1044 assert_matches!(
1045 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1046 Poll::Ready(Err(zx::Status::INTERNAL))
1047 );
1048 }
1049
1050 #[fuchsia::test(allow_stalls = false)]
1051 async fn serve_exits_successfully_if_mlme_completes_just_before_init_sender_dropped() {
1052 let (mut serve_fut, harness) = ServeTestHarness::new();
1053
1054 harness.complete_mlme_sender.send(Ok(())).unwrap();
1055 drop(harness.mlme_init_sender);
1056 assert_matches!(
1057 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1058 Poll::Ready(Err(zx::Status::INTERNAL))
1059 );
1060 }
1061
1062 #[fuchsia::test(allow_stalls = false)]
1063 async fn serve_exits_successfully_if_mlme_completes_just_before_init() {
1064 let (mut serve_fut, harness) = ServeTestHarness::new();
1065
1066 harness.complete_mlme_sender.send(Ok(())).unwrap();
1067 harness.mlme_init_sender.send(()).unwrap();
1068 assert_matches!(
1069 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1070 Poll::Ready(Ok(()))
1071 );
1072 }
1073
1074 #[test_case(Ok(()))]
1075 #[test_case(Err(format_err!("")))]
1076 #[fuchsia::test(allow_stalls = false)]
1077 async fn serve_exits_with_error_if_mlme_completes_before_init(
1078 early_mlme_result: Result<(), Error>,
1079 ) {
1080 let (mut serve_fut, harness) = ServeTestHarness::new();
1081
1082 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1083 harness.complete_mlme_sender.send(early_mlme_result).unwrap();
1084 assert_matches!(
1085 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1086 Poll::Ready(Err(zx::Status::INTERNAL))
1087 );
1088 }
1089
1090 #[test_case(Ok(()))]
1091 #[test_case(Err(format_err!("")))]
1092 #[fuchsia::test(allow_stalls = false)]
1093 async fn serve_exits_with_error_if_sme_shuts_down_before_mlme(
1094 early_sme_result: Result<(), Error>,
1095 ) {
1096 let (mut serve_fut, harness) = ServeTestHarness::new();
1097
1098 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1099 harness.mlme_init_sender.send(()).unwrap();
1100 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1101 harness.complete_sme_sender.send(early_sme_result).unwrap();
1102 assert_matches!(
1103 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1104 Poll::Ready(Err(zx::Status::INTERNAL))
1105 );
1106 }
1107
1108 #[fuchsia::test(allow_stalls = false)]
1109 async fn serve_exits_with_error_if_mlme_completes_with_error() {
1110 let (mut serve_fut, harness) = ServeTestHarness::new();
1111
1112 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1113 harness.mlme_init_sender.send(()).unwrap();
1114 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1115 harness.complete_mlme_sender.send(Err(format_err!("mlme error"))).unwrap();
1116 assert_eq!(
1117 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1118 Poll::Ready(Err(zx::Status::INTERNAL))
1119 );
1120 }
1121
1122 #[fuchsia::test(allow_stalls = false)]
1123 async fn serve_exits_with_error_if_sme_shuts_down_with_error() {
1124 let (mut serve_fut, harness) = ServeTestHarness::new();
1125
1126 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1127 harness.mlme_init_sender.send(()).unwrap();
1128 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1129 harness.complete_mlme_sender.send(Ok(())).unwrap();
1130 harness.complete_sme_sender.send(Err(format_err!("sme error"))).unwrap();
1131 assert_eq!(
1132 TestExecutor::poll_until_stalled(&mut serve_fut).await,
1133 Poll::Ready(Err(zx::Status::INTERNAL))
1134 );
1135 }
1136
1137 #[fuchsia::test(allow_stalls = false)]
1138 async fn serve_exits_with_error_if_bridge_exits_early_with_error() {
1139 let (mut serve_fut, harness) = ServeTestHarness::new();
1140
1141 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1142 harness.mlme_init_sender.send(()).unwrap();
1143 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1144
1145 drop(harness.softmac_ifc_bridge_proxy);
1147 assert_eq!(serve_fut.await, Err(zx::Status::INTERNAL));
1148 }
1149
1150 #[fuchsia::test(allow_stalls = false)]
1151 async fn serve_exits_with_error_if_bridge_cannot_queue_stop() {
1152 let (mut serve_fut, harness) = ServeTestHarness::new();
1153
1154 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1155 harness.mlme_init_sender.send(()).unwrap();
1156 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1157
1158 drop(harness.driver_event_stream);
1160 harness.softmac_ifc_bridge_proxy.stop_bridged_driver().await.unwrap();
1161 assert_eq!(serve_fut.await, Err(zx::Status::INTERNAL));
1162 }
1163
1164 #[test_case(true)]
1165 #[test_case(false)]
1166 #[fuchsia::test(allow_stalls = false)]
1167 async fn serve_shuts_down_gracefully(bridge_shutdown_before_mlme: bool) {
1168 let (mut serve_fut, mut harness) = ServeTestHarness::new();
1169
1170 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1171 harness.mlme_init_sender.send(()).unwrap();
1172 assert_matches!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1173 let mut stop_response_fut = harness.softmac_ifc_bridge_proxy.stop_bridged_driver();
1174
1175 if bridge_shutdown_before_mlme {
1185 assert_matches!(
1186 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
1187 Poll::Pending
1188 );
1189 let responder = assert_matches!(harness.driver_event_stream.next().await,
1190 Some(DriverEvent::Stop{ responder }) => responder);
1191 responder.send().unwrap();
1192 assert_matches!(
1193 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
1194 Poll::Ready(Ok(()))
1195 );
1196
1197 harness.complete_mlme_sender.send(Ok(())).unwrap();
1198 } else {
1199 harness.complete_mlme_sender.send(Ok(())).unwrap();
1200 assert_eq!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1201
1202 assert_matches!(
1203 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
1204 Poll::Pending
1205 );
1206 let responder = assert_matches!(harness.driver_event_stream.next().await,
1207 Some(DriverEvent::Stop{ responder }) => responder);
1208 responder.send().unwrap();
1209 assert_matches!(
1210 TestExecutor::poll_until_stalled(&mut stop_response_fut).await,
1211 Poll::Ready(Ok(()))
1212 );
1213 }
1214
1215 assert_eq!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Pending);
1216 harness.complete_sme_sender.send(Ok(())).unwrap();
1217 assert_eq!(TestExecutor::poll_until_stalled(&mut serve_fut).await, Poll::Ready(Ok(())));
1218 }
1219
1220 #[derive(Debug)]
1221 struct StartAndServeTestHarness<F> {
1222 pub start_and_serve_fut: F,
1223 pub start_complete_receiver: oneshot::Receiver<zx::sys::zx_status_t>,
1224 pub generic_sme_proxy: fidl_sme::GenericSmeProxy,
1225 }
1226
1227 async fn start_and_serve_with_device(
1235 fake_device: FakeDevice,
1236 ) -> Result<StartAndServeTestHarness<impl Future<Output = Result<(), zx::Status>>>, zx::Status>
1237 {
1238 let (start_complete_sender, mut start_complete_receiver) =
1239 oneshot::channel::<zx::sys::zx_status_t>();
1240 let start_and_serve_fut = start_and_serve(
1241 Completer::new(move |status| {
1242 start_complete_sender.send(status).expect("Failed to signal start complete.")
1243 }),
1244 fake_device.clone(),
1245 );
1246 let mut start_and_serve_fut = Box::pin(start_and_serve_fut);
1247
1248 let usme_bootstrap_client_end = fake_device.state().lock().usme_bootstrap_client_end.take();
1249 match usme_bootstrap_client_end {
1250 None => match TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await {
1253 Poll::Pending => panic!(
1254 "start_and_serve() failed to exit when the UsmeBootstrap client was dropped."
1255 ),
1256 Poll::Ready(result) => {
1257 assert_matches!(
1258 TestExecutor::poll_until_stalled(&mut start_complete_receiver).await,
1259 Poll::Ready(Ok(status)) => assert_ne!(status, zx::Status::OK.into_raw())
1260 );
1261 return Err(result.unwrap_err());
1262 }
1263 },
1264 Some(usme_bootstrap_client_end) => {
1267 let (generic_sme_proxy, inspect_vmo_fut) =
1268 bootstrap_generic_sme_proxy_and_inspect_vmo(usme_bootstrap_client_end);
1269 let start_and_serve_fut = match TestExecutor::poll_until_stalled(
1270 &mut start_and_serve_fut,
1271 )
1272 .await
1273 {
1274 Poll::Pending => start_and_serve_fut,
1275 Poll::Ready(result) => {
1276 assert_matches!(
1277 TestExecutor::poll_until_stalled(&mut start_complete_receiver)
1278 .await,
1279 Poll::Ready(Ok(status)) => assert_ne!(status, zx::Status::OK.into_raw())
1280 );
1281 return Err(result.unwrap_err());
1282 }
1283 };
1284
1285 inspect_vmo_fut.await.expect("Failed to bootstrap USME.");
1286
1287 Ok(StartAndServeTestHarness {
1288 start_and_serve_fut,
1289 start_complete_receiver,
1290 generic_sme_proxy,
1291 })
1292 }
1293 }
1294 }
1295
1296 #[fuchsia::test(allow_stalls = false)]
1297 async fn start_and_serve_fails_on_dropped_usme_bootstrap_client() {
1298 let (fake_device, fake_device_state) = FakeDevice::new().await;
1299 fake_device_state.lock().usme_bootstrap_client_end = None;
1300 match start_and_serve_with_device(fake_device.clone()).await {
1301 Ok(_) => panic!(
1302 "start_and_serve() does not fail when the UsmeBootstrap client end is dropped."
1303 ),
1304 Err(status) => assert_eq!(status, zx::Status::BAD_STATE),
1305 }
1306 }
1307
1308 #[fuchsia::test(allow_stalls = false)]
1310 async fn start_and_serve_fails_on_dropped_mlme_event_stream() {
1311 let (mut fake_device, _fake_device_state) = FakeDevice::new().await;
1312 let _ = fake_device.take_mlme_event_stream();
1313 match start_and_serve_with_device(fake_device.clone()).await {
1314 Ok(_) => {
1315 panic!("start_and_serve() does not fail when the MLME event stream is missing.")
1316 }
1317 Err(status) => assert_eq!(status, zx::Status::INTERNAL),
1318 }
1319 }
1320
1321 #[fuchsia::test(allow_stalls = false)]
1322 async fn start_and_serve_fails_on_dropped_generic_sme_client() {
1323 let (fake_device, _fake_device_state) = FakeDevice::new().await;
1324 let StartAndServeTestHarness {
1325 mut start_and_serve_fut,
1326 mut start_complete_receiver,
1327 generic_sme_proxy,
1328 } = start_and_serve_with_device(fake_device)
1329 .await
1330 .expect("Failed to initiate wlansoftmac setup.");
1331 assert_matches!(
1332 TestExecutor::poll_until_stalled(&mut start_complete_receiver).await,
1333 Poll::Ready(Ok(status)) => assert_eq!(zx::Status::OK.into_raw(), status)
1334 );
1335 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1336
1337 drop(generic_sme_proxy);
1338
1339 assert_eq!(
1340 TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await,
1341 Poll::Ready(Err(zx::Status::INTERNAL))
1342 );
1343 }
1344
1345 #[fuchsia::test(allow_stalls = false)]
1346 async fn start_and_serve_shuts_down_gracefully() {
1347 let (fake_device, fake_device_state) = FakeDevice::new().await;
1348 let StartAndServeTestHarness {
1349 mut start_and_serve_fut,
1350 mut start_complete_receiver,
1351 generic_sme_proxy: _generic_sme_proxy,
1352 } = start_and_serve_with_device(fake_device)
1353 .await
1354 .expect("Failed to initiate wlansoftmac setup.");
1355 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1356 assert_matches!(
1357 TestExecutor::poll_until_stalled(&mut start_complete_receiver).await,
1358 Poll::Ready(Ok(status)) => assert_eq!(zx::Status::OK.into_raw(), status)
1359 );
1360
1361 let wlan_softmac_ifc_bridge_proxy =
1362 fake_device_state.lock().wlan_softmac_ifc_bridge_proxy.take().unwrap();
1363 let stop_response_fut = wlan_softmac_ifc_bridge_proxy.stop_bridged_driver();
1364 assert_matches!(futures::join!(start_and_serve_fut, stop_response_fut), (Ok(()), Ok(())));
1365 }
1366
1367 #[fuchsia::test(allow_stalls = false)]
1368 async fn start_and_serve_responds_to_generic_sme_requests() {
1369 let (fake_device, fake_device_state) = FakeDevice::new().await;
1370 let StartAndServeTestHarness {
1371 mut start_and_serve_fut,
1372 mut start_complete_receiver,
1373 generic_sme_proxy,
1374 } = start_and_serve_with_device(fake_device)
1375 .await
1376 .expect("Failed to initiate wlansoftmac setup.");
1377 assert_matches!(
1378 TestExecutor::poll_until_stalled(&mut start_complete_receiver).await,
1379 Poll::Ready(Ok(status)) => assert_eq!(zx::Status::OK.into_raw(), status)
1380 );
1381
1382 let (sme_telemetry_proxy, sme_telemetry_server) = fidl::endpoints::create_proxy();
1383 let (client_sme_proxy, client_sme_server) = fidl::endpoints::create_proxy();
1384
1385 let resp_fut = generic_sme_proxy.get_sme_telemetry(sme_telemetry_server);
1386 let mut resp_fut = pin!(resp_fut);
1387
1388 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
1391 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1392 assert_matches!(
1393 TestExecutor::poll_until_stalled(&mut resp_fut).await,
1394 Poll::Ready(Ok(Ok(())))
1395 );
1396
1397 let resp_fut = generic_sme_proxy.get_client_sme(client_sme_server);
1398 let mut resp_fut = pin!(resp_fut);
1399
1400 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
1403 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1404 resp_fut.await.expect("Generic SME proxy failed").expect("Client SME request failed");
1405
1406 let wlan_softmac_ifc_bridge_proxy =
1407 fake_device_state.lock().wlan_softmac_ifc_bridge_proxy.take().unwrap();
1408 let stop_response_fut = wlan_softmac_ifc_bridge_proxy.stop_bridged_driver();
1409 assert_matches!(futures::join!(start_and_serve_fut, stop_response_fut), (Ok(()), Ok(())));
1410
1411 assert!(generic_sme_proxy.is_closed());
1413 assert!(sme_telemetry_proxy.is_closed());
1414 assert!(client_sme_proxy.is_closed());
1415 }
1416
1417 #[fuchsia::test(allow_stalls = false)]
1422 async fn start_and_serve_responds_to_passive_scan_request() {
1423 let (fake_device, fake_device_state) = FakeDevice::new().await;
1424 let StartAndServeTestHarness {
1425 mut start_and_serve_fut,
1426 mut start_complete_receiver,
1427 generic_sme_proxy,
1428 } = start_and_serve_with_device(fake_device)
1429 .await
1430 .expect("Failed to initiate wlansoftmac setup.");
1431 assert_matches!(
1432 TestExecutor::poll_until_stalled(&mut start_complete_receiver).await,
1433 Poll::Ready(Ok(status)) => assert_eq!(zx::Status::OK.into_raw(), status)
1434 );
1435
1436 let (client_sme_proxy, client_sme_server) = fidl::endpoints::create_proxy();
1437
1438 let resp_fut = generic_sme_proxy.get_client_sme(client_sme_server);
1439 let mut resp_fut = pin!(resp_fut);
1440 assert_matches!(TestExecutor::poll_until_stalled(&mut resp_fut).await, Poll::Pending);
1441 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1442 assert!(matches!(
1443 TestExecutor::poll_until_stalled(&mut resp_fut).await,
1444 Poll::Ready(Ok(Ok(())))
1445 ));
1446
1447 let scan_response_fut =
1448 client_sme_proxy.scan(&fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest {}));
1449 let mut scan_response_fut = pin!(scan_response_fut);
1450 assert!(matches!(
1451 TestExecutor::poll_until_stalled(&mut scan_response_fut).await,
1452 Poll::Pending
1453 ));
1454
1455 assert!(fake_device_state.lock().captured_passive_scan_request.is_none());
1456 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1457 assert!(fake_device_state.lock().captured_passive_scan_request.is_some());
1458
1459 let wlan_softmac_ifc_bridge_proxy =
1460 fake_device_state.lock().wlan_softmac_ifc_bridge_proxy.take().unwrap();
1461 let notify_scan_complete_fut = wlan_softmac_ifc_bridge_proxy.notify_scan_complete(
1462 &fidl_softmac::WlanSoftmacIfcBaseNotifyScanCompleteRequest {
1463 status: Some(zx::Status::OK.into_raw()),
1464 scan_id: Some(0),
1465 ..Default::default()
1466 },
1467 );
1468 notify_scan_complete_fut.await.expect("Failed to receive NotifyScanComplete response");
1469 assert_eq!(TestExecutor::poll_until_stalled(&mut start_and_serve_fut).await, Poll::Pending);
1470 assert!(matches!(
1471 TestExecutor::poll_until_stalled(&mut scan_response_fut).await,
1472 Poll::Ready(Ok(_))
1473 ));
1474
1475 let stop_response_fut = wlan_softmac_ifc_bridge_proxy.stop_bridged_driver();
1476 assert_matches!(futures::join!(start_and_serve_fut, stop_response_fut), (Ok(()), Ok(())));
1477
1478 assert!(generic_sme_proxy.is_closed());
1480 assert!(client_sme_proxy.is_closed());
1481 }
1482}