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