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 rand::Rng;
503 use std::pin::pin;
504 use test_case::test_case;
505 use wlan_common::channel::Bandwidth;
506 use wlan_common::sequestered::Sequestered;
507 use wlan_common::{RadioConfig, random_fidl_bss_description};
508
509 struct TestValues {
510 exec: fasync::TestExecutor,
511 iface_manager: IfaceManager,
512 receiver: mpsc::Receiver<IfaceManagerRequest>,
513 }
514
515 fn test_setup() -> TestValues {
516 let exec = fasync::TestExecutor::new();
517 let (sender, receiver) = mpsc::channel(1);
518 TestValues { exec, iface_manager: IfaceManager { sender }, receiver }
519 }
520
521 #[allow(clippy::enum_variant_names, reason = "mass allow for https://fxbug.dev/381896734")]
522 #[derive(Clone)]
523 enum NegativeTestFailureMode {
524 RequestFailure,
525 OperationFailure,
526 ServiceFailure,
527 }
528
529 fn handle_negative_test_result_responder<T: std::fmt::Debug>(
530 responder: oneshot::Sender<Result<T, Error>>,
531 failure_mode: NegativeTestFailureMode,
532 ) {
533 match failure_mode {
534 NegativeTestFailureMode::RequestFailure => {
535 panic!("Test bug: this request should have been handled previously")
536 }
537 NegativeTestFailureMode::OperationFailure => {
538 responder
539 .send(Err(format_err!("operation failed")))
540 .expect("failed to send response");
541 }
542 NegativeTestFailureMode::ServiceFailure => {
543 drop(responder);
545 }
546 }
547 }
548
549 fn handle_negative_test_responder<T: std::fmt::Debug>(
550 responder: oneshot::Sender<T>,
551 failure_mode: NegativeTestFailureMode,
552 ) {
553 match failure_mode {
554 NegativeTestFailureMode::RequestFailure | NegativeTestFailureMode::OperationFailure => {
555 panic!("Test bug: invalid operation")
556 }
557 NegativeTestFailureMode::ServiceFailure => {
558 drop(responder);
560 }
561 }
562 }
563
564 fn iface_manager_api_negative_test(
565 mut receiver: mpsc::Receiver<IfaceManagerRequest>,
566 failure_mode: NegativeTestFailureMode,
567 ) -> LocalBoxFuture<'static, ()> {
568 if let NegativeTestFailureMode::RequestFailure = failure_mode {
569 drop(receiver);
571 let fut = async move {};
572 return Box::pin(fut);
573 }
574
575 let fut = async move {
576 let req = match receiver.next().await {
577 Some(req) => req,
578 None => panic!("no request available."),
579 };
580
581 match req {
582 IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest {
584 responder,
585 ..
586 })
587 | IfaceManagerRequest::Disconnect(DisconnectRequest { responder, .. })
588 | IfaceManagerRequest::StopAp(StopApRequest { responder, .. })
589 | IfaceManagerRequest::StopAllAps(StopAllApsRequest { responder, .. })
590 | IfaceManagerRequest::SetCountry(SetCountryRequest { responder, .. })
591 | IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest {
592 responder,
593 })
594 | IfaceManagerRequest::Connect(ConnectRequest { responder, .. }) => {
595 handle_negative_test_result_responder(responder, failure_mode);
596 }
597 IfaceManagerRequest::GetScanProxy(ScanProxyRequest { responder }) => {
599 handle_negative_test_result_responder(responder, failure_mode);
600 }
601 IfaceManagerRequest::StartAp(StartApRequest { responder, .. }) => {
603 handle_negative_test_result_responder(responder, failure_mode);
604 }
605 IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest {
607 responder, ..
608 })
609 | IfaceManagerRequest::AddIface(AddIfaceRequest { responder, .. })
610 | IfaceManagerRequest::RemoveIface(RemoveIfaceRequest { responder, .. }) => {
611 handle_negative_test_responder(responder, failure_mode);
612 }
613 IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest { responder }) => {
615 handle_negative_test_responder(responder, failure_mode);
616 }
617 }
618 };
619 Box::pin(fut)
620 }
621
622 #[fuchsia::test]
623 fn test_disconnect_succeeds() {
624 let mut test_values = test_setup();
625
626 let req = ap_types::NetworkIdentifier {
628 ssid: Ssid::try_from("foo").unwrap(),
629 security_type: ap_types::SecurityType::None,
630 };
631 let req_reason = client_types::DisconnectReason::NetworkUnsaved;
632 let disconnect_fut = test_values.iface_manager.disconnect(req.clone(), req_reason);
633 let mut disconnect_fut = pin!(disconnect_fut);
634
635 assert_matches!(test_values.exec.run_until_stalled(&mut disconnect_fut), Poll::Pending);
636
637 let next_message = test_values.receiver.next();
639 let mut next_message = pin!(next_message);
640
641 assert_matches!(
642 test_values.exec.run_until_stalled(&mut next_message),
643 Poll::Ready(Some(IfaceManagerRequest::Disconnect(DisconnectRequest {
644 network_id, responder, reason
645 }))) => {
646 assert_eq!(network_id, req);
647 assert_eq!(reason, req_reason);
648 responder.send(Ok(())).expect("failed to send disconnect response");
649 }
650 );
651
652 assert_matches!(
654 test_values.exec.run_until_stalled(&mut disconnect_fut),
655 Poll::Ready(Ok(()))
656 );
657 }
658
659 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
660 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
661 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
662 #[fuchsia::test(add_test_attr = false)]
663 fn disconnect_negative_test(failure_mode: NegativeTestFailureMode) {
664 let mut test_values = test_setup();
665
666 let req = ap_types::NetworkIdentifier {
668 ssid: Ssid::try_from("foo").unwrap(),
669 security_type: ap_types::SecurityType::None,
670 };
671 let disconnect_fut = test_values
672 .iface_manager
673 .disconnect(req.clone(), client_types::DisconnectReason::NetworkUnsaved);
674 let mut disconnect_fut = pin!(disconnect_fut);
675
676 let service_fut =
677 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
678 let mut service_fut = pin!(service_fut);
679
680 match failure_mode {
681 NegativeTestFailureMode::RequestFailure => {}
682 _ => {
683 assert_matches!(
685 test_values.exec.run_until_stalled(&mut disconnect_fut),
686 Poll::Pending
687 );
688 assert_matches!(
689 test_values.exec.run_until_stalled(&mut service_fut),
690 Poll::Ready(())
691 );
692 }
693 }
694
695 assert_matches!(
697 test_values.exec.run_until_stalled(&mut disconnect_fut),
698 Poll::Ready(Err(_))
699 );
700 }
701
702 #[fuchsia::test]
703 fn test_connect_succeeds() {
704 let mut test_values = test_setup();
705
706 let req = ConnectAttemptRequest::new(
708 client_types::NetworkIdentifier {
709 ssid: Ssid::try_from("foo").unwrap(),
710 security_type: client_types::SecurityType::None,
711 },
712 Credential::None,
713 client_types::ConnectReason::FidlConnectRequest,
714 );
715 let connect_fut = test_values.iface_manager.connect(req.clone());
716 let mut connect_fut = pin!(connect_fut);
717
718 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Pending);
719
720 let next_message = test_values.receiver.next();
722 let mut next_message = pin!(next_message);
723
724 assert_matches!(
725 test_values.exec.run_until_stalled(&mut next_message),
726 Poll::Ready(Some(IfaceManagerRequest::Connect(ConnectRequest {
727 request, responder
728 }))) => {
729 assert_eq!(request, req);
730 responder.send(Ok(())).expect("failed to send connect response");
731 }
732 );
733
734 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Ok(_)));
736 }
737
738 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
739 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
740 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
741 #[fuchsia::test(add_test_attr = false)]
742 fn connect_negative_test(failure_mode: NegativeTestFailureMode) {
743 let mut test_values = test_setup();
744
745 let req = ConnectAttemptRequest::new(
747 client_types::NetworkIdentifier {
748 ssid: Ssid::try_from("foo").unwrap(),
749 security_type: client_types::SecurityType::None,
750 },
751 Credential::None,
752 client_types::ConnectReason::FidlConnectRequest,
753 );
754 let connect_fut = test_values.iface_manager.connect(req.clone());
755 let mut connect_fut = pin!(connect_fut);
756
757 let service_fut =
758 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
759 let mut service_fut = pin!(service_fut);
760
761 match failure_mode {
762 NegativeTestFailureMode::RequestFailure => {}
763 _ => {
764 assert_matches!(
766 test_values.exec.run_until_stalled(&mut connect_fut),
767 Poll::Pending
768 );
769 assert_matches!(
770 test_values.exec.run_until_stalled(&mut service_fut),
771 Poll::Ready(())
772 );
773 }
774 }
775
776 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
778 }
779
780 #[fuchsia::test]
781 fn test_record_idle_client_succeeds() {
782 let mut test_values = test_setup();
783
784 let iface_id = 123;
786 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
787 let mut idle_client_fut = pin!(idle_client_fut);
788
789 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
790
791 let next_message = test_values.receiver.next();
793 let mut next_message = pin!(next_message);
794
795 assert_matches!(
796 test_values.exec.run_until_stalled(&mut next_message),
797 Poll::Ready(
798 Some(IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest{ iface_id: 123, responder}))
799 ) => {
800 responder.send(()).expect("failed to send idle iface response");
801 }
802 );
803
804 assert_matches!(
806 test_values.exec.run_until_stalled(&mut idle_client_fut),
807 Poll::Ready(Ok(()))
808 );
809 }
810
811 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
812 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
813 #[fuchsia::test(add_test_attr = false)]
814 fn test_record_idle_client_service_failure(failure_mode: NegativeTestFailureMode) {
815 let mut test_values = test_setup();
816
817 let iface_id = 123;
819 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
820 let mut idle_client_fut = pin!(idle_client_fut);
821
822 let service_fut =
823 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
824 let mut service_fut = pin!(service_fut);
825
826 match failure_mode {
827 NegativeTestFailureMode::RequestFailure => {}
828 _ => {
829 assert_matches!(
831 test_values.exec.run_until_stalled(&mut idle_client_fut),
832 Poll::Pending
833 );
834 assert_matches!(
835 test_values.exec.run_until_stalled(&mut service_fut),
836 Poll::Ready(())
837 );
838 }
839 }
840
841 assert_matches!(
843 test_values.exec.run_until_stalled(&mut idle_client_fut),
844 Poll::Ready(Err(_))
845 );
846 }
847
848 #[fuchsia::test]
849 fn test_has_idle_client_success() {
850 let mut test_values = test_setup();
851
852 let idle_client_fut = test_values.iface_manager.has_idle_client();
854 let mut idle_client_fut = pin!(idle_client_fut);
855 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
856
857 let next_message = test_values.receiver.next();
859 let mut next_message = pin!(next_message);
860
861 assert_matches!(
862 test_values.exec.run_until_stalled(&mut next_message),
863 Poll::Ready(
864 Some(IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest{ responder}))
865 ) => responder.send(true).expect("failed to reply to idle client query")
866 );
867
868 assert_matches!(
870 test_values.exec.run_until_stalled(&mut idle_client_fut),
871 Poll::Ready(Ok(true))
872 );
873 }
874
875 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
876 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
877 #[fuchsia::test(add_test_attr = false)]
878 fn idle_client_negative_test(failure_mode: NegativeTestFailureMode) {
879 let mut test_values = test_setup();
880
881 let idle_client_fut = test_values.iface_manager.has_idle_client();
883 let mut idle_client_fut = pin!(idle_client_fut);
884 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
885
886 let service_fut =
887 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
888 let mut service_fut = pin!(service_fut);
889
890 match failure_mode {
891 NegativeTestFailureMode::RequestFailure => {}
892 _ => {
893 assert_matches!(
895 test_values.exec.run_until_stalled(&mut idle_client_fut),
896 Poll::Pending
897 );
898 assert_matches!(
899 test_values.exec.run_until_stalled(&mut service_fut),
900 Poll::Ready(())
901 );
902 }
903 }
904
905 assert_matches!(
907 test_values.exec.run_until_stalled(&mut idle_client_fut),
908 Poll::Ready(Err(_))
909 );
910 }
911
912 #[fuchsia::test]
913 fn test_add_iface_success() {
914 let mut test_values = test_setup();
915
916 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
918 let mut added_iface_fut = pin!(added_iface_fut);
919 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
920
921 let next_message = test_values.receiver.next();
923 let mut next_message = pin!(next_message);
924
925 assert_matches!(
926 test_values.exec.run_until_stalled(&mut next_message),
927 Poll::Ready(
928 Some(IfaceManagerRequest::AddIface(AddIfaceRequest{ iface_id: 123, responder }))
929 ) => {
930 responder.send(()).expect("failed to respond while adding iface");
931 }
932 );
933
934 assert_matches!(
936 test_values.exec.run_until_stalled(&mut added_iface_fut),
937 Poll::Ready(Ok(()))
938 );
939 }
940
941 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
942 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
943 #[fuchsia::test(add_test_attr = false)]
944 fn add_iface_negative_test(failure_mode: NegativeTestFailureMode) {
945 let mut test_values = test_setup();
946
947 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
949 let mut added_iface_fut = pin!(added_iface_fut);
950 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
951
952 let service_fut =
953 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
954 let mut service_fut = pin!(service_fut);
955
956 match failure_mode {
957 NegativeTestFailureMode::RequestFailure => {}
958 _ => {
959 assert_matches!(
961 test_values.exec.run_until_stalled(&mut added_iface_fut),
962 Poll::Pending
963 );
964 assert_matches!(
965 test_values.exec.run_until_stalled(&mut service_fut),
966 Poll::Ready(())
967 );
968 }
969 }
970
971 assert_matches!(
973 test_values.exec.run_until_stalled(&mut added_iface_fut),
974 Poll::Ready(Err(_))
975 );
976 }
977
978 #[fuchsia::test]
979 fn test_remove_iface_success() {
980 let mut test_values = test_setup();
981
982 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
984 let mut removed_iface_fut = pin!(removed_iface_fut);
985 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
986
987 let next_message = test_values.receiver.next();
989 let mut next_message = pin!(next_message);
990
991 assert_matches!(
992 test_values.exec.run_until_stalled(&mut next_message),
993 Poll::Ready(
994 Some(IfaceManagerRequest::RemoveIface(RemoveIfaceRequest{ iface_id: 123, responder }))
995 ) => {
996 responder.send(()).expect("failed to respond while adding iface");
997 }
998 );
999
1000 assert_matches!(
1002 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1003 Poll::Ready(Ok(()))
1004 );
1005 }
1006
1007 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1008 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1009 #[fuchsia::test(add_test_attr = false)]
1010 fn remove_iface_negative_test(failure_mode: NegativeTestFailureMode) {
1011 let mut test_values = test_setup();
1012
1013 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
1015 let mut removed_iface_fut = pin!(removed_iface_fut);
1016 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
1017
1018 let service_fut =
1019 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1020 let mut service_fut = pin!(service_fut);
1021
1022 match failure_mode {
1023 NegativeTestFailureMode::RequestFailure => {}
1024 _ => {
1025 assert_matches!(
1027 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1028 Poll::Pending
1029 );
1030 assert_matches!(
1031 test_values.exec.run_until_stalled(&mut service_fut),
1032 Poll::Ready(())
1033 );
1034 }
1035 }
1036
1037 assert_matches!(
1039 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1040 Poll::Ready(Err(_))
1041 );
1042 }
1043
1044 #[fuchsia::test]
1045 fn test_get_scan_proxy_success() {
1046 let mut test_values = test_setup();
1047
1048 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1050 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1051 assert_matches!(test_values.exec.run_until_stalled(&mut scan_proxy_fut), Poll::Pending);
1052
1053 let next_message = test_values.receiver.next();
1055 let mut next_message = pin!(next_message);
1056
1057 assert_matches!(
1058 test_values.exec.run_until_stalled(&mut next_message),
1059 Poll::Ready(Some(IfaceManagerRequest::GetScanProxy(ScanProxyRequest{
1060 responder
1061 }))) => {
1062 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1063 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1064 responder.send(Ok(SmeForScan{proxy, iface_id: 0, defect_sender})).expect("failed to send scan sme proxy");
1065 }
1066 );
1067
1068 assert_matches!(
1070 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1071 Poll::Ready(Ok(_))
1072 );
1073 }
1074
1075 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1076 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1077 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1078 #[fuchsia::test(add_test_attr = false)]
1079 fn scan_proxy_negative_test(failure_mode: NegativeTestFailureMode) {
1080 let mut test_values = test_setup();
1081
1082 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1084 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1085
1086 let service_fut =
1087 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1088 let mut service_fut = pin!(service_fut);
1089
1090 match failure_mode {
1091 NegativeTestFailureMode::RequestFailure => {}
1092 _ => {
1093 assert_matches!(
1095 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1096 Poll::Pending
1097 );
1098 assert_matches!(
1099 test_values.exec.run_until_stalled(&mut service_fut),
1100 Poll::Ready(())
1101 );
1102 }
1103 }
1104
1105 assert_matches!(
1107 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1108 Poll::Ready(Err(_))
1109 );
1110 }
1111
1112 #[fuchsia::test]
1113 fn test_stop_client_connections_succeeds() {
1114 let mut test_values = test_setup();
1115
1116 let stop_fut = test_values.iface_manager.stop_client_connections(
1118 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1119 );
1120 let mut stop_fut = pin!(stop_fut);
1121 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1122
1123 let next_message = test_values.receiver.next();
1125 let mut next_message = pin!(next_message);
1126
1127 assert_matches!(
1128 test_values.exec.run_until_stalled(&mut next_message),
1129 Poll::Ready(Some(IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest{
1130 responder, reason
1131 }))) => {
1132 assert_eq!(reason, client_types::DisconnectReason::FidlStopClientConnectionsRequest);
1133 responder.send(Ok(())).expect("failed sending stop client connections response");
1134 }
1135 );
1136
1137 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(())));
1139 }
1140
1141 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1142 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1143 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1144 #[fuchsia::test(add_test_attr = false)]
1145 fn stop_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1146 let mut test_values = test_setup();
1147
1148 let stop_fut = test_values.iface_manager.stop_client_connections(
1150 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1151 );
1152 let mut stop_fut = pin!(stop_fut);
1153 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1154
1155 let service_fut =
1156 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1157 let mut service_fut = pin!(service_fut);
1158
1159 match failure_mode {
1160 NegativeTestFailureMode::RequestFailure => {}
1161 _ => {
1162 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1164 assert_matches!(
1165 test_values.exec.run_until_stalled(&mut service_fut),
1166 Poll::Ready(())
1167 );
1168 }
1169 }
1170
1171 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1173 }
1174
1175 #[fuchsia::test]
1176 fn test_start_client_connections_succeeds() {
1177 let mut test_values = test_setup();
1178
1179 let start_fut = test_values.iface_manager.start_client_connections();
1181 let mut start_fut = pin!(start_fut);
1182 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1183
1184 let next_message = test_values.receiver.next();
1186 let mut next_message = pin!(next_message);
1187
1188 assert_matches!(
1189 test_values.exec.run_until_stalled(&mut next_message),
1190 Poll::Ready(Some(IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest{
1191 responder
1192 }))) => {
1193 responder.send(Ok(())).expect("failed sending stop client connections response");
1194 }
1195 );
1196
1197 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(())));
1199 }
1200
1201 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1202 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1203 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1204 #[fuchsia::test(add_test_attr = false)]
1205 fn start_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1206 let mut test_values = test_setup();
1207
1208 let start_fut = test_values.iface_manager.start_client_connections();
1210 let mut start_fut = pin!(start_fut);
1211 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1212
1213 let service_fut =
1214 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1215 let mut service_fut = pin!(service_fut);
1216
1217 match failure_mode {
1218 NegativeTestFailureMode::RequestFailure => {}
1219 _ => {
1220 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1222 assert_matches!(
1223 test_values.exec.run_until_stalled(&mut service_fut),
1224 Poll::Ready(())
1225 );
1226 }
1227 }
1228
1229 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1231 }
1232
1233 fn create_ap_config() -> ap_fsm::ApConfig {
1234 ap_fsm::ApConfig {
1235 id: types::NetworkIdentifier {
1236 ssid: Ssid::try_from("foo").unwrap(),
1237 security_type: types::SecurityType::None,
1238 },
1239 credential: vec![],
1240 radio_config: RadioConfig::new(
1241 fidl_fuchsia_wlan_ieee80211::WlanPhyType::Ht,
1242 Bandwidth::Cbw20,
1243 6,
1244 fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz,
1245 ),
1246 mode: types::ConnectivityMode::Unrestricted,
1247 band: types::OperatingBand::Any,
1248 }
1249 }
1250
1251 #[fuchsia::test]
1252 fn test_start_ap_succeeds() {
1253 let mut test_values = test_setup();
1254
1255 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1257 let mut start_fut = pin!(start_fut);
1258 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1259
1260 let next_message = test_values.receiver.next();
1262 let mut next_message = pin!(next_message);
1263
1264 assert_matches!(
1265 test_values.exec.run_until_stalled(&mut next_message),
1266 Poll::Ready(Some(IfaceManagerRequest::StartAp(StartApRequest{
1267 config, responder
1268 }))) => {
1269 assert_eq!(config, create_ap_config());
1270
1271 let (_, receiver) = oneshot::channel();
1272 responder.send(Ok(receiver)).expect("failed to send start AP response");
1273 }
1274 );
1275
1276 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1278 }
1279
1280 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1281 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1282 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1283 #[fuchsia::test(add_test_attr = false)]
1284 fn start_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1285 let mut test_values = test_setup();
1286
1287 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1289 let mut start_fut = pin!(start_fut);
1290 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1291
1292 let service_fut =
1293 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1294 let mut service_fut = pin!(service_fut);
1295
1296 match failure_mode {
1297 NegativeTestFailureMode::RequestFailure => {}
1298 _ => {
1299 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1301 assert_matches!(
1302 test_values.exec.run_until_stalled(&mut service_fut),
1303 Poll::Ready(())
1304 );
1305 }
1306 }
1307
1308 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1310 }
1311
1312 #[fuchsia::test]
1313 fn test_stop_ap_succeeds() {
1314 let mut test_values = test_setup();
1315
1316 let stop_fut = test_values
1318 .iface_manager
1319 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1320 let mut stop_fut = pin!(stop_fut);
1321 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1322
1323 let next_message = test_values.receiver.next();
1325 let mut next_message = pin!(next_message);
1326
1327 assert_matches!(
1328 test_values.exec.run_until_stalled(&mut next_message),
1329 Poll::Ready(Some(IfaceManagerRequest::StopAp(StopApRequest{
1330 ssid, password, responder
1331 }))) => {
1332 assert_eq!(ssid, Ssid::try_from("foo").unwrap());
1333 assert_eq!(password, "bar".as_bytes().to_vec());
1334
1335 responder.send(Ok(())).expect("failed to send stop AP response");
1336 }
1337 );
1338
1339 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1341 }
1342
1343 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1344 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1345 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1346 #[fuchsia::test(add_test_attr = false)]
1347 fn stop_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1348 let mut test_values = test_setup();
1349
1350 let stop_fut = test_values
1352 .iface_manager
1353 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1354 let mut stop_fut = pin!(stop_fut);
1355 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1356
1357 let service_fut =
1358 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1359 let mut service_fut = pin!(service_fut);
1360
1361 match failure_mode {
1362 NegativeTestFailureMode::RequestFailure => {}
1363 _ => {
1364 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1366 assert_matches!(
1367 test_values.exec.run_until_stalled(&mut service_fut),
1368 Poll::Ready(())
1369 );
1370 }
1371 }
1372
1373 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1375 }
1376
1377 #[fuchsia::test]
1378 fn test_stop_all_aps_succeeds() {
1379 let mut test_values = test_setup();
1380
1381 let stop_fut = test_values.iface_manager.stop_all_aps();
1383 let mut stop_fut = pin!(stop_fut);
1384 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1385
1386 let next_message = test_values.receiver.next();
1388 let mut next_message = pin!(next_message);
1389 assert_matches!(
1390 test_values.exec.run_until_stalled(&mut next_message),
1391 Poll::Ready(Some(IfaceManagerRequest::StopAllAps(StopAllApsRequest{
1392 responder
1393 }))) => {
1394 responder.send(Ok(())).expect("failed to send stop AP response");
1395 }
1396 );
1397
1398 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1400 }
1401
1402 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1403 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1404 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1405 #[fuchsia::test(add_test_attr = false)]
1406 fn stop_all_aps_negative_test(failure_mode: NegativeTestFailureMode) {
1407 let mut test_values = test_setup();
1408
1409 let stop_fut = test_values.iface_manager.stop_all_aps();
1411 let mut stop_fut = pin!(stop_fut);
1412 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1413
1414 let service_fut =
1415 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1416 let mut service_fut = pin!(service_fut);
1417
1418 match failure_mode {
1419 NegativeTestFailureMode::RequestFailure => {}
1420 _ => {
1421 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1423 assert_matches!(
1424 test_values.exec.run_until_stalled(&mut service_fut),
1425 Poll::Ready(())
1426 );
1427 }
1428 }
1429
1430 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1432 }
1433
1434 #[fuchsia::test]
1435 fn test_set_country_succeeds() {
1436 let mut test_values = test_setup();
1437
1438 let set_country_fut = test_values.iface_manager.set_country(None);
1440 let mut set_country_fut = pin!(set_country_fut);
1441 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1442
1443 let next_message = test_values.receiver.next();
1445 let mut next_message = pin!(next_message);
1446
1447 assert_matches!(
1448 test_values.exec.run_until_stalled(&mut next_message),
1449 Poll::Ready(Some(IfaceManagerRequest::SetCountry(SetCountryRequest{
1450 country_code: None,
1451 responder
1452 }))) => {
1453 responder.send(Ok(())).expect("failed to send stop AP response");
1454 }
1455 );
1456
1457 assert_matches!(
1459 test_values.exec.run_until_stalled(&mut set_country_fut),
1460 Poll::Ready(Ok(_))
1461 );
1462 }
1463
1464 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1465 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1466 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1467 #[fuchsia::test(add_test_attr = false)]
1468 fn set_country_negative_test(failure_mode: NegativeTestFailureMode) {
1469 let mut test_values = test_setup();
1470
1471 let set_country_fut = test_values.iface_manager.set_country(None);
1473 let mut set_country_fut = pin!(set_country_fut);
1474 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1475 let service_fut =
1476 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1477 let mut service_fut = pin!(service_fut);
1478
1479 match failure_mode {
1480 NegativeTestFailureMode::RequestFailure => {}
1481 _ => {
1482 assert_matches!(
1484 test_values.exec.run_until_stalled(&mut set_country_fut),
1485 Poll::Pending
1486 );
1487 assert_matches!(
1488 test_values.exec.run_until_stalled(&mut service_fut),
1489 Poll::Ready(())
1490 );
1491 }
1492 }
1493
1494 assert_matches!(
1496 test_values.exec.run_until_stalled(&mut set_country_fut),
1497 Poll::Ready(Err(_))
1498 );
1499 }
1500
1501 #[fuchsia::test]
1502 fn test_sme_for_scan() {
1503 let mut exec = fasync::TestExecutor::new();
1504
1505 let (proxy, server_end) = create_proxy::<fidl_sme::ClientSmeMarker>();
1507 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1508 let sme = SmeForScan::new(proxy, 0, defect_sender);
1509 let mut sme_stream = server_end.into_stream();
1510
1511 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1513 ssids: vec![vec![]],
1514 channels: vec![],
1515 });
1516
1517 let scan_result_fut = sme.scan(&scan_request);
1519 let mut scan_result_fut = pin!(scan_result_fut);
1520 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1521
1522 assert_matches!(
1524 exec.run_until_stalled(&mut sme_stream.next()),
1525 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1526 req, ..
1527 }))) => {
1528 assert_eq!(scan_request, req)
1529 }
1530 );
1531 }
1532
1533 #[fuchsia::test]
1534 fn sme_for_scan_defects() {
1535 let _exec = fasync::TestExecutor::new();
1536
1537 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1539 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1540 let iface_id = rand::random::<u16>();
1541 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1542
1543 sme.log_aborted_scan_defect();
1544 sme.log_failed_scan_defect();
1545 sme.log_empty_scan_defect();
1546
1547 assert_eq!(
1548 defect_receiver.try_next().expect("missing canceled scan error"),
1549 Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id })),
1550 );
1551 assert_eq!(
1552 defect_receiver.try_next().expect("missing failed scan error"),
1553 Some(Defect::Iface(IfaceFailure::FailedScan { iface_id })),
1554 );
1555 assert_eq!(
1556 defect_receiver.try_next().expect("missing empty scan results error"),
1557 Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id })),
1558 );
1559 }
1560
1561 #[fuchsia::test]
1562 fn sme_for_scan_timeout() {
1563 let mut exec = fasync::TestExecutor::new_with_fake_time();
1564 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1565
1566 let (proxy, _server) = create_proxy::<fidl_sme::ClientSmeMarker>();
1568 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1569 let iface_id = rand::random::<u16>();
1570 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1571
1572 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1574 ssids: vec![vec![]],
1575 channels: vec![],
1576 });
1577 let scan_result_fut = sme.scan(&scan_request);
1578 let mut scan_result_fut = pin!(scan_result_fut);
1579 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1580
1581 exec.set_fake_time(fasync::MonotonicInstant::after(
1583 SCAN_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1584 ));
1585
1586 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Ready(Err(_)));
1588 assert_eq!(
1589 defect_receiver.try_next().expect("missing empty scan results error"),
1590 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Scan })),
1591 );
1592 }
1593
1594 #[fuchsia::test]
1595 fn state_machine_sme_disconnects_successfully() {
1596 let mut exec = fasync::TestExecutor::new();
1597
1598 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1600 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1601 let iface_id = rand::random::<u16>();
1602 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1603
1604 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1606 let mut fut = pin!(fut);
1607 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1608
1609 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1611 assert_matches!(
1612 poll_sme_req(&mut exec, &mut sme_fut),
1613 Poll::Ready(fidl_sme::ClientSmeRequest::Disconnect{
1614 responder,
1615 reason: fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest
1616 }) => {
1617 responder.send().expect("could not send sme response");
1618 }
1619 );
1620
1621 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1623 }
1624
1625 #[fuchsia::test]
1626 fn state_machine_sme_fails_to_disconnect() {
1627 let mut exec = fasync::TestExecutor::new();
1628
1629 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1631 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1632 let iface_id = rand::random::<u16>();
1633 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1634
1635 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1637 let mut fut = pin!(fut);
1638 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1639 }
1640
1641 #[fuchsia::test]
1642 fn state_machine_sme_disconnect_timeout() {
1643 let mut exec = fasync::TestExecutor::new_with_fake_time();
1644 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1645
1646 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1648 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1649 let iface_id = rand::random::<u16>();
1650 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1651
1652 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1654 let mut fut = pin!(fut);
1655 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1656
1657 exec.set_fake_time(fasync::MonotonicInstant::after(
1659 DISCONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1660 ));
1661
1662 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1664 assert_eq!(
1665 defect_receiver.try_next().expect("missing empty scan results error"),
1666 Some(Defect::Iface(IfaceFailure::Timeout {
1667 iface_id,
1668 source: TimeoutSource::Disconnect,
1669 })),
1670 );
1671 }
1672
1673 #[fuchsia::test]
1674 fn state_machine_sme_roam_sends_request() {
1675 let mut exec = fasync::TestExecutor::new();
1676
1677 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1679 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1680 let iface_id = rand::random::<u16>();
1681 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1682
1683 let roam_request =
1685 fidl_sme::RoamRequest { bss_description: random_fidl_bss_description!() };
1686 sme.roam(&roam_request).unwrap();
1687
1688 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1690 assert_matches!(
1691 poll_sme_req(&mut exec, &mut sme_fut),
1692 Poll::Ready(fidl_sme::ClientSmeRequest::Roam {
1693 req, ..
1694 }) => {
1695 assert_eq!(req, roam_request);
1696 }
1697 );
1698 }
1699
1700 fn generate_connect_request() -> fidl_sme::ConnectRequest {
1701 let connection_selection = generate_connect_selection();
1702 fidl_sme::ConnectRequest {
1703 ssid: connection_selection.target.network.ssid.to_vec(),
1704 bss_description: Sequestered::release(connection_selection.target.bss.bss_description),
1705 multiple_bss_candidates: connection_selection.target.network_has_multiple_bss,
1706 authentication: connection_selection.target.authenticator.clone().into(),
1707 deprecated_scan_type: fidl_fuchsia_wlan_common::ScanType::Active,
1708 }
1709 }
1710
1711 #[fuchsia::test]
1712 fn state_machine_sme_connects_successfully() {
1713 let mut exec = fasync::TestExecutor::new();
1714
1715 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1717 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1718 let iface_id = rand::random::<u16>();
1719 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1720
1721 let connect_request = generate_connect_request();
1723 let fut = sme.connect(&connect_request);
1724 let mut fut = pin!(fut);
1725 match exec.run_until_stalled(&mut fut) {
1726 Poll::Pending => {}
1727 _ => panic!("connect request should be pending."),
1728 }
1729
1730 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1732 assert_matches!(
1733 poll_sme_req(&mut exec, &mut sme_fut),
1734 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1735 txn,
1736 ..
1737 }) => {
1738 let (_stream, ctrl) = txn.expect("connect txn unused")
1739 .into_stream_and_control_handle();
1740 ctrl
1741 .send_on_connect_result(&fidl_sme::ConnectResult {
1742 code: fidl_ieee80211::StatusCode::Success,
1743 is_credential_rejected: false,
1744 is_reconnect: false,
1745 })
1746 .expect("failed to send connection completion");
1747 }
1748 );
1749
1750 match exec.run_until_stalled(&mut fut) {
1752 Poll::Ready(Ok((result, txn))) => {
1753 assert_eq!(
1754 result,
1755 fidl_sme::ConnectResult {
1756 code: fidl_ieee80211::StatusCode::Success,
1757 is_credential_rejected: false,
1758 is_reconnect: false,
1759 }
1760 );
1761 drop(txn)
1764 }
1765 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1766 Poll::Pending => panic!("connect request should not be pending."),
1767 }
1768 }
1769
1770 #[fuchsia::test]
1771 fn state_machine_sme_connection_failure() {
1772 let mut exec = fasync::TestExecutor::new();
1773
1774 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1776 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1777 let iface_id = rand::random::<u16>();
1778 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1779
1780 let connect_request = generate_connect_request();
1782 let fut = sme.connect(&connect_request);
1783 let mut fut = pin!(fut);
1784 match exec.run_until_stalled(&mut fut) {
1785 Poll::Pending => {}
1786 _ => panic!("connect request should be pending."),
1787 }
1788
1789 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1791 assert_matches!(
1792 poll_sme_req(&mut exec, &mut sme_fut),
1793 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1794 txn,
1795 ..
1796 }) => {
1797 let (_stream, ctrl) = txn.expect("connect txn unused")
1798 .into_stream_and_control_handle();
1799 ctrl
1800 .send_on_connect_result(&fidl_sme::ConnectResult {
1801 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1802 is_credential_rejected: false,
1803 is_reconnect: false,
1804 })
1805 .expect("failed to send connection completion");
1806 }
1807 );
1808
1809 match exec.run_until_stalled(&mut fut) {
1811 Poll::Ready(Ok((result, txn))) => {
1812 assert_eq!(
1813 result,
1814 fidl_sme::ConnectResult {
1815 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1816 is_credential_rejected: false,
1817 is_reconnect: false,
1818 }
1819 );
1820 drop(txn)
1823 }
1824 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1825 Poll::Pending => panic!("connect request should not be pending."),
1826 }
1827 }
1828
1829 #[fuchsia::test]
1830 fn state_machine_sme_connect_request_fails() {
1831 let mut exec = fasync::TestExecutor::new();
1832
1833 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1835 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1836 let iface_id = rand::random::<u16>();
1837 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1838
1839 let connect_request = generate_connect_request();
1841 let fut = sme.connect(&connect_request);
1842 let mut fut = pin!(fut);
1843 match exec.run_until_stalled(&mut fut) {
1844 Poll::Ready(Err(_)) => {}
1845 _ => panic!("connect request should have failed."),
1846 }
1847 }
1848
1849 #[fuchsia::test]
1850 fn state_machine_sme_connect_timeout() {
1851 let mut exec = fasync::TestExecutor::new_with_fake_time();
1852 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1853
1854 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1856 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1857 let iface_id = rand::random::<u16>();
1858 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1859
1860 let connect_request = generate_connect_request();
1862 let fut = sme.connect(&connect_request);
1863 let mut fut = pin!(fut);
1864 match exec.run_until_stalled(&mut fut) {
1865 Poll::Pending => {}
1866 _ => panic!("connect future completed unexpectedly"),
1867 }
1868
1869 exec.set_fake_time(fasync::MonotonicInstant::after(
1871 CONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1872 ));
1873
1874 match exec.run_until_stalled(&mut fut) {
1876 Poll::Ready(Err(_)) => {}
1877 Poll::Ready(Ok(_)) => panic!("connect future completed successfully"),
1878 Poll::Pending => panic!("connect future did not complete"),
1879 }
1880 assert_eq!(
1881 defect_receiver.try_next().expect("missing connection timeout"),
1882 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Connect })),
1883 );
1884 }
1885
1886 #[fuchsia::test]
1887 fn wait_for_connect_result_error() {
1888 let mut exec = fasync::TestExecutor::new();
1889 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1890 let mut response_stream = connect_txn.take_event_stream();
1891
1892 let fut = wait_for_connect_result(&mut response_stream);
1893
1894 let mut fut = pin!(fut);
1895 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1896
1897 drop(remote);
1899 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1900 }
1901
1902 #[fuchsia::test]
1903 fn wait_for_connect_result_ignores_other_events() {
1904 let mut exec = fasync::TestExecutor::new();
1905 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1906 let request_handle = remote.into_stream().control_handle();
1907 let mut response_stream = connect_txn.take_event_stream();
1908
1909 let fut = wait_for_connect_result(&mut response_stream);
1910
1911 let mut fut = pin!(fut);
1912 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1913
1914 let ind = fidl_internal::SignalReportIndication { rssi_dbm: -20, snr_db: 25 };
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_next().expect("missing connection timeout"),
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_next().expect("missing connection timeout"),
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_next().expect("missing connection timeout"),
2174 Some(Defect::Iface(IfaceFailure::Timeout {
2175 iface_id,
2176 source: TimeoutSource::ApStatus,
2177 })),
2178 );
2179 }
2180}