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