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 ),
1245 mode: types::ConnectivityMode::Unrestricted,
1246 band: types::OperatingBand::Any,
1247 }
1248 }
1249
1250 #[fuchsia::test]
1251 fn test_start_ap_succeeds() {
1252 let mut test_values = test_setup();
1253
1254 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1256 let mut start_fut = pin!(start_fut);
1257 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1258
1259 let next_message = test_values.receiver.next();
1261 let mut next_message = pin!(next_message);
1262
1263 assert_matches!(
1264 test_values.exec.run_until_stalled(&mut next_message),
1265 Poll::Ready(Some(IfaceManagerRequest::StartAp(StartApRequest{
1266 config, responder
1267 }))) => {
1268 assert_eq!(config, create_ap_config());
1269
1270 let (_, receiver) = oneshot::channel();
1271 responder.send(Ok(receiver)).expect("failed to send start AP response");
1272 }
1273 );
1274
1275 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1277 }
1278
1279 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1280 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1281 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1282 #[fuchsia::test(add_test_attr = false)]
1283 fn start_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1284 let mut test_values = test_setup();
1285
1286 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1288 let mut start_fut = pin!(start_fut);
1289 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1290
1291 let service_fut =
1292 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1293 let mut service_fut = pin!(service_fut);
1294
1295 match failure_mode {
1296 NegativeTestFailureMode::RequestFailure => {}
1297 _ => {
1298 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1300 assert_matches!(
1301 test_values.exec.run_until_stalled(&mut service_fut),
1302 Poll::Ready(())
1303 );
1304 }
1305 }
1306
1307 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1309 }
1310
1311 #[fuchsia::test]
1312 fn test_stop_ap_succeeds() {
1313 let mut test_values = test_setup();
1314
1315 let stop_fut = test_values
1317 .iface_manager
1318 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1319 let mut stop_fut = pin!(stop_fut);
1320 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1321
1322 let next_message = test_values.receiver.next();
1324 let mut next_message = pin!(next_message);
1325
1326 assert_matches!(
1327 test_values.exec.run_until_stalled(&mut next_message),
1328 Poll::Ready(Some(IfaceManagerRequest::StopAp(StopApRequest{
1329 ssid, password, responder
1330 }))) => {
1331 assert_eq!(ssid, Ssid::try_from("foo").unwrap());
1332 assert_eq!(password, "bar".as_bytes().to_vec());
1333
1334 responder.send(Ok(())).expect("failed to send stop AP response");
1335 }
1336 );
1337
1338 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1340 }
1341
1342 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1343 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1344 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1345 #[fuchsia::test(add_test_attr = false)]
1346 fn stop_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1347 let mut test_values = test_setup();
1348
1349 let stop_fut = test_values
1351 .iface_manager
1352 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1353 let mut stop_fut = pin!(stop_fut);
1354 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1355
1356 let service_fut =
1357 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1358 let mut service_fut = pin!(service_fut);
1359
1360 match failure_mode {
1361 NegativeTestFailureMode::RequestFailure => {}
1362 _ => {
1363 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1365 assert_matches!(
1366 test_values.exec.run_until_stalled(&mut service_fut),
1367 Poll::Ready(())
1368 );
1369 }
1370 }
1371
1372 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1374 }
1375
1376 #[fuchsia::test]
1377 fn test_stop_all_aps_succeeds() {
1378 let mut test_values = test_setup();
1379
1380 let stop_fut = test_values.iface_manager.stop_all_aps();
1382 let mut stop_fut = pin!(stop_fut);
1383 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1384
1385 let next_message = test_values.receiver.next();
1387 let mut next_message = pin!(next_message);
1388 assert_matches!(
1389 test_values.exec.run_until_stalled(&mut next_message),
1390 Poll::Ready(Some(IfaceManagerRequest::StopAllAps(StopAllApsRequest{
1391 responder
1392 }))) => {
1393 responder.send(Ok(())).expect("failed to send stop AP response");
1394 }
1395 );
1396
1397 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1399 }
1400
1401 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1402 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1403 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1404 #[fuchsia::test(add_test_attr = false)]
1405 fn stop_all_aps_negative_test(failure_mode: NegativeTestFailureMode) {
1406 let mut test_values = test_setup();
1407
1408 let stop_fut = test_values.iface_manager.stop_all_aps();
1410 let mut stop_fut = pin!(stop_fut);
1411 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1412
1413 let service_fut =
1414 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1415 let mut service_fut = pin!(service_fut);
1416
1417 match failure_mode {
1418 NegativeTestFailureMode::RequestFailure => {}
1419 _ => {
1420 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1422 assert_matches!(
1423 test_values.exec.run_until_stalled(&mut service_fut),
1424 Poll::Ready(())
1425 );
1426 }
1427 }
1428
1429 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1431 }
1432
1433 #[fuchsia::test]
1434 fn test_set_country_succeeds() {
1435 let mut test_values = test_setup();
1436
1437 let set_country_fut = test_values.iface_manager.set_country(None);
1439 let mut set_country_fut = pin!(set_country_fut);
1440 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1441
1442 let next_message = test_values.receiver.next();
1444 let mut next_message = pin!(next_message);
1445
1446 assert_matches!(
1447 test_values.exec.run_until_stalled(&mut next_message),
1448 Poll::Ready(Some(IfaceManagerRequest::SetCountry(SetCountryRequest{
1449 country_code: None,
1450 responder
1451 }))) => {
1452 responder.send(Ok(())).expect("failed to send stop AP response");
1453 }
1454 );
1455
1456 assert_matches!(
1458 test_values.exec.run_until_stalled(&mut set_country_fut),
1459 Poll::Ready(Ok(_))
1460 );
1461 }
1462
1463 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1464 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1465 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1466 #[fuchsia::test(add_test_attr = false)]
1467 fn set_country_negative_test(failure_mode: NegativeTestFailureMode) {
1468 let mut test_values = test_setup();
1469
1470 let set_country_fut = test_values.iface_manager.set_country(None);
1472 let mut set_country_fut = pin!(set_country_fut);
1473 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1474 let service_fut =
1475 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1476 let mut service_fut = pin!(service_fut);
1477
1478 match failure_mode {
1479 NegativeTestFailureMode::RequestFailure => {}
1480 _ => {
1481 assert_matches!(
1483 test_values.exec.run_until_stalled(&mut set_country_fut),
1484 Poll::Pending
1485 );
1486 assert_matches!(
1487 test_values.exec.run_until_stalled(&mut service_fut),
1488 Poll::Ready(())
1489 );
1490 }
1491 }
1492
1493 assert_matches!(
1495 test_values.exec.run_until_stalled(&mut set_country_fut),
1496 Poll::Ready(Err(_))
1497 );
1498 }
1499
1500 #[fuchsia::test]
1501 fn test_sme_for_scan() {
1502 let mut exec = fasync::TestExecutor::new();
1503
1504 let (proxy, server_end) = create_proxy::<fidl_sme::ClientSmeMarker>();
1506 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1507 let sme = SmeForScan::new(proxy, 0, defect_sender);
1508 let mut sme_stream = server_end.into_stream();
1509
1510 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1512 ssids: vec![vec![]],
1513 channels: vec![],
1514 });
1515
1516 let scan_result_fut = sme.scan(&scan_request);
1518 let mut scan_result_fut = pin!(scan_result_fut);
1519 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1520
1521 assert_matches!(
1523 exec.run_until_stalled(&mut sme_stream.next()),
1524 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1525 req, ..
1526 }))) => {
1527 assert_eq!(scan_request, req)
1528 }
1529 );
1530 }
1531
1532 #[fuchsia::test]
1533 fn sme_for_scan_defects() {
1534 let _exec = fasync::TestExecutor::new();
1535
1536 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1538 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1539 let iface_id = rand::random::<u16>();
1540 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1541
1542 sme.log_aborted_scan_defect();
1543 sme.log_failed_scan_defect();
1544 sme.log_empty_scan_defect();
1545
1546 assert_eq!(
1547 defect_receiver.try_next().expect("missing canceled scan error"),
1548 Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id })),
1549 );
1550 assert_eq!(
1551 defect_receiver.try_next().expect("missing failed scan error"),
1552 Some(Defect::Iface(IfaceFailure::FailedScan { iface_id })),
1553 );
1554 assert_eq!(
1555 defect_receiver.try_next().expect("missing empty scan results error"),
1556 Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id })),
1557 );
1558 }
1559
1560 #[fuchsia::test]
1561 fn sme_for_scan_timeout() {
1562 let mut exec = fasync::TestExecutor::new_with_fake_time();
1563 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1564
1565 let (proxy, _server) = create_proxy::<fidl_sme::ClientSmeMarker>();
1567 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1568 let iface_id = rand::random::<u16>();
1569 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1570
1571 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1573 ssids: vec![vec![]],
1574 channels: vec![],
1575 });
1576 let scan_result_fut = sme.scan(&scan_request);
1577 let mut scan_result_fut = pin!(scan_result_fut);
1578 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1579
1580 exec.set_fake_time(fasync::MonotonicInstant::after(
1582 SCAN_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1583 ));
1584
1585 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Ready(Err(_)));
1587 assert_eq!(
1588 defect_receiver.try_next().expect("missing empty scan results error"),
1589 Some(Defect::Iface(IfaceFailure::Timeout {
1590 iface_id,
1591 source: telemetry::TimeoutSource::Scan,
1592 })),
1593 );
1594 }
1595
1596 #[fuchsia::test]
1597 fn state_machine_sme_disconnects_successfully() {
1598 let mut exec = fasync::TestExecutor::new();
1599
1600 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1602 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1603 let iface_id = rand::random::<u16>();
1604 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1605
1606 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1608 let mut fut = pin!(fut);
1609 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1610
1611 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1613 assert_matches!(
1614 poll_sme_req(&mut exec, &mut sme_fut),
1615 Poll::Ready(fidl_sme::ClientSmeRequest::Disconnect{
1616 responder,
1617 reason: fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest
1618 }) => {
1619 responder.send().expect("could not send sme response");
1620 }
1621 );
1622
1623 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1625 }
1626
1627 #[fuchsia::test]
1628 fn state_machine_sme_fails_to_disconnect() {
1629 let mut exec = fasync::TestExecutor::new();
1630
1631 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1633 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1634 let iface_id = rand::random::<u16>();
1635 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1636
1637 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1639 let mut fut = pin!(fut);
1640 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1641 }
1642
1643 #[fuchsia::test]
1644 fn state_machine_sme_disconnect_timeout() {
1645 let mut exec = fasync::TestExecutor::new_with_fake_time();
1646 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1647
1648 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1650 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1651 let iface_id = rand::random::<u16>();
1652 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1653
1654 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1656 let mut fut = pin!(fut);
1657 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1658
1659 exec.set_fake_time(fasync::MonotonicInstant::after(
1661 DISCONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1662 ));
1663
1664 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1666 assert_eq!(
1667 defect_receiver.try_next().expect("missing empty scan results error"),
1668 Some(Defect::Iface(IfaceFailure::Timeout {
1669 iface_id,
1670 source: telemetry::TimeoutSource::Disconnect,
1671 })),
1672 );
1673 }
1674
1675 #[fuchsia::test]
1676 fn state_machine_sme_roam_sends_request() {
1677 let mut exec = fasync::TestExecutor::new();
1678
1679 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1681 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1682 let iface_id = rand::random::<u16>();
1683 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1684
1685 let roam_request =
1687 fidl_sme::RoamRequest { bss_description: random_fidl_bss_description!() };
1688 sme.roam(&roam_request).unwrap();
1689
1690 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1692 assert_matches!(
1693 poll_sme_req(&mut exec, &mut sme_fut),
1694 Poll::Ready(fidl_sme::ClientSmeRequest::Roam {
1695 req, ..
1696 }) => {
1697 assert_eq!(req, roam_request);
1698 }
1699 );
1700 }
1701
1702 fn generate_connect_request() -> fidl_sme::ConnectRequest {
1703 let connection_selection = generate_connect_selection();
1704 fidl_sme::ConnectRequest {
1705 ssid: connection_selection.target.network.ssid.to_vec(),
1706 bss_description: Sequestered::release(connection_selection.target.bss.bss_description),
1707 multiple_bss_candidates: connection_selection.target.network_has_multiple_bss,
1708 authentication: connection_selection.target.authenticator.clone().into(),
1709 deprecated_scan_type: fidl_fuchsia_wlan_common::ScanType::Active,
1710 }
1711 }
1712
1713 #[fuchsia::test]
1714 fn state_machine_sme_connects_successfully() {
1715 let mut exec = fasync::TestExecutor::new();
1716
1717 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1719 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1720 let iface_id = rand::random::<u16>();
1721 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1722
1723 let connect_request = generate_connect_request();
1725 let fut = sme.connect(&connect_request);
1726 let mut fut = pin!(fut);
1727 match exec.run_until_stalled(&mut fut) {
1728 Poll::Pending => {}
1729 _ => panic!("connect request should be pending."),
1730 }
1731
1732 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1734 assert_matches!(
1735 poll_sme_req(&mut exec, &mut sme_fut),
1736 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1737 txn,
1738 ..
1739 }) => {
1740 let (_stream, ctrl) = txn.expect("connect txn unused")
1741 .into_stream_and_control_handle();
1742 ctrl
1743 .send_on_connect_result(&fidl_sme::ConnectResult {
1744 code: fidl_ieee80211::StatusCode::Success,
1745 is_credential_rejected: false,
1746 is_reconnect: false,
1747 })
1748 .expect("failed to send connection completion");
1749 }
1750 );
1751
1752 match exec.run_until_stalled(&mut fut) {
1754 Poll::Ready(Ok((result, txn))) => {
1755 assert_eq!(
1756 result,
1757 fidl_sme::ConnectResult {
1758 code: fidl_ieee80211::StatusCode::Success,
1759 is_credential_rejected: false,
1760 is_reconnect: false,
1761 }
1762 );
1763 drop(txn)
1766 }
1767 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1768 Poll::Pending => panic!("connect request should not be pending."),
1769 }
1770 }
1771
1772 #[fuchsia::test]
1773 fn state_machine_sme_connection_failure() {
1774 let mut exec = fasync::TestExecutor::new();
1775
1776 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1778 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1779 let iface_id = rand::random::<u16>();
1780 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1781
1782 let connect_request = generate_connect_request();
1784 let fut = sme.connect(&connect_request);
1785 let mut fut = pin!(fut);
1786 match exec.run_until_stalled(&mut fut) {
1787 Poll::Pending => {}
1788 _ => panic!("connect request should be pending."),
1789 }
1790
1791 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1793 assert_matches!(
1794 poll_sme_req(&mut exec, &mut sme_fut),
1795 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1796 txn,
1797 ..
1798 }) => {
1799 let (_stream, ctrl) = txn.expect("connect txn unused")
1800 .into_stream_and_control_handle();
1801 ctrl
1802 .send_on_connect_result(&fidl_sme::ConnectResult {
1803 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1804 is_credential_rejected: false,
1805 is_reconnect: false,
1806 })
1807 .expect("failed to send connection completion");
1808 }
1809 );
1810
1811 match exec.run_until_stalled(&mut fut) {
1813 Poll::Ready(Ok((result, txn))) => {
1814 assert_eq!(
1815 result,
1816 fidl_sme::ConnectResult {
1817 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1818 is_credential_rejected: false,
1819 is_reconnect: false,
1820 }
1821 );
1822 drop(txn)
1825 }
1826 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1827 Poll::Pending => panic!("connect request should not be pending."),
1828 }
1829 }
1830
1831 #[fuchsia::test]
1832 fn state_machine_sme_connect_request_fails() {
1833 let mut exec = fasync::TestExecutor::new();
1834
1835 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1837 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1838 let iface_id = rand::random::<u16>();
1839 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1840
1841 let connect_request = generate_connect_request();
1843 let fut = sme.connect(&connect_request);
1844 let mut fut = pin!(fut);
1845 match exec.run_until_stalled(&mut fut) {
1846 Poll::Ready(Err(_)) => {}
1847 _ => panic!("connect request should have failed."),
1848 }
1849 }
1850
1851 #[fuchsia::test]
1852 fn state_machine_sme_connect_timeout() {
1853 let mut exec = fasync::TestExecutor::new_with_fake_time();
1854 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1855
1856 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1858 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1859 let iface_id = rand::random::<u16>();
1860 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1861
1862 let connect_request = generate_connect_request();
1864 let fut = sme.connect(&connect_request);
1865 let mut fut = pin!(fut);
1866 match exec.run_until_stalled(&mut fut) {
1867 Poll::Pending => {}
1868 _ => panic!("connect future completed unexpectedly"),
1869 }
1870
1871 exec.set_fake_time(fasync::MonotonicInstant::after(
1873 CONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1874 ));
1875
1876 match exec.run_until_stalled(&mut fut) {
1878 Poll::Ready(Err(_)) => {}
1879 Poll::Ready(Ok(_)) => panic!("connect future completed successfully"),
1880 Poll::Pending => panic!("connect future did not complete"),
1881 }
1882 assert_eq!(
1883 defect_receiver.try_next().expect("missing connection timeout"),
1884 Some(Defect::Iface(IfaceFailure::Timeout {
1885 iface_id,
1886 source: telemetry::TimeoutSource::Connect,
1887 })),
1888 );
1889 }
1890
1891 #[fuchsia::test]
1892 fn wait_for_connect_result_error() {
1893 let mut exec = fasync::TestExecutor::new();
1894 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1895 let mut response_stream = connect_txn.take_event_stream();
1896
1897 let fut = wait_for_connect_result(&mut response_stream);
1898
1899 let mut fut = pin!(fut);
1900 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1901
1902 drop(remote);
1904 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1905 }
1906
1907 #[fuchsia::test]
1908 fn wait_for_connect_result_ignores_other_events() {
1909 let mut exec = fasync::TestExecutor::new();
1910 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1911 let request_handle = remote.into_stream().control_handle();
1912 let mut response_stream = connect_txn.take_event_stream();
1913
1914 let fut = wait_for_connect_result(&mut response_stream);
1915
1916 let mut fut = pin!(fut);
1917 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1918
1919 let ind = fidl_internal::SignalReportIndication { rssi_dbm: -20, snr_db: 25 };
1921 request_handle.send_on_signal_report(&ind).unwrap();
1922
1923 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1925
1926 let sme_result = fidl_sme::ConnectResult {
1928 code: fidl_ieee80211::StatusCode::Success,
1929 is_credential_rejected: false,
1930 is_reconnect: false,
1931 };
1932 request_handle.send_on_connect_result(&sme_result).unwrap();
1933 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(response)) => {
1934 assert_eq!(sme_result, response);
1935 });
1936 }
1937
1938 fn poll_ap_sme_req(
1939 exec: &mut fasync::TestExecutor,
1940 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
1941 ) -> Poll<fidl_sme::ApSmeRequest> {
1942 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
1943 *next_sme_req = stream.into_future();
1944 req.expect("did not expect the SME request stream to end")
1945 .expect("error polling SME request stream")
1946 })
1947 }
1948
1949 #[fuchsia::test]
1950 fn state_machine_sme_starts_ap_successfully() {
1951 let mut exec = fasync::TestExecutor::new();
1952
1953 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
1955 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1956 let iface_id = rand::random::<u16>();
1957 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1958
1959 let config = fidl_sme::ApConfig::from(create_ap_config());
1961 let fut = sme.start(&config);
1962 let mut fut = pin!(fut);
1963 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1964
1965 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1967 assert_matches!(
1968 poll_ap_sme_req(&mut exec, &mut sme_fut),
1969 Poll::Ready(fidl_sme::ApSmeRequest::Start { responder, .. }) => {
1970 responder.send(fidl_sme::StartApResultCode::Success)
1971 .expect("could not send sme response");
1972 }
1973 );
1974
1975 assert_matches!(
1977 exec.run_until_stalled(&mut fut),
1978 Poll::Ready(Ok(fidl_sme::StartApResultCode::Success))
1979 );
1980 }
1981
1982 #[fuchsia::test]
1983 fn state_machine_sme_fails_to_request_start_ap() {
1984 let mut exec = fasync::TestExecutor::new();
1985
1986 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
1988 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1989 let iface_id = rand::random::<u16>();
1990 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1991
1992 let config = fidl_sme::ApConfig::from(create_ap_config());
1994 let fut = sme.start(&config);
1995 let mut fut = pin!(fut);
1996 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1997 }
1998
1999 #[fuchsia::test]
2000 fn state_machine_sme_start_ap_timeout() {
2001 let mut exec = fasync::TestExecutor::new_with_fake_time();
2002 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2003
2004 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2006 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2007 let iface_id = rand::random::<u16>();
2008 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2009
2010 let config = fidl_sme::ApConfig::from(create_ap_config());
2012 let fut = sme.start(&config);
2013 let mut fut = pin!(fut);
2014 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2015
2016 exec.set_fake_time(fasync::MonotonicInstant::after(
2018 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2019 ));
2020
2021 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2023 assert_eq!(
2024 defect_receiver.try_next().expect("missing connection timeout"),
2025 Some(Defect::Iface(IfaceFailure::Timeout {
2026 iface_id,
2027 source: telemetry::TimeoutSource::ApStart,
2028 })),
2029 );
2030 }
2031
2032 #[fuchsia::test]
2033 fn state_machine_sme_stops_ap_successfully() {
2034 let mut exec = fasync::TestExecutor::new();
2035
2036 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2038 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2039 let iface_id = rand::random::<u16>();
2040 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2041
2042 let fut = sme.stop();
2044 let mut fut = pin!(fut);
2045 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2046
2047 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2049 assert_matches!(
2050 poll_ap_sme_req(&mut exec, &mut sme_fut),
2051 Poll::Ready(fidl_sme::ApSmeRequest::Stop { responder }) => {
2052 responder.send(fidl_sme::StopApResultCode::Success)
2053 .expect("could not send sme response");
2054 }
2055 );
2056
2057 assert_matches!(
2059 exec.run_until_stalled(&mut fut),
2060 Poll::Ready(Ok(fidl_sme::StopApResultCode::Success))
2061 );
2062 }
2063
2064 #[fuchsia::test]
2065 fn state_machine_sme_fails_to_request_stop_ap() {
2066 let mut exec = fasync::TestExecutor::new();
2067
2068 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2070 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2071 let iface_id = rand::random::<u16>();
2072 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2073
2074 let fut = sme.stop();
2076 let mut fut = pin!(fut);
2077 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2078 }
2079
2080 #[fuchsia::test]
2081 fn state_machine_sme_stop_ap_timeout() {
2082 let mut exec = fasync::TestExecutor::new_with_fake_time();
2083 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2084
2085 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2087 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2088 let iface_id = rand::random::<u16>();
2089 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2090
2091 let fut = sme.stop();
2093 let mut fut = pin!(fut);
2094 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2095
2096 exec.set_fake_time(fasync::MonotonicInstant::after(
2098 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2099 ));
2100
2101 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2103 assert_eq!(
2104 defect_receiver.try_next().expect("missing connection timeout"),
2105 Some(Defect::Iface(IfaceFailure::Timeout {
2106 iface_id,
2107 source: telemetry::TimeoutSource::ApStop,
2108 })),
2109 );
2110 }
2111
2112 #[fuchsia::test]
2113 fn state_machine_sme_successfully_queries_ap_status() {
2114 let mut exec = fasync::TestExecutor::new();
2115
2116 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2118 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2119 let iface_id = rand::random::<u16>();
2120 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2121
2122 let fut = sme.status();
2124 let mut fut = pin!(fut);
2125 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2126
2127 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2129 assert_matches!(
2130 poll_ap_sme_req(&mut exec, &mut sme_fut),
2131 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
2132 let response = fidl_sme::ApStatusResponse { running_ap: None };
2133 responder.send(&response).expect("could not send AP status response");
2134 }
2135 );
2136
2137 assert_matches!(
2139 exec.run_until_stalled(&mut fut),
2140 Poll::Ready(Ok(fidl_sme::ApStatusResponse { running_ap: None }))
2141 );
2142 }
2143
2144 #[fuchsia::test]
2145 fn state_machine_sme_fails_to_query_ap_status() {
2146 let mut exec = fasync::TestExecutor::new();
2147
2148 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2150 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2151 let iface_id = rand::random::<u16>();
2152 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2153
2154 let fut = sme.status();
2156 let mut fut = pin!(fut);
2157 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2158 }
2159
2160 #[fuchsia::test]
2161 fn state_machine_sme_query_ap_status_timeout() {
2162 let mut exec = fasync::TestExecutor::new_with_fake_time();
2163 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2164
2165 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2167 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2168 let iface_id = rand::random::<u16>();
2169 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2170
2171 let fut = sme.status();
2173 let mut fut = pin!(fut);
2174 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2175
2176 exec.set_fake_time(fasync::MonotonicInstant::after(
2178 AP_STATUS_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2179 ));
2180
2181 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2183 assert_eq!(
2184 defect_receiver.try_next().expect("missing connection timeout"),
2185 Some(Defect::Iface(IfaceFailure::Timeout {
2186 iface_id,
2187 source: telemetry::TimeoutSource::ApStatus,
2188 })),
2189 );
2190 }
2191}