1use crate::access_point::{state_machine as ap_fsm, types as ap_types};
6use crate::client::types as client_types;
7use crate::config_management::network_config::Credential;
8use crate::mode_management::iface_manager_types::*;
9use crate::mode_management::{Defect, IfaceFailure};
10use anyhow::{Error, bail, format_err};
11use async_trait::async_trait;
12use fidl::endpoints::create_proxy;
13use fidl_fuchsia_wlan_sme as fidl_sme;
14use fuchsia_async::TimeoutExt;
15use futures::channel::{mpsc, oneshot};
16use futures::{TryFutureExt, TryStreamExt};
17use log::{info, warn};
18use wlan_telemetry::TimeoutSource;
19
20const SCAN_TIMEOUT: fuchsia_async::MonotonicDuration =
23 fuchsia_async::MonotonicDuration::from_seconds(60);
24const CONNECT_TIMEOUT: fuchsia_async::MonotonicDuration =
25 fuchsia_async::MonotonicDuration::from_seconds(30);
26const DISCONNECT_TIMEOUT: fuchsia_async::MonotonicDuration =
27 fuchsia_async::MonotonicDuration::from_seconds(10);
28const START_AP_TIMEOUT: fuchsia_async::MonotonicDuration =
29 fuchsia_async::MonotonicDuration::from_seconds(30);
30const STOP_AP_TIMEOUT: fuchsia_async::MonotonicDuration =
31 fuchsia_async::MonotonicDuration::from_seconds(10);
32const AP_STATUS_TIMEOUT: fuchsia_async::MonotonicDuration =
33 fuchsia_async::MonotonicDuration::from_seconds(10);
34
35#[async_trait(?Send)]
36pub trait IfaceManagerApi {
37 async fn disconnect(
40 &mut self,
41 network_id: ap_types::NetworkIdentifier,
42 reason: client_types::DisconnectReason,
43 ) -> Result<(), Error>;
44
45 async fn connect(&mut self, connect_req: ConnectAttemptRequest) -> Result<(), Error>;
49
50 async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error>;
52
53 async fn has_idle_client(&mut self) -> Result<bool, Error>;
55
56 async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error>;
59
60 async fn handle_removed_iface(&mut self, iface_id: u16) -> Result<(), Error>;
62
63 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error>;
65
66 async fn stop_client_connections(
69 &mut self,
70 reason: client_types::DisconnectReason,
71 ) -> Result<(), Error>;
72
73 async fn start_client_connections(&mut self) -> Result<(), Error>;
75
76 async fn start_ap(&mut self, config: ap_fsm::ApConfig) -> Result<oneshot::Receiver<()>, Error>;
78
79 async fn stop_ap(&mut self, ssid: Ssid, password: Vec<u8>) -> Result<(), Error>;
81
82 async fn stop_all_aps(&mut self) -> Result<(), Error>;
84
85 async fn set_country(
87 &mut self,
88 country_code: Option<client_types::CountryCode>,
89 ) -> Result<(), Error>;
90}
91
92#[derive(Clone)]
93pub struct IfaceManager {
94 pub sender: mpsc::Sender<IfaceManagerRequest>,
95}
96
97#[async_trait(?Send)]
98impl IfaceManagerApi for IfaceManager {
99 async fn disconnect(
100 &mut self,
101 network_id: ap_types::NetworkIdentifier,
102 reason: client_types::DisconnectReason,
103 ) -> Result<(), Error> {
104 let (responder, receiver) = oneshot::channel();
105 let req = DisconnectRequest { network_id, responder, reason };
106 self.sender.try_send(IfaceManagerRequest::Disconnect(req))?;
107
108 receiver.await?
109 }
110
111 async fn connect(&mut self, connect_req: ConnectAttemptRequest) -> Result<(), Error> {
112 let (responder, receiver) = oneshot::channel();
113 let req = ConnectRequest { request: connect_req, responder };
114 self.sender.try_send(IfaceManagerRequest::Connect(req))?;
115
116 receiver.await?
117 }
118
119 async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error> {
120 let (responder, receiver) = oneshot::channel();
121 let req = RecordIdleIfaceRequest { iface_id, responder };
122 self.sender.try_send(IfaceManagerRequest::RecordIdleIface(req))?;
123 receiver.await?;
124 Ok(())
125 }
126
127 async fn has_idle_client(&mut self) -> Result<bool, Error> {
128 let (responder, receiver) = oneshot::channel();
129 let req = HasIdleIfaceRequest { responder };
130 self.sender.try_send(IfaceManagerRequest::HasIdleIface(req))?;
131 receiver.await.map_err(|e| e.into())
132 }
133
134 async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error> {
135 let (responder, receiver) = oneshot::channel();
136 let req = AddIfaceRequest { iface_id, responder };
137 self.sender.try_send(IfaceManagerRequest::AddIface(req))?;
138 receiver.await?;
139 Ok(())
140 }
141
142 async fn handle_removed_iface(&mut self, iface_id: u16) -> Result<(), Error> {
143 let (responder, receiver) = oneshot::channel();
144 let req = RemoveIfaceRequest { iface_id, responder };
145 self.sender.try_send(IfaceManagerRequest::RemoveIface(req))?;
146 receiver.await?;
147 Ok(())
148 }
149
150 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
151 let (responder, receiver) = oneshot::channel();
152 let req = ScanProxyRequest { responder };
153 self.sender.try_send(IfaceManagerRequest::GetScanProxy(req))?;
154 receiver.await?
155 }
156
157 async fn start_client_connections(&mut self) -> Result<(), Error> {
158 let (responder, receiver) = oneshot::channel();
159 let req = StartClientConnectionsRequest { responder };
160 self.sender.try_send(IfaceManagerRequest::StartClientConnections(req))?;
161 receiver.await?
162 }
163
164 async fn start_ap(&mut self, config: ap_fsm::ApConfig) -> Result<oneshot::Receiver<()>, Error> {
165 let (responder, receiver) = oneshot::channel();
166 let req = StartApRequest { config, responder };
167 self.sender.try_send(IfaceManagerRequest::StartAp(req))?;
168 receiver.await?
169 }
170
171 async fn stop_client_connections(
172 &mut self,
173 reason: client_types::DisconnectReason,
174 ) -> Result<(), Error> {
175 let (responder, receiver) = oneshot::channel();
176 let req = StopClientConnectionsRequest { responder, reason };
177 self.sender.try_send(IfaceManagerRequest::StopClientConnections(req))?;
178 receiver.await?
179 }
180
181 async fn stop_ap(&mut self, ssid: Ssid, password: Vec<u8>) -> Result<(), Error> {
182 let (responder, receiver) = oneshot::channel();
183 let req = StopApRequest { ssid, password, responder };
184 self.sender.try_send(IfaceManagerRequest::StopAp(req))?;
185 receiver.await?
186 }
187
188 async fn stop_all_aps(&mut self) -> Result<(), Error> {
189 let (responder, receiver) = oneshot::channel();
190 let req = StopAllApsRequest { responder };
191 self.sender.try_send(IfaceManagerRequest::StopAllAps(req))?;
192 receiver.await?
193 }
194
195 async fn set_country(
196 &mut self,
197 country_code: Option<client_types::CountryCode>,
198 ) -> Result<(), Error> {
199 let (responder, receiver) = oneshot::channel();
200 let req = SetCountryRequest { country_code, responder };
201 self.sender.try_send(IfaceManagerRequest::SetCountry(req))?;
202 receiver.await?
203 }
204}
205
206trait DefectReporter {
207 fn defect_sender(&self) -> mpsc::Sender<Defect>;
208
209 fn report_defect(&self, defect: Defect) {
210 let mut defect_sender = self.defect_sender();
211 if let Err(e) = defect_sender.try_send(defect) {
212 warn!("Failed to report defect {:?}: {:?}", defect, e)
213 }
214 }
215}
216
217#[derive(Debug)]
218pub struct SmeForScan {
219 proxy: fidl_sme::ClientSmeProxy,
220 iface_id: u16,
221 defect_sender: mpsc::Sender<Defect>,
222}
223
224impl SmeForScan {
225 pub fn new(
226 proxy: fidl_sme::ClientSmeProxy,
227 iface_id: u16,
228 defect_sender: mpsc::Sender<Defect>,
229 ) -> Self {
230 SmeForScan { proxy, iface_id, defect_sender }
231 }
232
233 pub async fn scan(
234 &self,
235 req: &fidl_sme::ScanRequest,
236 ) -> Result<fidl_sme::ClientSmeScanResult, Error> {
237 self.proxy
238 .scan(req)
239 .map_err(|e| format_err!("{:?}", e))
240 .on_timeout(SCAN_TIMEOUT, || {
241 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
242 iface_id: self.iface_id,
243 source: TimeoutSource::Scan,
244 }));
245 Err(format_err!("Timed out waiting on scan response from SME"))
246 })
247 .await
248 }
249
250 pub fn log_aborted_scan_defect(&self) {
251 self.report_defect(Defect::Iface(IfaceFailure::CanceledScan { iface_id: self.iface_id }))
252 }
253
254 pub fn log_failed_scan_defect(&self) {
255 self.report_defect(Defect::Iface(IfaceFailure::FailedScan { iface_id: self.iface_id }))
256 }
257
258 pub fn log_empty_scan_defect(&self) {
259 self.report_defect(Defect::Iface(IfaceFailure::EmptyScanResults {
260 iface_id: self.iface_id,
261 }))
262 }
263}
264
265impl DefectReporter for SmeForScan {
266 fn defect_sender(&self) -> mpsc::Sender<Defect> {
267 self.defect_sender.clone()
268 }
269}
270
271#[derive(Clone, Debug)]
272pub struct SmeForClientStateMachine {
273 proxy: fidl_sme::ClientSmeProxy,
274 iface_id: u16,
275 defect_sender: mpsc::Sender<Defect>,
276}
277
278impl SmeForClientStateMachine {
279 pub fn new(
280 proxy: fidl_sme::ClientSmeProxy,
281 iface_id: u16,
282 defect_sender: mpsc::Sender<Defect>,
283 ) -> Self {
284 Self { proxy, iface_id, defect_sender }
285 }
286
287 pub async fn connect(
288 &self,
289 req: &fidl_sme::ConnectRequest,
290 ) -> Result<(fidl_sme::ConnectResult, fidl_sme::ConnectTransactionEventStream), anyhow::Error>
291 {
292 let (connect_txn, remote) = create_proxy();
293
294 self.proxy
295 .connect(req, Some(remote))
296 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))?;
297
298 let mut stream = connect_txn.take_event_stream();
299 let result = wait_for_connect_result(&mut stream)
300 .on_timeout(CONNECT_TIMEOUT, || {
301 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
302 iface_id: self.iface_id,
303 source: TimeoutSource::Connect,
304 }));
305 Err(format_err!("Timed out waiting for connect result from SME."))
306 })
307 .await?;
308
309 Ok((result, stream))
310 }
311
312 pub async fn disconnect(&self, reason: fidl_sme::UserDisconnectReason) -> Result<(), Error> {
313 self.proxy
314 .disconnect(reason)
315 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
316 .on_timeout(DISCONNECT_TIMEOUT, || {
317 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
318 iface_id: self.iface_id,
319 source: TimeoutSource::Disconnect,
320 }));
321 Err(format_err!("Timed out waiting for disconnect"))
322 })
323 .await
324 }
325
326 pub fn roam(&self, req: &fidl_sme::RoamRequest) -> Result<(), Error> {
327 self.proxy.roam(req).map_err(|e| format_err!("Failed to send roam command: {:}", e))
328 }
329
330 pub fn take_event_stream(&self) -> fidl_sme::ClientSmeEventStream {
331 self.proxy.take_event_stream()
332 }
333
334 pub fn sme_for_scan(&self) -> SmeForScan {
335 SmeForScan {
336 proxy: self.proxy.clone(),
337 iface_id: self.iface_id,
338 defect_sender: self.defect_sender.clone(),
339 }
340 }
341}
342
343impl DefectReporter for SmeForClientStateMachine {
344 fn defect_sender(&self) -> mpsc::Sender<Defect> {
345 self.defect_sender.clone()
346 }
347}
348
349async fn wait_for_connect_result(
351 stream: &mut fidl_sme::ConnectTransactionEventStream,
352) -> Result<fidl_sme::ConnectResult, Error> {
353 loop {
354 let stream_fut = stream.try_next();
355 match stream_fut
356 .await
357 .map_err(|e| format_err!("Failed to receive connect result from sme: {:?}", e))?
358 {
359 Some(fidl_sme::ConnectTransactionEvent::OnConnectResult { result }) => {
360 return Ok(result);
361 }
362 Some(other) => {
363 info!(
364 "Expected ConnectTransactionEvent::OnConnectResult, got {}. Ignoring.",
365 connect_txn_event_name(&other)
366 );
367 }
368 None => {
369 bail!("Server closed the ConnectTransaction channel before sending a response");
370 }
371 };
372 }
373}
374
375fn connect_txn_event_name(event: &fidl_sme::ConnectTransactionEvent) -> &'static str {
376 match event {
377 fidl_sme::ConnectTransactionEvent::OnConnectResult { .. } => "OnConnectResult",
378 fidl_sme::ConnectTransactionEvent::OnRoamResult { .. } => "OnRoamResult",
379 fidl_sme::ConnectTransactionEvent::OnDisconnect { .. } => "OnDisconnect",
380 fidl_sme::ConnectTransactionEvent::OnSignalReport { .. } => "OnSignalReport",
381 fidl_sme::ConnectTransactionEvent::OnChannelSwitched { .. } => "OnChannelSwitched",
382 }
383}
384
385#[derive(Clone, Debug)]
386pub struct SmeForApStateMachine {
387 proxy: fidl_sme::ApSmeProxy,
388 iface_id: u16,
389 defect_sender: mpsc::Sender<Defect>,
390}
391
392impl SmeForApStateMachine {
393 pub fn new(
394 proxy: fidl_sme::ApSmeProxy,
395 iface_id: u16,
396 defect_sender: mpsc::Sender<Defect>,
397 ) -> Self {
398 Self { proxy, iface_id, defect_sender }
399 }
400
401 pub async fn start(
402 &self,
403 config: &fidl_sme::ApConfig,
404 ) -> Result<fidl_sme::StartApResultCode, Error> {
405 self.proxy
406 .start(config)
407 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
408 .on_timeout(START_AP_TIMEOUT, || {
409 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
410 iface_id: self.iface_id,
411 source: TimeoutSource::ApStart,
412 }));
413 Err(format_err!("Timed out waiting for AP to start"))
414 })
415 .await
416 }
417
418 pub async fn stop(&self) -> Result<fidl_sme::StopApResultCode, Error> {
419 self.proxy
420 .stop()
421 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
422 .on_timeout(STOP_AP_TIMEOUT, || {
423 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
424 iface_id: self.iface_id,
425 source: TimeoutSource::ApStop,
426 }));
427 Err(format_err!("Timed out waiting for AP to stop"))
428 })
429 .await
430 }
431
432 pub async fn status(&self) -> Result<fidl_sme::ApStatusResponse, Error> {
433 self.proxy
434 .status()
435 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
436 .on_timeout(AP_STATUS_TIMEOUT, || {
437 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
438 iface_id: self.iface_id,
439 source: TimeoutSource::ApStatus,
440 }));
441 Err(format_err!("Timed out waiting for AP status"))
442 })
443 .await
444 }
445
446 pub fn take_event_stream(&self) -> fidl_sme::ApSmeEventStream {
447 self.proxy.take_event_stream()
448 }
449}
450
451impl DefectReporter for SmeForApStateMachine {
452 fn defect_sender(&self) -> mpsc::Sender<Defect> {
453 self.defect_sender.clone()
454 }
455}
456
457#[cfg_attr(test, derive(Debug))]
459#[derive(Clone, PartialEq)]
460pub struct ConnectAttemptRequest {
461 pub network: client_types::NetworkIdentifier,
462 pub credential: Credential,
463 pub reason: client_types::ConnectReason,
464 pub attempts: u8,
465}
466
467impl ConnectAttemptRequest {
468 pub fn new(
469 network: client_types::NetworkIdentifier,
470 credential: Credential,
471 reason: client_types::ConnectReason,
472 ) -> Self {
473 ConnectAttemptRequest { network, credential, reason, attempts: 0 }
474 }
475}
476
477impl From<client_types::ConnectSelection> for ConnectAttemptRequest {
478 fn from(selection: client_types::ConnectSelection) -> ConnectAttemptRequest {
479 ConnectAttemptRequest::new(
480 selection.target.network,
481 selection.target.credential,
482 selection.reason,
483 )
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use super::*;
490 use crate::access_point::types;
491 use crate::util::testing::{generate_connect_selection, poll_sme_req};
492 use anyhow::format_err;
493 use assert_matches::assert_matches;
494 use fidl::endpoints::{RequestStream, create_proxy};
495 use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
496 use fidl_fuchsia_wlan_internal as fidl_internal;
497 use fuchsia_async as fasync;
498 use futures::StreamExt;
499 use futures::future::LocalBoxFuture;
500 use futures::stream::StreamFuture;
501 use futures::task::Poll;
502 use std::pin::pin;
503 use test_case::test_case;
504 use wlan_common::channel::Bandwidth;
505 use wlan_common::sequestered::Sequestered;
506 use wlan_common::{RadioConfig, random_fidl_bss_description};
507
508 struct TestValues {
509 exec: fasync::TestExecutor,
510 iface_manager: IfaceManager,
511 receiver: mpsc::Receiver<IfaceManagerRequest>,
512 }
513
514 fn test_setup() -> TestValues {
515 let exec = fasync::TestExecutor::new();
516 let (sender, receiver) = mpsc::channel(1);
517 TestValues { exec, iface_manager: IfaceManager { sender }, receiver }
518 }
519
520 #[allow(clippy::enum_variant_names, reason = "mass allow for https://fxbug.dev/381896734")]
521 #[derive(Clone)]
522 enum NegativeTestFailureMode {
523 RequestFailure,
524 OperationFailure,
525 ServiceFailure,
526 }
527
528 fn handle_negative_test_result_responder<T: std::fmt::Debug>(
529 responder: oneshot::Sender<Result<T, Error>>,
530 failure_mode: NegativeTestFailureMode,
531 ) {
532 match failure_mode {
533 NegativeTestFailureMode::RequestFailure => {
534 panic!("Test bug: this request should have been handled previously")
535 }
536 NegativeTestFailureMode::OperationFailure => {
537 responder
538 .send(Err(format_err!("operation failed")))
539 .expect("failed to send response");
540 }
541 NegativeTestFailureMode::ServiceFailure => {
542 drop(responder);
544 }
545 }
546 }
547
548 fn handle_negative_test_responder<T: std::fmt::Debug>(
549 responder: oneshot::Sender<T>,
550 failure_mode: NegativeTestFailureMode,
551 ) {
552 match failure_mode {
553 NegativeTestFailureMode::RequestFailure | NegativeTestFailureMode::OperationFailure => {
554 panic!("Test bug: invalid operation")
555 }
556 NegativeTestFailureMode::ServiceFailure => {
557 drop(responder);
559 }
560 }
561 }
562
563 fn iface_manager_api_negative_test(
564 mut receiver: mpsc::Receiver<IfaceManagerRequest>,
565 failure_mode: NegativeTestFailureMode,
566 ) -> LocalBoxFuture<'static, ()> {
567 if let NegativeTestFailureMode::RequestFailure = failure_mode {
568 drop(receiver);
570 let fut = async move {};
571 return Box::pin(fut);
572 }
573
574 let fut = async move {
575 let req = match receiver.next().await {
576 Some(req) => req,
577 None => panic!("no request available."),
578 };
579
580 match req {
581 IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest {
583 responder,
584 ..
585 })
586 | IfaceManagerRequest::Disconnect(DisconnectRequest { responder, .. })
587 | IfaceManagerRequest::StopAp(StopApRequest { responder, .. })
588 | IfaceManagerRequest::StopAllAps(StopAllApsRequest { responder, .. })
589 | IfaceManagerRequest::SetCountry(SetCountryRequest { responder, .. })
590 | IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest {
591 responder,
592 })
593 | IfaceManagerRequest::Connect(ConnectRequest { responder, .. }) => {
594 handle_negative_test_result_responder(responder, failure_mode);
595 }
596 IfaceManagerRequest::GetScanProxy(ScanProxyRequest { responder }) => {
598 handle_negative_test_result_responder(responder, failure_mode);
599 }
600 IfaceManagerRequest::StartAp(StartApRequest { responder, .. }) => {
602 handle_negative_test_result_responder(responder, failure_mode);
603 }
604 IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest {
606 responder, ..
607 })
608 | IfaceManagerRequest::AddIface(AddIfaceRequest { responder, .. })
609 | IfaceManagerRequest::RemoveIface(RemoveIfaceRequest { responder, .. }) => {
610 handle_negative_test_responder(responder, failure_mode);
611 }
612 IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest { responder }) => {
614 handle_negative_test_responder(responder, failure_mode);
615 }
616 }
617 };
618 Box::pin(fut)
619 }
620
621 #[fuchsia::test]
622 fn test_disconnect_succeeds() {
623 let mut test_values = test_setup();
624
625 let req = ap_types::NetworkIdentifier {
627 ssid: Ssid::try_from("foo").unwrap(),
628 security_type: ap_types::SecurityType::None,
629 };
630 let req_reason = client_types::DisconnectReason::NetworkUnsaved;
631 let disconnect_fut = test_values.iface_manager.disconnect(req.clone(), req_reason);
632 let mut disconnect_fut = pin!(disconnect_fut);
633
634 assert_matches!(test_values.exec.run_until_stalled(&mut disconnect_fut), Poll::Pending);
635
636 let next_message = test_values.receiver.next();
638 let mut next_message = pin!(next_message);
639
640 assert_matches!(
641 test_values.exec.run_until_stalled(&mut next_message),
642 Poll::Ready(Some(IfaceManagerRequest::Disconnect(DisconnectRequest {
643 network_id, responder, reason
644 }))) => {
645 assert_eq!(network_id, req);
646 assert_eq!(reason, req_reason);
647 responder.send(Ok(())).expect("failed to send disconnect response");
648 }
649 );
650
651 assert_matches!(
653 test_values.exec.run_until_stalled(&mut disconnect_fut),
654 Poll::Ready(Ok(()))
655 );
656 }
657
658 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
659 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
660 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
661 #[fuchsia::test(add_test_attr = false)]
662 fn disconnect_negative_test(failure_mode: NegativeTestFailureMode) {
663 let mut test_values = test_setup();
664
665 let req = ap_types::NetworkIdentifier {
667 ssid: Ssid::try_from("foo").unwrap(),
668 security_type: ap_types::SecurityType::None,
669 };
670 let disconnect_fut = test_values
671 .iface_manager
672 .disconnect(req.clone(), client_types::DisconnectReason::NetworkUnsaved);
673 let mut disconnect_fut = pin!(disconnect_fut);
674
675 let service_fut =
676 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
677 let mut service_fut = pin!(service_fut);
678
679 match failure_mode {
680 NegativeTestFailureMode::RequestFailure => {}
681 _ => {
682 assert_matches!(
684 test_values.exec.run_until_stalled(&mut disconnect_fut),
685 Poll::Pending
686 );
687 assert_matches!(
688 test_values.exec.run_until_stalled(&mut service_fut),
689 Poll::Ready(())
690 );
691 }
692 }
693
694 assert_matches!(
696 test_values.exec.run_until_stalled(&mut disconnect_fut),
697 Poll::Ready(Err(_))
698 );
699 }
700
701 #[fuchsia::test]
702 fn test_connect_succeeds() {
703 let mut test_values = test_setup();
704
705 let req = ConnectAttemptRequest::new(
707 client_types::NetworkIdentifier {
708 ssid: Ssid::try_from("foo").unwrap(),
709 security_type: client_types::SecurityType::None,
710 },
711 Credential::None,
712 client_types::ConnectReason::FidlConnectRequest,
713 );
714 let connect_fut = test_values.iface_manager.connect(req.clone());
715 let mut connect_fut = pin!(connect_fut);
716
717 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Pending);
718
719 let next_message = test_values.receiver.next();
721 let mut next_message = pin!(next_message);
722
723 assert_matches!(
724 test_values.exec.run_until_stalled(&mut next_message),
725 Poll::Ready(Some(IfaceManagerRequest::Connect(ConnectRequest {
726 request, responder
727 }))) => {
728 assert_eq!(request, req);
729 responder.send(Ok(())).expect("failed to send connect response");
730 }
731 );
732
733 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Ok(_)));
735 }
736
737 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
738 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
739 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
740 #[fuchsia::test(add_test_attr = false)]
741 fn connect_negative_test(failure_mode: NegativeTestFailureMode) {
742 let mut test_values = test_setup();
743
744 let req = ConnectAttemptRequest::new(
746 client_types::NetworkIdentifier {
747 ssid: Ssid::try_from("foo").unwrap(),
748 security_type: client_types::SecurityType::None,
749 },
750 Credential::None,
751 client_types::ConnectReason::FidlConnectRequest,
752 );
753 let connect_fut = test_values.iface_manager.connect(req.clone());
754 let mut connect_fut = pin!(connect_fut);
755
756 let service_fut =
757 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
758 let mut service_fut = pin!(service_fut);
759
760 match failure_mode {
761 NegativeTestFailureMode::RequestFailure => {}
762 _ => {
763 assert_matches!(
765 test_values.exec.run_until_stalled(&mut connect_fut),
766 Poll::Pending
767 );
768 assert_matches!(
769 test_values.exec.run_until_stalled(&mut service_fut),
770 Poll::Ready(())
771 );
772 }
773 }
774
775 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
777 }
778
779 #[fuchsia::test]
780 fn test_record_idle_client_succeeds() {
781 let mut test_values = test_setup();
782
783 let iface_id = 123;
785 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
786 let mut idle_client_fut = pin!(idle_client_fut);
787
788 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
789
790 let next_message = test_values.receiver.next();
792 let mut next_message = pin!(next_message);
793
794 assert_matches!(
795 test_values.exec.run_until_stalled(&mut next_message),
796 Poll::Ready(
797 Some(IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest{ iface_id: 123, responder}))
798 ) => {
799 responder.send(()).expect("failed to send idle iface response");
800 }
801 );
802
803 assert_matches!(
805 test_values.exec.run_until_stalled(&mut idle_client_fut),
806 Poll::Ready(Ok(()))
807 );
808 }
809
810 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
811 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
812 #[fuchsia::test(add_test_attr = false)]
813 fn test_record_idle_client_service_failure(failure_mode: NegativeTestFailureMode) {
814 let mut test_values = test_setup();
815
816 let iface_id = 123;
818 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
819 let mut idle_client_fut = pin!(idle_client_fut);
820
821 let service_fut =
822 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
823 let mut service_fut = pin!(service_fut);
824
825 match failure_mode {
826 NegativeTestFailureMode::RequestFailure => {}
827 _ => {
828 assert_matches!(
830 test_values.exec.run_until_stalled(&mut idle_client_fut),
831 Poll::Pending
832 );
833 assert_matches!(
834 test_values.exec.run_until_stalled(&mut service_fut),
835 Poll::Ready(())
836 );
837 }
838 }
839
840 assert_matches!(
842 test_values.exec.run_until_stalled(&mut idle_client_fut),
843 Poll::Ready(Err(_))
844 );
845 }
846
847 #[fuchsia::test]
848 fn test_has_idle_client_success() {
849 let mut test_values = test_setup();
850
851 let idle_client_fut = test_values.iface_manager.has_idle_client();
853 let mut idle_client_fut = pin!(idle_client_fut);
854 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
855
856 let next_message = test_values.receiver.next();
858 let mut next_message = pin!(next_message);
859
860 assert_matches!(
861 test_values.exec.run_until_stalled(&mut next_message),
862 Poll::Ready(
863 Some(IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest{ responder}))
864 ) => responder.send(true).expect("failed to reply to idle client query")
865 );
866
867 assert_matches!(
869 test_values.exec.run_until_stalled(&mut idle_client_fut),
870 Poll::Ready(Ok(true))
871 );
872 }
873
874 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
875 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
876 #[fuchsia::test(add_test_attr = false)]
877 fn idle_client_negative_test(failure_mode: NegativeTestFailureMode) {
878 let mut test_values = test_setup();
879
880 let idle_client_fut = test_values.iface_manager.has_idle_client();
882 let mut idle_client_fut = pin!(idle_client_fut);
883 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
884
885 let service_fut =
886 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
887 let mut service_fut = pin!(service_fut);
888
889 match failure_mode {
890 NegativeTestFailureMode::RequestFailure => {}
891 _ => {
892 assert_matches!(
894 test_values.exec.run_until_stalled(&mut idle_client_fut),
895 Poll::Pending
896 );
897 assert_matches!(
898 test_values.exec.run_until_stalled(&mut service_fut),
899 Poll::Ready(())
900 );
901 }
902 }
903
904 assert_matches!(
906 test_values.exec.run_until_stalled(&mut idle_client_fut),
907 Poll::Ready(Err(_))
908 );
909 }
910
911 #[fuchsia::test]
912 fn test_add_iface_success() {
913 let mut test_values = test_setup();
914
915 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
917 let mut added_iface_fut = pin!(added_iface_fut);
918 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
919
920 let next_message = test_values.receiver.next();
922 let mut next_message = pin!(next_message);
923
924 assert_matches!(
925 test_values.exec.run_until_stalled(&mut next_message),
926 Poll::Ready(
927 Some(IfaceManagerRequest::AddIface(AddIfaceRequest{ iface_id: 123, responder }))
928 ) => {
929 responder.send(()).expect("failed to respond while adding iface");
930 }
931 );
932
933 assert_matches!(
935 test_values.exec.run_until_stalled(&mut added_iface_fut),
936 Poll::Ready(Ok(()))
937 );
938 }
939
940 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
941 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
942 #[fuchsia::test(add_test_attr = false)]
943 fn add_iface_negative_test(failure_mode: NegativeTestFailureMode) {
944 let mut test_values = test_setup();
945
946 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
948 let mut added_iface_fut = pin!(added_iface_fut);
949 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
950
951 let service_fut =
952 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
953 let mut service_fut = pin!(service_fut);
954
955 match failure_mode {
956 NegativeTestFailureMode::RequestFailure => {}
957 _ => {
958 assert_matches!(
960 test_values.exec.run_until_stalled(&mut added_iface_fut),
961 Poll::Pending
962 );
963 assert_matches!(
964 test_values.exec.run_until_stalled(&mut service_fut),
965 Poll::Ready(())
966 );
967 }
968 }
969
970 assert_matches!(
972 test_values.exec.run_until_stalled(&mut added_iface_fut),
973 Poll::Ready(Err(_))
974 );
975 }
976
977 #[fuchsia::test]
978 fn test_remove_iface_success() {
979 let mut test_values = test_setup();
980
981 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
983 let mut removed_iface_fut = pin!(removed_iface_fut);
984 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
985
986 let next_message = test_values.receiver.next();
988 let mut next_message = pin!(next_message);
989
990 assert_matches!(
991 test_values.exec.run_until_stalled(&mut next_message),
992 Poll::Ready(
993 Some(IfaceManagerRequest::RemoveIface(RemoveIfaceRequest{ iface_id: 123, responder }))
994 ) => {
995 responder.send(()).expect("failed to respond while adding iface");
996 }
997 );
998
999 assert_matches!(
1001 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1002 Poll::Ready(Ok(()))
1003 );
1004 }
1005
1006 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1007 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1008 #[fuchsia::test(add_test_attr = false)]
1009 fn remove_iface_negative_test(failure_mode: NegativeTestFailureMode) {
1010 let mut test_values = test_setup();
1011
1012 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
1014 let mut removed_iface_fut = pin!(removed_iface_fut);
1015 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
1016
1017 let service_fut =
1018 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1019 let mut service_fut = pin!(service_fut);
1020
1021 match failure_mode {
1022 NegativeTestFailureMode::RequestFailure => {}
1023 _ => {
1024 assert_matches!(
1026 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1027 Poll::Pending
1028 );
1029 assert_matches!(
1030 test_values.exec.run_until_stalled(&mut service_fut),
1031 Poll::Ready(())
1032 );
1033 }
1034 }
1035
1036 assert_matches!(
1038 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1039 Poll::Ready(Err(_))
1040 );
1041 }
1042
1043 #[fuchsia::test]
1044 fn test_get_scan_proxy_success() {
1045 let mut test_values = test_setup();
1046
1047 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1049 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1050 assert_matches!(test_values.exec.run_until_stalled(&mut scan_proxy_fut), Poll::Pending);
1051
1052 let next_message = test_values.receiver.next();
1054 let mut next_message = pin!(next_message);
1055
1056 assert_matches!(
1057 test_values.exec.run_until_stalled(&mut next_message),
1058 Poll::Ready(Some(IfaceManagerRequest::GetScanProxy(ScanProxyRequest{
1059 responder
1060 }))) => {
1061 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1062 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1063 responder.send(Ok(SmeForScan{proxy, iface_id: 0, defect_sender})).expect("failed to send scan sme proxy");
1064 }
1065 );
1066
1067 assert_matches!(
1069 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1070 Poll::Ready(Ok(_))
1071 );
1072 }
1073
1074 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1075 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1076 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1077 #[fuchsia::test(add_test_attr = false)]
1078 fn scan_proxy_negative_test(failure_mode: NegativeTestFailureMode) {
1079 let mut test_values = test_setup();
1080
1081 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1083 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1084
1085 let service_fut =
1086 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1087 let mut service_fut = pin!(service_fut);
1088
1089 match failure_mode {
1090 NegativeTestFailureMode::RequestFailure => {}
1091 _ => {
1092 assert_matches!(
1094 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1095 Poll::Pending
1096 );
1097 assert_matches!(
1098 test_values.exec.run_until_stalled(&mut service_fut),
1099 Poll::Ready(())
1100 );
1101 }
1102 }
1103
1104 assert_matches!(
1106 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1107 Poll::Ready(Err(_))
1108 );
1109 }
1110
1111 #[fuchsia::test]
1112 fn test_stop_client_connections_succeeds() {
1113 let mut test_values = test_setup();
1114
1115 let stop_fut = test_values.iface_manager.stop_client_connections(
1117 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1118 );
1119 let mut stop_fut = pin!(stop_fut);
1120 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1121
1122 let next_message = test_values.receiver.next();
1124 let mut next_message = pin!(next_message);
1125
1126 assert_matches!(
1127 test_values.exec.run_until_stalled(&mut next_message),
1128 Poll::Ready(Some(IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest{
1129 responder, reason
1130 }))) => {
1131 assert_eq!(reason, client_types::DisconnectReason::FidlStopClientConnectionsRequest);
1132 responder.send(Ok(())).expect("failed sending stop client connections response");
1133 }
1134 );
1135
1136 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(())));
1138 }
1139
1140 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1141 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1142 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1143 #[fuchsia::test(add_test_attr = false)]
1144 fn stop_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1145 let mut test_values = test_setup();
1146
1147 let stop_fut = test_values.iface_manager.stop_client_connections(
1149 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1150 );
1151 let mut stop_fut = pin!(stop_fut);
1152 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1153
1154 let service_fut =
1155 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1156 let mut service_fut = pin!(service_fut);
1157
1158 match failure_mode {
1159 NegativeTestFailureMode::RequestFailure => {}
1160 _ => {
1161 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1163 assert_matches!(
1164 test_values.exec.run_until_stalled(&mut service_fut),
1165 Poll::Ready(())
1166 );
1167 }
1168 }
1169
1170 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1172 }
1173
1174 #[fuchsia::test]
1175 fn test_start_client_connections_succeeds() {
1176 let mut test_values = test_setup();
1177
1178 let start_fut = test_values.iface_manager.start_client_connections();
1180 let mut start_fut = pin!(start_fut);
1181 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1182
1183 let next_message = test_values.receiver.next();
1185 let mut next_message = pin!(next_message);
1186
1187 assert_matches!(
1188 test_values.exec.run_until_stalled(&mut next_message),
1189 Poll::Ready(Some(IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest{
1190 responder
1191 }))) => {
1192 responder.send(Ok(())).expect("failed sending stop client connections response");
1193 }
1194 );
1195
1196 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(())));
1198 }
1199
1200 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1201 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1202 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1203 #[fuchsia::test(add_test_attr = false)]
1204 fn start_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1205 let mut test_values = test_setup();
1206
1207 let start_fut = test_values.iface_manager.start_client_connections();
1209 let mut start_fut = pin!(start_fut);
1210 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1211
1212 let service_fut =
1213 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1214 let mut service_fut = pin!(service_fut);
1215
1216 match failure_mode {
1217 NegativeTestFailureMode::RequestFailure => {}
1218 _ => {
1219 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1221 assert_matches!(
1222 test_values.exec.run_until_stalled(&mut service_fut),
1223 Poll::Ready(())
1224 );
1225 }
1226 }
1227
1228 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1230 }
1231
1232 fn create_ap_config() -> ap_fsm::ApConfig {
1233 ap_fsm::ApConfig {
1234 id: types::NetworkIdentifier {
1235 ssid: Ssid::try_from("foo").unwrap(),
1236 security_type: types::SecurityType::None,
1237 },
1238 credential: vec![],
1239 radio_config: RadioConfig::new(
1240 fidl_fuchsia_wlan_ieee80211::WlanPhyType::Ht,
1241 Bandwidth::Cbw20,
1242 6,
1243 fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz,
1244 ),
1245 mode: types::ConnectivityMode::Unrestricted,
1246 band: types::OperatingBand::Any,
1247 }
1248 }
1249
1250 #[fuchsia::test]
1251 fn test_start_ap_succeeds() {
1252 let mut test_values = test_setup();
1253
1254 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1256 let mut start_fut = pin!(start_fut);
1257 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1258
1259 let next_message = test_values.receiver.next();
1261 let mut next_message = pin!(next_message);
1262
1263 assert_matches!(
1264 test_values.exec.run_until_stalled(&mut next_message),
1265 Poll::Ready(Some(IfaceManagerRequest::StartAp(StartApRequest{
1266 config, responder
1267 }))) => {
1268 assert_eq!(config, create_ap_config());
1269
1270 let (_, receiver) = oneshot::channel();
1271 responder.send(Ok(receiver)).expect("failed to send start AP response");
1272 }
1273 );
1274
1275 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1277 }
1278
1279 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1280 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1281 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1282 #[fuchsia::test(add_test_attr = false)]
1283 fn start_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1284 let mut test_values = test_setup();
1285
1286 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1288 let mut start_fut = pin!(start_fut);
1289 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1290
1291 let service_fut =
1292 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1293 let mut service_fut = pin!(service_fut);
1294
1295 match failure_mode {
1296 NegativeTestFailureMode::RequestFailure => {}
1297 _ => {
1298 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1300 assert_matches!(
1301 test_values.exec.run_until_stalled(&mut service_fut),
1302 Poll::Ready(())
1303 );
1304 }
1305 }
1306
1307 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1309 }
1310
1311 #[fuchsia::test]
1312 fn test_stop_ap_succeeds() {
1313 let mut test_values = test_setup();
1314
1315 let stop_fut = test_values
1317 .iface_manager
1318 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1319 let mut stop_fut = pin!(stop_fut);
1320 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1321
1322 let next_message = test_values.receiver.next();
1324 let mut next_message = pin!(next_message);
1325
1326 assert_matches!(
1327 test_values.exec.run_until_stalled(&mut next_message),
1328 Poll::Ready(Some(IfaceManagerRequest::StopAp(StopApRequest{
1329 ssid, password, responder
1330 }))) => {
1331 assert_eq!(ssid, Ssid::try_from("foo").unwrap());
1332 assert_eq!(password, "bar".as_bytes().to_vec());
1333
1334 responder.send(Ok(())).expect("failed to send stop AP response");
1335 }
1336 );
1337
1338 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1340 }
1341
1342 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1343 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1344 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1345 #[fuchsia::test(add_test_attr = false)]
1346 fn stop_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1347 let mut test_values = test_setup();
1348
1349 let stop_fut = test_values
1351 .iface_manager
1352 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1353 let mut stop_fut = pin!(stop_fut);
1354 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1355
1356 let service_fut =
1357 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1358 let mut service_fut = pin!(service_fut);
1359
1360 match failure_mode {
1361 NegativeTestFailureMode::RequestFailure => {}
1362 _ => {
1363 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1365 assert_matches!(
1366 test_values.exec.run_until_stalled(&mut service_fut),
1367 Poll::Ready(())
1368 );
1369 }
1370 }
1371
1372 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1374 }
1375
1376 #[fuchsia::test]
1377 fn test_stop_all_aps_succeeds() {
1378 let mut test_values = test_setup();
1379
1380 let stop_fut = test_values.iface_manager.stop_all_aps();
1382 let mut stop_fut = pin!(stop_fut);
1383 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1384
1385 let next_message = test_values.receiver.next();
1387 let mut next_message = pin!(next_message);
1388 assert_matches!(
1389 test_values.exec.run_until_stalled(&mut next_message),
1390 Poll::Ready(Some(IfaceManagerRequest::StopAllAps(StopAllApsRequest{
1391 responder
1392 }))) => {
1393 responder.send(Ok(())).expect("failed to send stop AP response");
1394 }
1395 );
1396
1397 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1399 }
1400
1401 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1402 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1403 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1404 #[fuchsia::test(add_test_attr = false)]
1405 fn stop_all_aps_negative_test(failure_mode: NegativeTestFailureMode) {
1406 let mut test_values = test_setup();
1407
1408 let stop_fut = test_values.iface_manager.stop_all_aps();
1410 let mut stop_fut = pin!(stop_fut);
1411 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1412
1413 let service_fut =
1414 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1415 let mut service_fut = pin!(service_fut);
1416
1417 match failure_mode {
1418 NegativeTestFailureMode::RequestFailure => {}
1419 _ => {
1420 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1422 assert_matches!(
1423 test_values.exec.run_until_stalled(&mut service_fut),
1424 Poll::Ready(())
1425 );
1426 }
1427 }
1428
1429 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1431 }
1432
1433 #[fuchsia::test]
1434 fn test_set_country_succeeds() {
1435 let mut test_values = test_setup();
1436
1437 let set_country_fut = test_values.iface_manager.set_country(None);
1439 let mut set_country_fut = pin!(set_country_fut);
1440 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1441
1442 let next_message = test_values.receiver.next();
1444 let mut next_message = pin!(next_message);
1445
1446 assert_matches!(
1447 test_values.exec.run_until_stalled(&mut next_message),
1448 Poll::Ready(Some(IfaceManagerRequest::SetCountry(SetCountryRequest{
1449 country_code: None,
1450 responder
1451 }))) => {
1452 responder.send(Ok(())).expect("failed to send stop AP response");
1453 }
1454 );
1455
1456 assert_matches!(
1458 test_values.exec.run_until_stalled(&mut set_country_fut),
1459 Poll::Ready(Ok(_))
1460 );
1461 }
1462
1463 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1464 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1465 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1466 #[fuchsia::test(add_test_attr = false)]
1467 fn set_country_negative_test(failure_mode: NegativeTestFailureMode) {
1468 let mut test_values = test_setup();
1469
1470 let set_country_fut = test_values.iface_manager.set_country(None);
1472 let mut set_country_fut = pin!(set_country_fut);
1473 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1474 let service_fut =
1475 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1476 let mut service_fut = pin!(service_fut);
1477
1478 match failure_mode {
1479 NegativeTestFailureMode::RequestFailure => {}
1480 _ => {
1481 assert_matches!(
1483 test_values.exec.run_until_stalled(&mut set_country_fut),
1484 Poll::Pending
1485 );
1486 assert_matches!(
1487 test_values.exec.run_until_stalled(&mut service_fut),
1488 Poll::Ready(())
1489 );
1490 }
1491 }
1492
1493 assert_matches!(
1495 test_values.exec.run_until_stalled(&mut set_country_fut),
1496 Poll::Ready(Err(_))
1497 );
1498 }
1499
1500 #[fuchsia::test]
1501 fn test_sme_for_scan() {
1502 let mut exec = fasync::TestExecutor::new();
1503
1504 let (proxy, server_end) = create_proxy::<fidl_sme::ClientSmeMarker>();
1506 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1507 let sme = SmeForScan::new(proxy, 0, defect_sender);
1508 let mut sme_stream = server_end.into_stream();
1509
1510 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1512 ssids: vec![vec![]],
1513 channels: vec![],
1514 });
1515
1516 let scan_result_fut = sme.scan(&scan_request);
1518 let mut scan_result_fut = pin!(scan_result_fut);
1519 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1520
1521 assert_matches!(
1523 exec.run_until_stalled(&mut sme_stream.next()),
1524 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1525 req, ..
1526 }))) => {
1527 assert_eq!(scan_request, req)
1528 }
1529 );
1530 }
1531
1532 #[fuchsia::test]
1533 fn sme_for_scan_defects() {
1534 let _exec = fasync::TestExecutor::new();
1535
1536 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1538 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1539 let iface_id = rand::random::<u16>();
1540 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1541
1542 sme.log_aborted_scan_defect();
1543 sme.log_failed_scan_defect();
1544 sme.log_empty_scan_defect();
1545
1546 assert_eq!(
1547 defect_receiver.try_recv().ok(),
1548 Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id })),
1549 );
1550 assert_eq!(
1551 defect_receiver.try_recv().ok(),
1552 Some(Defect::Iface(IfaceFailure::FailedScan { iface_id })),
1553 );
1554 assert_eq!(
1555 defect_receiver.try_recv().ok(),
1556 Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id })),
1557 );
1558 }
1559
1560 #[fuchsia::test]
1561 fn sme_for_scan_timeout() {
1562 let mut exec = fasync::TestExecutor::new_with_fake_time();
1563 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1564
1565 let (proxy, _server) = create_proxy::<fidl_sme::ClientSmeMarker>();
1567 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1568 let iface_id = rand::random::<u16>();
1569 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1570
1571 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1573 ssids: vec![vec![]],
1574 channels: vec![],
1575 });
1576 let scan_result_fut = sme.scan(&scan_request);
1577 let mut scan_result_fut = pin!(scan_result_fut);
1578 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1579
1580 exec.set_fake_time(fasync::MonotonicInstant::after(
1582 SCAN_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1583 ));
1584
1585 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Ready(Err(_)));
1587 assert_eq!(
1588 defect_receiver.try_recv().ok(),
1589 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Scan })),
1590 );
1591 }
1592
1593 #[fuchsia::test]
1594 fn state_machine_sme_disconnects_successfully() {
1595 let mut exec = fasync::TestExecutor::new();
1596
1597 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1599 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1600 let iface_id = rand::random::<u16>();
1601 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1602
1603 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1605 let mut fut = pin!(fut);
1606 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1607
1608 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1610 assert_matches!(
1611 poll_sme_req(&mut exec, &mut sme_fut),
1612 Poll::Ready(fidl_sme::ClientSmeRequest::Disconnect{
1613 responder,
1614 reason: fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest
1615 }) => {
1616 responder.send().expect("could not send sme response");
1617 }
1618 );
1619
1620 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1622 }
1623
1624 #[fuchsia::test]
1625 fn state_machine_sme_fails_to_disconnect() {
1626 let mut exec = fasync::TestExecutor::new();
1627
1628 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1630 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1631 let iface_id = rand::random::<u16>();
1632 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1633
1634 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1636 let mut fut = pin!(fut);
1637 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1638 }
1639
1640 #[fuchsia::test]
1641 fn state_machine_sme_disconnect_timeout() {
1642 let mut exec = fasync::TestExecutor::new_with_fake_time();
1643 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1644
1645 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1647 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1648 let iface_id = rand::random::<u16>();
1649 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1650
1651 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1653 let mut fut = pin!(fut);
1654 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1655
1656 exec.set_fake_time(fasync::MonotonicInstant::after(
1658 DISCONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1659 ));
1660
1661 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1663 assert_eq!(
1664 defect_receiver.try_recv().ok(),
1665 Some(Defect::Iface(IfaceFailure::Timeout {
1666 iface_id,
1667 source: TimeoutSource::Disconnect,
1668 })),
1669 );
1670 }
1671
1672 #[fuchsia::test]
1673 fn state_machine_sme_roam_sends_request() {
1674 let mut exec = fasync::TestExecutor::new();
1675
1676 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1678 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1679 let iface_id = rand::random::<u16>();
1680 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1681
1682 let roam_request =
1684 fidl_sme::RoamRequest { bss_description: random_fidl_bss_description!() };
1685 sme.roam(&roam_request).unwrap();
1686
1687 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1689 assert_matches!(
1690 poll_sme_req(&mut exec, &mut sme_fut),
1691 Poll::Ready(fidl_sme::ClientSmeRequest::Roam {
1692 req, ..
1693 }) => {
1694 assert_eq!(req, roam_request);
1695 }
1696 );
1697 }
1698
1699 fn generate_connect_request() -> fidl_sme::ConnectRequest {
1700 let connection_selection = generate_connect_selection();
1701 fidl_sme::ConnectRequest {
1702 ssid: connection_selection.target.network.ssid.to_vec(),
1703 bss_description: Sequestered::release(connection_selection.target.bss.bss_description),
1704 multiple_bss_candidates: connection_selection.target.network_has_multiple_bss,
1705 authentication: connection_selection.target.authenticator.clone().into(),
1706 deprecated_scan_type: fidl_fuchsia_wlan_common::ScanType::Active,
1707 }
1708 }
1709
1710 #[fuchsia::test]
1711 fn state_machine_sme_connects_successfully() {
1712 let mut exec = fasync::TestExecutor::new();
1713
1714 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1716 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1717 let iface_id = rand::random::<u16>();
1718 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1719
1720 let connect_request = generate_connect_request();
1722 let fut = sme.connect(&connect_request);
1723 let mut fut = pin!(fut);
1724 match exec.run_until_stalled(&mut fut) {
1725 Poll::Pending => {}
1726 _ => panic!("connect request should be pending."),
1727 }
1728
1729 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1731 assert_matches!(
1732 poll_sme_req(&mut exec, &mut sme_fut),
1733 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1734 txn,
1735 ..
1736 }) => {
1737 let (_stream, ctrl) = txn.expect("connect txn unused")
1738 .into_stream_and_control_handle();
1739 ctrl
1740 .send_on_connect_result(&fidl_sme::ConnectResult {
1741 code: fidl_ieee80211::StatusCode::Success,
1742 is_credential_rejected: false,
1743 is_reconnect: false,
1744 })
1745 .expect("failed to send connection completion");
1746 }
1747 );
1748
1749 match exec.run_until_stalled(&mut fut) {
1751 Poll::Ready(Ok((result, txn))) => {
1752 assert_eq!(
1753 result,
1754 fidl_sme::ConnectResult {
1755 code: fidl_ieee80211::StatusCode::Success,
1756 is_credential_rejected: false,
1757 is_reconnect: false,
1758 }
1759 );
1760 drop(txn)
1763 }
1764 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1765 Poll::Pending => panic!("connect request should not be pending."),
1766 }
1767 }
1768
1769 #[fuchsia::test]
1770 fn state_machine_sme_connection_failure() {
1771 let mut exec = fasync::TestExecutor::new();
1772
1773 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1775 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1776 let iface_id = rand::random::<u16>();
1777 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1778
1779 let connect_request = generate_connect_request();
1781 let fut = sme.connect(&connect_request);
1782 let mut fut = pin!(fut);
1783 match exec.run_until_stalled(&mut fut) {
1784 Poll::Pending => {}
1785 _ => panic!("connect request should be pending."),
1786 }
1787
1788 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1790 assert_matches!(
1791 poll_sme_req(&mut exec, &mut sme_fut),
1792 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1793 txn,
1794 ..
1795 }) => {
1796 let (_stream, ctrl) = txn.expect("connect txn unused")
1797 .into_stream_and_control_handle();
1798 ctrl
1799 .send_on_connect_result(&fidl_sme::ConnectResult {
1800 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1801 is_credential_rejected: false,
1802 is_reconnect: false,
1803 })
1804 .expect("failed to send connection completion");
1805 }
1806 );
1807
1808 match exec.run_until_stalled(&mut fut) {
1810 Poll::Ready(Ok((result, txn))) => {
1811 assert_eq!(
1812 result,
1813 fidl_sme::ConnectResult {
1814 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1815 is_credential_rejected: false,
1816 is_reconnect: false,
1817 }
1818 );
1819 drop(txn)
1822 }
1823 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1824 Poll::Pending => panic!("connect request should not be pending."),
1825 }
1826 }
1827
1828 #[fuchsia::test]
1829 fn state_machine_sme_connect_request_fails() {
1830 let mut exec = fasync::TestExecutor::new();
1831
1832 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1834 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1835 let iface_id = rand::random::<u16>();
1836 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1837
1838 let connect_request = generate_connect_request();
1840 let fut = sme.connect(&connect_request);
1841 let mut fut = pin!(fut);
1842 match exec.run_until_stalled(&mut fut) {
1843 Poll::Ready(Err(_)) => {}
1844 _ => panic!("connect request should have failed."),
1845 }
1846 }
1847
1848 #[fuchsia::test]
1849 fn state_machine_sme_connect_timeout() {
1850 let mut exec = fasync::TestExecutor::new_with_fake_time();
1851 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1852
1853 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1855 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1856 let iface_id = rand::random::<u16>();
1857 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1858
1859 let connect_request = generate_connect_request();
1861 let fut = sme.connect(&connect_request);
1862 let mut fut = pin!(fut);
1863 match exec.run_until_stalled(&mut fut) {
1864 Poll::Pending => {}
1865 _ => panic!("connect future completed unexpectedly"),
1866 }
1867
1868 exec.set_fake_time(fasync::MonotonicInstant::after(
1870 CONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1871 ));
1872
1873 match exec.run_until_stalled(&mut fut) {
1875 Poll::Ready(Err(_)) => {}
1876 Poll::Ready(Ok(_)) => panic!("connect future completed successfully"),
1877 Poll::Pending => panic!("connect future did not complete"),
1878 }
1879 assert_eq!(
1880 defect_receiver.try_recv().ok(),
1881 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Connect })),
1882 );
1883 }
1884
1885 #[fuchsia::test]
1886 fn wait_for_connect_result_error() {
1887 let mut exec = fasync::TestExecutor::new();
1888 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1889 let mut response_stream = connect_txn.take_event_stream();
1890
1891 let fut = wait_for_connect_result(&mut response_stream);
1892
1893 let mut fut = pin!(fut);
1894 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1895
1896 drop(remote);
1898 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1899 }
1900
1901 #[fuchsia::test]
1902 fn wait_for_connect_result_ignores_other_events() {
1903 let mut exec = fasync::TestExecutor::new();
1904 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1905 let request_handle = remote.into_stream().control_handle();
1906 let mut response_stream = connect_txn.take_event_stream();
1907
1908 let fut = wait_for_connect_result(&mut response_stream);
1909
1910 let mut fut = pin!(fut);
1911 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1912
1913 let ind =
1915 fidl_internal::SignalReportIndication { rssi_dbm: -20, snr_db: 25, tx_rate_500kbps: 0 };
1916 request_handle.send_on_signal_report(&ind).unwrap();
1917
1918 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1920
1921 let sme_result = fidl_sme::ConnectResult {
1923 code: fidl_ieee80211::StatusCode::Success,
1924 is_credential_rejected: false,
1925 is_reconnect: false,
1926 };
1927 request_handle.send_on_connect_result(&sme_result).unwrap();
1928 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(response)) => {
1929 assert_eq!(sme_result, response);
1930 });
1931 }
1932
1933 fn poll_ap_sme_req(
1934 exec: &mut fasync::TestExecutor,
1935 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
1936 ) -> Poll<fidl_sme::ApSmeRequest> {
1937 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
1938 *next_sme_req = stream.into_future();
1939 req.expect("did not expect the SME request stream to end")
1940 .expect("error polling SME request stream")
1941 })
1942 }
1943
1944 #[fuchsia::test]
1945 fn state_machine_sme_starts_ap_successfully() {
1946 let mut exec = fasync::TestExecutor::new();
1947
1948 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
1950 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1951 let iface_id = rand::random::<u16>();
1952 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1953
1954 let config = fidl_sme::ApConfig::from(create_ap_config());
1956 let fut = sme.start(&config);
1957 let mut fut = pin!(fut);
1958 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1959
1960 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1962 assert_matches!(
1963 poll_ap_sme_req(&mut exec, &mut sme_fut),
1964 Poll::Ready(fidl_sme::ApSmeRequest::Start { responder, .. }) => {
1965 responder.send(fidl_sme::StartApResultCode::Success)
1966 .expect("could not send sme response");
1967 }
1968 );
1969
1970 assert_matches!(
1972 exec.run_until_stalled(&mut fut),
1973 Poll::Ready(Ok(fidl_sme::StartApResultCode::Success))
1974 );
1975 }
1976
1977 #[fuchsia::test]
1978 fn state_machine_sme_fails_to_request_start_ap() {
1979 let mut exec = fasync::TestExecutor::new();
1980
1981 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
1983 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1984 let iface_id = rand::random::<u16>();
1985 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1986
1987 let config = fidl_sme::ApConfig::from(create_ap_config());
1989 let fut = sme.start(&config);
1990 let mut fut = pin!(fut);
1991 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1992 }
1993
1994 #[fuchsia::test]
1995 fn state_machine_sme_start_ap_timeout() {
1996 let mut exec = fasync::TestExecutor::new_with_fake_time();
1997 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1998
1999 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2001 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2002 let iface_id = rand::random::<u16>();
2003 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2004
2005 let config = fidl_sme::ApConfig::from(create_ap_config());
2007 let fut = sme.start(&config);
2008 let mut fut = pin!(fut);
2009 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2010
2011 exec.set_fake_time(fasync::MonotonicInstant::after(
2013 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2014 ));
2015
2016 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2018 assert_eq!(
2019 defect_receiver.try_recv().ok(),
2020 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::ApStart })),
2021 );
2022 }
2023
2024 #[fuchsia::test]
2025 fn state_machine_sme_stops_ap_successfully() {
2026 let mut exec = fasync::TestExecutor::new();
2027
2028 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2030 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2031 let iface_id = rand::random::<u16>();
2032 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2033
2034 let fut = sme.stop();
2036 let mut fut = pin!(fut);
2037 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2038
2039 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2041 assert_matches!(
2042 poll_ap_sme_req(&mut exec, &mut sme_fut),
2043 Poll::Ready(fidl_sme::ApSmeRequest::Stop { responder }) => {
2044 responder.send(fidl_sme::StopApResultCode::Success)
2045 .expect("could not send sme response");
2046 }
2047 );
2048
2049 assert_matches!(
2051 exec.run_until_stalled(&mut fut),
2052 Poll::Ready(Ok(fidl_sme::StopApResultCode::Success))
2053 );
2054 }
2055
2056 #[fuchsia::test]
2057 fn state_machine_sme_fails_to_request_stop_ap() {
2058 let mut exec = fasync::TestExecutor::new();
2059
2060 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2062 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2063 let iface_id = rand::random::<u16>();
2064 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2065
2066 let fut = sme.stop();
2068 let mut fut = pin!(fut);
2069 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2070 }
2071
2072 #[fuchsia::test]
2073 fn state_machine_sme_stop_ap_timeout() {
2074 let mut exec = fasync::TestExecutor::new_with_fake_time();
2075 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2076
2077 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2079 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2080 let iface_id = rand::random::<u16>();
2081 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2082
2083 let fut = sme.stop();
2085 let mut fut = pin!(fut);
2086 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2087
2088 exec.set_fake_time(fasync::MonotonicInstant::after(
2090 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2091 ));
2092
2093 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2095 assert_eq!(
2096 defect_receiver.try_recv().ok(),
2097 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::ApStop })),
2098 );
2099 }
2100
2101 #[fuchsia::test]
2102 fn state_machine_sme_successfully_queries_ap_status() {
2103 let mut exec = fasync::TestExecutor::new();
2104
2105 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2107 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2108 let iface_id = rand::random::<u16>();
2109 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2110
2111 let fut = sme.status();
2113 let mut fut = pin!(fut);
2114 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2115
2116 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2118 assert_matches!(
2119 poll_ap_sme_req(&mut exec, &mut sme_fut),
2120 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
2121 let response = fidl_sme::ApStatusResponse { running_ap: None };
2122 responder.send(&response).expect("could not send AP status response");
2123 }
2124 );
2125
2126 assert_matches!(
2128 exec.run_until_stalled(&mut fut),
2129 Poll::Ready(Ok(fidl_sme::ApStatusResponse { running_ap: None }))
2130 );
2131 }
2132
2133 #[fuchsia::test]
2134 fn state_machine_sme_fails_to_query_ap_status() {
2135 let mut exec = fasync::TestExecutor::new();
2136
2137 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2139 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2140 let iface_id = rand::random::<u16>();
2141 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2142
2143 let fut = sme.status();
2145 let mut fut = pin!(fut);
2146 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2147 }
2148
2149 #[fuchsia::test]
2150 fn state_machine_sme_query_ap_status_timeout() {
2151 let mut exec = fasync::TestExecutor::new_with_fake_time();
2152 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2153
2154 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2156 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2157 let iface_id = rand::random::<u16>();
2158 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2159
2160 let fut = sme.status();
2162 let mut fut = pin!(fut);
2163 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2164
2165 exec.set_fake_time(fasync::MonotonicInstant::after(
2167 AP_STATUS_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2168 ));
2169
2170 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2172 assert_eq!(
2173 defect_receiver.try_recv().ok(),
2174 Some(Defect::Iface(IfaceFailure::Timeout {
2175 iface_id,
2176 source: TimeoutSource::ApStatus,
2177 })),
2178 );
2179 }
2180}