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 crate::telemetry;
11use anyhow::{Error, bail, format_err};
12use async_trait::async_trait;
13use fidl::endpoints::create_proxy;
14use fidl_fuchsia_wlan_sme as fidl_sme;
15use fuchsia_async::TimeoutExt;
16use futures::channel::{mpsc, oneshot};
17use futures::{TryFutureExt, TryStreamExt};
18use log::{info, warn};
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: telemetry::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: telemetry::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: telemetry::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: telemetry::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: telemetry::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: telemetry::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::Cbw;
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 Cbw::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 {
1591 iface_id,
1592 source: telemetry::TimeoutSource::Scan,
1593 })),
1594 );
1595 }
1596
1597 #[fuchsia::test]
1598 fn state_machine_sme_disconnects_successfully() {
1599 let mut exec = fasync::TestExecutor::new();
1600
1601 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1603 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1604 let iface_id = rand::random::<u16>();
1605 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1606
1607 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1609 let mut fut = pin!(fut);
1610 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1611
1612 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1614 assert_matches!(
1615 poll_sme_req(&mut exec, &mut sme_fut),
1616 Poll::Ready(fidl_sme::ClientSmeRequest::Disconnect{
1617 responder,
1618 reason: fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest
1619 }) => {
1620 responder.send().expect("could not send sme response");
1621 }
1622 );
1623
1624 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1626 }
1627
1628 #[fuchsia::test]
1629 fn state_machine_sme_fails_to_disconnect() {
1630 let mut exec = fasync::TestExecutor::new();
1631
1632 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1634 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1635 let iface_id = rand::random::<u16>();
1636 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1637
1638 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1640 let mut fut = pin!(fut);
1641 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1642 }
1643
1644 #[fuchsia::test]
1645 fn state_machine_sme_disconnect_timeout() {
1646 let mut exec = fasync::TestExecutor::new_with_fake_time();
1647 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1648
1649 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1651 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1652 let iface_id = rand::random::<u16>();
1653 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1654
1655 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1657 let mut fut = pin!(fut);
1658 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1659
1660 exec.set_fake_time(fasync::MonotonicInstant::after(
1662 DISCONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1663 ));
1664
1665 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1667 assert_eq!(
1668 defect_receiver.try_next().expect("missing empty scan results error"),
1669 Some(Defect::Iface(IfaceFailure::Timeout {
1670 iface_id,
1671 source: telemetry::TimeoutSource::Disconnect,
1672 })),
1673 );
1674 }
1675
1676 #[fuchsia::test]
1677 fn state_machine_sme_roam_sends_request() {
1678 let mut exec = fasync::TestExecutor::new();
1679
1680 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1682 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1683 let iface_id = rand::random::<u16>();
1684 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1685
1686 let roam_request =
1688 fidl_sme::RoamRequest { bss_description: random_fidl_bss_description!() };
1689 sme.roam(&roam_request).unwrap();
1690
1691 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1693 assert_matches!(
1694 poll_sme_req(&mut exec, &mut sme_fut),
1695 Poll::Ready(fidl_sme::ClientSmeRequest::Roam {
1696 req, ..
1697 }) => {
1698 assert_eq!(req, roam_request);
1699 }
1700 );
1701 }
1702
1703 fn generate_connect_request() -> fidl_sme::ConnectRequest {
1704 let connection_selection = generate_connect_selection();
1705 fidl_sme::ConnectRequest {
1706 ssid: connection_selection.target.network.ssid.to_vec(),
1707 bss_description: Sequestered::release(connection_selection.target.bss.bss_description),
1708 multiple_bss_candidates: connection_selection.target.network_has_multiple_bss,
1709 authentication: connection_selection.target.authenticator.clone().into(),
1710 deprecated_scan_type: fidl_fuchsia_wlan_common::ScanType::Active,
1711 }
1712 }
1713
1714 #[fuchsia::test]
1715 fn state_machine_sme_connects_successfully() {
1716 let mut exec = fasync::TestExecutor::new();
1717
1718 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1720 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1721 let iface_id = rand::random::<u16>();
1722 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1723
1724 let connect_request = generate_connect_request();
1726 let fut = sme.connect(&connect_request);
1727 let mut fut = pin!(fut);
1728 match exec.run_until_stalled(&mut fut) {
1729 Poll::Pending => {}
1730 _ => panic!("connect request should be pending."),
1731 }
1732
1733 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1735 assert_matches!(
1736 poll_sme_req(&mut exec, &mut sme_fut),
1737 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1738 txn,
1739 ..
1740 }) => {
1741 let (_stream, ctrl) = txn.expect("connect txn unused")
1742 .into_stream_and_control_handle();
1743 ctrl
1744 .send_on_connect_result(&fidl_sme::ConnectResult {
1745 code: fidl_ieee80211::StatusCode::Success,
1746 is_credential_rejected: false,
1747 is_reconnect: false,
1748 })
1749 .expect("failed to send connection completion");
1750 }
1751 );
1752
1753 match exec.run_until_stalled(&mut fut) {
1755 Poll::Ready(Ok((result, txn))) => {
1756 assert_eq!(
1757 result,
1758 fidl_sme::ConnectResult {
1759 code: fidl_ieee80211::StatusCode::Success,
1760 is_credential_rejected: false,
1761 is_reconnect: false,
1762 }
1763 );
1764 drop(txn)
1767 }
1768 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1769 Poll::Pending => panic!("connect request should not be pending."),
1770 }
1771 }
1772
1773 #[fuchsia::test]
1774 fn state_machine_sme_connection_failure() {
1775 let mut exec = fasync::TestExecutor::new();
1776
1777 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1779 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1780 let iface_id = rand::random::<u16>();
1781 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1782
1783 let connect_request = generate_connect_request();
1785 let fut = sme.connect(&connect_request);
1786 let mut fut = pin!(fut);
1787 match exec.run_until_stalled(&mut fut) {
1788 Poll::Pending => {}
1789 _ => panic!("connect request should be pending."),
1790 }
1791
1792 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1794 assert_matches!(
1795 poll_sme_req(&mut exec, &mut sme_fut),
1796 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1797 txn,
1798 ..
1799 }) => {
1800 let (_stream, ctrl) = txn.expect("connect txn unused")
1801 .into_stream_and_control_handle();
1802 ctrl
1803 .send_on_connect_result(&fidl_sme::ConnectResult {
1804 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1805 is_credential_rejected: false,
1806 is_reconnect: false,
1807 })
1808 .expect("failed to send connection completion");
1809 }
1810 );
1811
1812 match exec.run_until_stalled(&mut fut) {
1814 Poll::Ready(Ok((result, txn))) => {
1815 assert_eq!(
1816 result,
1817 fidl_sme::ConnectResult {
1818 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1819 is_credential_rejected: false,
1820 is_reconnect: false,
1821 }
1822 );
1823 drop(txn)
1826 }
1827 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1828 Poll::Pending => panic!("connect request should not be pending."),
1829 }
1830 }
1831
1832 #[fuchsia::test]
1833 fn state_machine_sme_connect_request_fails() {
1834 let mut exec = fasync::TestExecutor::new();
1835
1836 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1838 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1839 let iface_id = rand::random::<u16>();
1840 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1841
1842 let connect_request = generate_connect_request();
1844 let fut = sme.connect(&connect_request);
1845 let mut fut = pin!(fut);
1846 match exec.run_until_stalled(&mut fut) {
1847 Poll::Ready(Err(_)) => {}
1848 _ => panic!("connect request should have failed."),
1849 }
1850 }
1851
1852 #[fuchsia::test]
1853 fn state_machine_sme_connect_timeout() {
1854 let mut exec = fasync::TestExecutor::new_with_fake_time();
1855 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1856
1857 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1859 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1860 let iface_id = rand::random::<u16>();
1861 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1862
1863 let connect_request = generate_connect_request();
1865 let fut = sme.connect(&connect_request);
1866 let mut fut = pin!(fut);
1867 match exec.run_until_stalled(&mut fut) {
1868 Poll::Pending => {}
1869 _ => panic!("connect future completed unexpectedly"),
1870 }
1871
1872 exec.set_fake_time(fasync::MonotonicInstant::after(
1874 CONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1875 ));
1876
1877 match exec.run_until_stalled(&mut fut) {
1879 Poll::Ready(Err(_)) => {}
1880 Poll::Ready(Ok(_)) => panic!("connect future completed successfully"),
1881 Poll::Pending => panic!("connect future did not complete"),
1882 }
1883 assert_eq!(
1884 defect_receiver.try_next().expect("missing connection timeout"),
1885 Some(Defect::Iface(IfaceFailure::Timeout {
1886 iface_id,
1887 source: telemetry::TimeoutSource::Connect,
1888 })),
1889 );
1890 }
1891
1892 #[fuchsia::test]
1893 fn wait_for_connect_result_error() {
1894 let mut exec = fasync::TestExecutor::new();
1895 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1896 let mut response_stream = connect_txn.take_event_stream();
1897
1898 let fut = wait_for_connect_result(&mut response_stream);
1899
1900 let mut fut = pin!(fut);
1901 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1902
1903 drop(remote);
1905 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1906 }
1907
1908 #[fuchsia::test]
1909 fn wait_for_connect_result_ignores_other_events() {
1910 let mut exec = fasync::TestExecutor::new();
1911 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1912 let request_handle = remote.into_stream().control_handle();
1913 let mut response_stream = connect_txn.take_event_stream();
1914
1915 let fut = wait_for_connect_result(&mut response_stream);
1916
1917 let mut fut = pin!(fut);
1918 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1919
1920 let ind = fidl_internal::SignalReportIndication { rssi_dbm: -20, snr_db: 25 };
1922 request_handle.send_on_signal_report(&ind).unwrap();
1923
1924 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1926
1927 let sme_result = fidl_sme::ConnectResult {
1929 code: fidl_ieee80211::StatusCode::Success,
1930 is_credential_rejected: false,
1931 is_reconnect: false,
1932 };
1933 request_handle.send_on_connect_result(&sme_result).unwrap();
1934 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(response)) => {
1935 assert_eq!(sme_result, response);
1936 });
1937 }
1938
1939 fn poll_ap_sme_req(
1940 exec: &mut fasync::TestExecutor,
1941 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
1942 ) -> Poll<fidl_sme::ApSmeRequest> {
1943 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
1944 *next_sme_req = stream.into_future();
1945 req.expect("did not expect the SME request stream to end")
1946 .expect("error polling SME request stream")
1947 })
1948 }
1949
1950 #[fuchsia::test]
1951 fn state_machine_sme_starts_ap_successfully() {
1952 let mut exec = fasync::TestExecutor::new();
1953
1954 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
1956 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1957 let iface_id = rand::random::<u16>();
1958 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1959
1960 let config = fidl_sme::ApConfig::from(create_ap_config());
1962 let fut = sme.start(&config);
1963 let mut fut = pin!(fut);
1964 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1965
1966 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1968 assert_matches!(
1969 poll_ap_sme_req(&mut exec, &mut sme_fut),
1970 Poll::Ready(fidl_sme::ApSmeRequest::Start { responder, .. }) => {
1971 responder.send(fidl_sme::StartApResultCode::Success)
1972 .expect("could not send sme response");
1973 }
1974 );
1975
1976 assert_matches!(
1978 exec.run_until_stalled(&mut fut),
1979 Poll::Ready(Ok(fidl_sme::StartApResultCode::Success))
1980 );
1981 }
1982
1983 #[fuchsia::test]
1984 fn state_machine_sme_fails_to_request_start_ap() {
1985 let mut exec = fasync::TestExecutor::new();
1986
1987 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
1989 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1990 let iface_id = rand::random::<u16>();
1991 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1992
1993 let config = fidl_sme::ApConfig::from(create_ap_config());
1995 let fut = sme.start(&config);
1996 let mut fut = pin!(fut);
1997 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1998 }
1999
2000 #[fuchsia::test]
2001 fn state_machine_sme_start_ap_timeout() {
2002 let mut exec = fasync::TestExecutor::new_with_fake_time();
2003 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2004
2005 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2007 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2008 let iface_id = rand::random::<u16>();
2009 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2010
2011 let config = fidl_sme::ApConfig::from(create_ap_config());
2013 let fut = sme.start(&config);
2014 let mut fut = pin!(fut);
2015 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2016
2017 exec.set_fake_time(fasync::MonotonicInstant::after(
2019 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2020 ));
2021
2022 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2024 assert_eq!(
2025 defect_receiver.try_next().expect("missing connection timeout"),
2026 Some(Defect::Iface(IfaceFailure::Timeout {
2027 iface_id,
2028 source: telemetry::TimeoutSource::ApStart,
2029 })),
2030 );
2031 }
2032
2033 #[fuchsia::test]
2034 fn state_machine_sme_stops_ap_successfully() {
2035 let mut exec = fasync::TestExecutor::new();
2036
2037 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2039 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2040 let iface_id = rand::random::<u16>();
2041 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2042
2043 let fut = sme.stop();
2045 let mut fut = pin!(fut);
2046 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2047
2048 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2050 assert_matches!(
2051 poll_ap_sme_req(&mut exec, &mut sme_fut),
2052 Poll::Ready(fidl_sme::ApSmeRequest::Stop { responder }) => {
2053 responder.send(fidl_sme::StopApResultCode::Success)
2054 .expect("could not send sme response");
2055 }
2056 );
2057
2058 assert_matches!(
2060 exec.run_until_stalled(&mut fut),
2061 Poll::Ready(Ok(fidl_sme::StopApResultCode::Success))
2062 );
2063 }
2064
2065 #[fuchsia::test]
2066 fn state_machine_sme_fails_to_request_stop_ap() {
2067 let mut exec = fasync::TestExecutor::new();
2068
2069 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2071 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2072 let iface_id = rand::random::<u16>();
2073 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2074
2075 let fut = sme.stop();
2077 let mut fut = pin!(fut);
2078 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2079 }
2080
2081 #[fuchsia::test]
2082 fn state_machine_sme_stop_ap_timeout() {
2083 let mut exec = fasync::TestExecutor::new_with_fake_time();
2084 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2085
2086 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2088 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2089 let iface_id = rand::random::<u16>();
2090 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2091
2092 let fut = sme.stop();
2094 let mut fut = pin!(fut);
2095 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2096
2097 exec.set_fake_time(fasync::MonotonicInstant::after(
2099 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2100 ));
2101
2102 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2104 assert_eq!(
2105 defect_receiver.try_next().expect("missing connection timeout"),
2106 Some(Defect::Iface(IfaceFailure::Timeout {
2107 iface_id,
2108 source: telemetry::TimeoutSource::ApStop,
2109 })),
2110 );
2111 }
2112
2113 #[fuchsia::test]
2114 fn state_machine_sme_successfully_queries_ap_status() {
2115 let mut exec = fasync::TestExecutor::new();
2116
2117 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2119 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2120 let iface_id = rand::random::<u16>();
2121 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2122
2123 let fut = sme.status();
2125 let mut fut = pin!(fut);
2126 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2127
2128 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2130 assert_matches!(
2131 poll_ap_sme_req(&mut exec, &mut sme_fut),
2132 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
2133 let response = fidl_sme::ApStatusResponse { running_ap: None };
2134 responder.send(&response).expect("could not send AP status response");
2135 }
2136 );
2137
2138 assert_matches!(
2140 exec.run_until_stalled(&mut fut),
2141 Poll::Ready(Ok(fidl_sme::ApStatusResponse { running_ap: None }))
2142 );
2143 }
2144
2145 #[fuchsia::test]
2146 fn state_machine_sme_fails_to_query_ap_status() {
2147 let mut exec = fasync::TestExecutor::new();
2148
2149 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2151 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2152 let iface_id = rand::random::<u16>();
2153 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2154
2155 let fut = sme.status();
2157 let mut fut = pin!(fut);
2158 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2159 }
2160
2161 #[fuchsia::test]
2162 fn state_machine_sme_query_ap_status_timeout() {
2163 let mut exec = fasync::TestExecutor::new_with_fake_time();
2164 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2165
2166 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2168 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2169 let iface_id = rand::random::<u16>();
2170 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2171
2172 let fut = sme.status();
2174 let mut fut = pin!(fut);
2175 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2176
2177 exec.set_fake_time(fasync::MonotonicInstant::after(
2179 AP_STATUS_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2180 ));
2181
2182 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2184 assert_eq!(
2185 defect_receiver.try_next().expect("missing connection timeout"),
2186 Some(Defect::Iface(IfaceFailure::Timeout {
2187 iface_id,
2188 source: telemetry::TimeoutSource::ApStatus,
2189 })),
2190 );
2191 }
2192}