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