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