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 futures::StreamExt;
496 use futures::future::LocalBoxFuture;
497 use futures::stream::StreamFuture;
498 use futures::task::Poll;
499 use rand::Rng;
500 use std::pin::pin;
501 use test_case::test_case;
502 use wlan_common::channel::Cbw;
503 use wlan_common::sequestered::Sequestered;
504 use wlan_common::{RadioConfig, random_fidl_bss_description};
505 use {
506 fidl_fuchsia_wlan_common as fidl_common, fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211,
507 fidl_fuchsia_wlan_internal as fidl_internal, fuchsia_async as fasync,
508 };
509
510 struct TestValues {
511 exec: fasync::TestExecutor,
512 iface_manager: IfaceManager,
513 receiver: mpsc::Receiver<IfaceManagerRequest>,
514 }
515
516 fn test_setup() -> TestValues {
517 let exec = fasync::TestExecutor::new();
518 let (sender, receiver) = mpsc::channel(1);
519 TestValues { exec, iface_manager: IfaceManager { sender }, receiver }
520 }
521
522 #[allow(clippy::enum_variant_names, reason = "mass allow for https://fxbug.dev/381896734")]
523 #[derive(Clone)]
524 enum NegativeTestFailureMode {
525 RequestFailure,
526 OperationFailure,
527 ServiceFailure,
528 }
529
530 fn handle_negative_test_result_responder<T: std::fmt::Debug>(
531 responder: oneshot::Sender<Result<T, Error>>,
532 failure_mode: NegativeTestFailureMode,
533 ) {
534 match failure_mode {
535 NegativeTestFailureMode::RequestFailure => {
536 panic!("Test bug: this request should have been handled previously")
537 }
538 NegativeTestFailureMode::OperationFailure => {
539 responder
540 .send(Err(format_err!("operation failed")))
541 .expect("failed to send response");
542 }
543 NegativeTestFailureMode::ServiceFailure => {
544 drop(responder);
546 }
547 }
548 }
549
550 fn handle_negative_test_responder<T: std::fmt::Debug>(
551 responder: oneshot::Sender<T>,
552 failure_mode: NegativeTestFailureMode,
553 ) {
554 match failure_mode {
555 NegativeTestFailureMode::RequestFailure | NegativeTestFailureMode::OperationFailure => {
556 panic!("Test bug: invalid operation")
557 }
558 NegativeTestFailureMode::ServiceFailure => {
559 drop(responder);
561 }
562 }
563 }
564
565 fn iface_manager_api_negative_test(
566 mut receiver: mpsc::Receiver<IfaceManagerRequest>,
567 failure_mode: NegativeTestFailureMode,
568 ) -> LocalBoxFuture<'static, ()> {
569 if let NegativeTestFailureMode::RequestFailure = failure_mode {
570 drop(receiver);
572 let fut = async move {};
573 return Box::pin(fut);
574 }
575
576 let fut = async move {
577 let req = match receiver.next().await {
578 Some(req) => req,
579 None => panic!("no request available."),
580 };
581
582 match req {
583 IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest {
585 responder,
586 ..
587 })
588 | IfaceManagerRequest::Disconnect(DisconnectRequest { responder, .. })
589 | IfaceManagerRequest::StopAp(StopApRequest { responder, .. })
590 | IfaceManagerRequest::StopAllAps(StopAllApsRequest { responder, .. })
591 | IfaceManagerRequest::SetCountry(SetCountryRequest { responder, .. })
592 | IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest {
593 responder,
594 })
595 | IfaceManagerRequest::Connect(ConnectRequest { responder, .. }) => {
596 handle_negative_test_result_responder(responder, failure_mode);
597 }
598 IfaceManagerRequest::GetScanProxy(ScanProxyRequest { responder }) => {
600 handle_negative_test_result_responder(responder, failure_mode);
601 }
602 IfaceManagerRequest::StartAp(StartApRequest { responder, .. }) => {
604 handle_negative_test_result_responder(responder, failure_mode);
605 }
606 IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest {
608 responder, ..
609 })
610 | IfaceManagerRequest::AddIface(AddIfaceRequest { responder, .. })
611 | IfaceManagerRequest::RemoveIface(RemoveIfaceRequest { responder, .. }) => {
612 handle_negative_test_responder(responder, failure_mode);
613 }
614 IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest { responder }) => {
616 handle_negative_test_responder(responder, failure_mode);
617 }
618 }
619 };
620 Box::pin(fut)
621 }
622
623 #[fuchsia::test]
624 fn test_disconnect_succeeds() {
625 let mut test_values = test_setup();
626
627 let req = ap_types::NetworkIdentifier {
629 ssid: Ssid::try_from("foo").unwrap(),
630 security_type: ap_types::SecurityType::None,
631 };
632 let req_reason = client_types::DisconnectReason::NetworkUnsaved;
633 let disconnect_fut = test_values.iface_manager.disconnect(req.clone(), req_reason);
634 let mut disconnect_fut = pin!(disconnect_fut);
635
636 assert_matches!(test_values.exec.run_until_stalled(&mut disconnect_fut), Poll::Pending);
637
638 let next_message = test_values.receiver.next();
640 let mut next_message = pin!(next_message);
641
642 assert_matches!(
643 test_values.exec.run_until_stalled(&mut next_message),
644 Poll::Ready(Some(IfaceManagerRequest::Disconnect(DisconnectRequest {
645 network_id, responder, reason
646 }))) => {
647 assert_eq!(network_id, req);
648 assert_eq!(reason, req_reason);
649 responder.send(Ok(())).expect("failed to send disconnect response");
650 }
651 );
652
653 assert_matches!(
655 test_values.exec.run_until_stalled(&mut disconnect_fut),
656 Poll::Ready(Ok(()))
657 );
658 }
659
660 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
661 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
662 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
663 #[fuchsia::test(add_test_attr = false)]
664 fn disconnect_negative_test(failure_mode: NegativeTestFailureMode) {
665 let mut test_values = test_setup();
666
667 let req = ap_types::NetworkIdentifier {
669 ssid: Ssid::try_from("foo").unwrap(),
670 security_type: ap_types::SecurityType::None,
671 };
672 let disconnect_fut = test_values
673 .iface_manager
674 .disconnect(req.clone(), client_types::DisconnectReason::NetworkUnsaved);
675 let mut disconnect_fut = pin!(disconnect_fut);
676
677 let service_fut =
678 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
679 let mut service_fut = pin!(service_fut);
680
681 match failure_mode {
682 NegativeTestFailureMode::RequestFailure => {}
683 _ => {
684 assert_matches!(
686 test_values.exec.run_until_stalled(&mut disconnect_fut),
687 Poll::Pending
688 );
689 assert_matches!(
690 test_values.exec.run_until_stalled(&mut service_fut),
691 Poll::Ready(())
692 );
693 }
694 }
695
696 assert_matches!(
698 test_values.exec.run_until_stalled(&mut disconnect_fut),
699 Poll::Ready(Err(_))
700 );
701 }
702
703 #[fuchsia::test]
704 fn test_connect_succeeds() {
705 let mut test_values = test_setup();
706
707 let req = ConnectAttemptRequest::new(
709 client_types::NetworkIdentifier {
710 ssid: Ssid::try_from("foo").unwrap(),
711 security_type: client_types::SecurityType::None,
712 },
713 Credential::None,
714 client_types::ConnectReason::FidlConnectRequest,
715 );
716 let connect_fut = test_values.iface_manager.connect(req.clone());
717 let mut connect_fut = pin!(connect_fut);
718
719 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Pending);
720
721 let next_message = test_values.receiver.next();
723 let mut next_message = pin!(next_message);
724
725 assert_matches!(
726 test_values.exec.run_until_stalled(&mut next_message),
727 Poll::Ready(Some(IfaceManagerRequest::Connect(ConnectRequest {
728 request, responder
729 }))) => {
730 assert_eq!(request, req);
731 responder.send(Ok(())).expect("failed to send connect response");
732 }
733 );
734
735 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Ok(_)));
737 }
738
739 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
740 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
741 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
742 #[fuchsia::test(add_test_attr = false)]
743 fn connect_negative_test(failure_mode: NegativeTestFailureMode) {
744 let mut test_values = test_setup();
745
746 let req = ConnectAttemptRequest::new(
748 client_types::NetworkIdentifier {
749 ssid: Ssid::try_from("foo").unwrap(),
750 security_type: client_types::SecurityType::None,
751 },
752 Credential::None,
753 client_types::ConnectReason::FidlConnectRequest,
754 );
755 let connect_fut = test_values.iface_manager.connect(req.clone());
756 let mut connect_fut = pin!(connect_fut);
757
758 let service_fut =
759 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
760 let mut service_fut = pin!(service_fut);
761
762 match failure_mode {
763 NegativeTestFailureMode::RequestFailure => {}
764 _ => {
765 assert_matches!(
767 test_values.exec.run_until_stalled(&mut connect_fut),
768 Poll::Pending
769 );
770 assert_matches!(
771 test_values.exec.run_until_stalled(&mut service_fut),
772 Poll::Ready(())
773 );
774 }
775 }
776
777 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
779 }
780
781 #[fuchsia::test]
782 fn test_record_idle_client_succeeds() {
783 let mut test_values = test_setup();
784
785 let iface_id = 123;
787 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
788 let mut idle_client_fut = pin!(idle_client_fut);
789
790 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
791
792 let next_message = test_values.receiver.next();
794 let mut next_message = pin!(next_message);
795
796 assert_matches!(
797 test_values.exec.run_until_stalled(&mut next_message),
798 Poll::Ready(
799 Some(IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest{ iface_id: 123, responder}))
800 ) => {
801 responder.send(()).expect("failed to send idle iface response");
802 }
803 );
804
805 assert_matches!(
807 test_values.exec.run_until_stalled(&mut idle_client_fut),
808 Poll::Ready(Ok(()))
809 );
810 }
811
812 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
813 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
814 #[fuchsia::test(add_test_attr = false)]
815 fn test_record_idle_client_service_failure(failure_mode: NegativeTestFailureMode) {
816 let mut test_values = test_setup();
817
818 let iface_id = 123;
820 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
821 let mut idle_client_fut = pin!(idle_client_fut);
822
823 let service_fut =
824 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
825 let mut service_fut = pin!(service_fut);
826
827 match failure_mode {
828 NegativeTestFailureMode::RequestFailure => {}
829 _ => {
830 assert_matches!(
832 test_values.exec.run_until_stalled(&mut idle_client_fut),
833 Poll::Pending
834 );
835 assert_matches!(
836 test_values.exec.run_until_stalled(&mut service_fut),
837 Poll::Ready(())
838 );
839 }
840 }
841
842 assert_matches!(
844 test_values.exec.run_until_stalled(&mut idle_client_fut),
845 Poll::Ready(Err(_))
846 );
847 }
848
849 #[fuchsia::test]
850 fn test_has_idle_client_success() {
851 let mut test_values = test_setup();
852
853 let idle_client_fut = test_values.iface_manager.has_idle_client();
855 let mut idle_client_fut = pin!(idle_client_fut);
856 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
857
858 let next_message = test_values.receiver.next();
860 let mut next_message = pin!(next_message);
861
862 assert_matches!(
863 test_values.exec.run_until_stalled(&mut next_message),
864 Poll::Ready(
865 Some(IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest{ responder}))
866 ) => responder.send(true).expect("failed to reply to idle client query")
867 );
868
869 assert_matches!(
871 test_values.exec.run_until_stalled(&mut idle_client_fut),
872 Poll::Ready(Ok(true))
873 );
874 }
875
876 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
877 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
878 #[fuchsia::test(add_test_attr = false)]
879 fn idle_client_negative_test(failure_mode: NegativeTestFailureMode) {
880 let mut test_values = test_setup();
881
882 let idle_client_fut = test_values.iface_manager.has_idle_client();
884 let mut idle_client_fut = pin!(idle_client_fut);
885 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
886
887 let service_fut =
888 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
889 let mut service_fut = pin!(service_fut);
890
891 match failure_mode {
892 NegativeTestFailureMode::RequestFailure => {}
893 _ => {
894 assert_matches!(
896 test_values.exec.run_until_stalled(&mut idle_client_fut),
897 Poll::Pending
898 );
899 assert_matches!(
900 test_values.exec.run_until_stalled(&mut service_fut),
901 Poll::Ready(())
902 );
903 }
904 }
905
906 assert_matches!(
908 test_values.exec.run_until_stalled(&mut idle_client_fut),
909 Poll::Ready(Err(_))
910 );
911 }
912
913 #[fuchsia::test]
914 fn test_add_iface_success() {
915 let mut test_values = test_setup();
916
917 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
919 let mut added_iface_fut = pin!(added_iface_fut);
920 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
921
922 let next_message = test_values.receiver.next();
924 let mut next_message = pin!(next_message);
925
926 assert_matches!(
927 test_values.exec.run_until_stalled(&mut next_message),
928 Poll::Ready(
929 Some(IfaceManagerRequest::AddIface(AddIfaceRequest{ iface_id: 123, responder }))
930 ) => {
931 responder.send(()).expect("failed to respond while adding iface");
932 }
933 );
934
935 assert_matches!(
937 test_values.exec.run_until_stalled(&mut added_iface_fut),
938 Poll::Ready(Ok(()))
939 );
940 }
941
942 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
943 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
944 #[fuchsia::test(add_test_attr = false)]
945 fn add_iface_negative_test(failure_mode: NegativeTestFailureMode) {
946 let mut test_values = test_setup();
947
948 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
950 let mut added_iface_fut = pin!(added_iface_fut);
951 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
952
953 let service_fut =
954 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
955 let mut service_fut = pin!(service_fut);
956
957 match failure_mode {
958 NegativeTestFailureMode::RequestFailure => {}
959 _ => {
960 assert_matches!(
962 test_values.exec.run_until_stalled(&mut added_iface_fut),
963 Poll::Pending
964 );
965 assert_matches!(
966 test_values.exec.run_until_stalled(&mut service_fut),
967 Poll::Ready(())
968 );
969 }
970 }
971
972 assert_matches!(
974 test_values.exec.run_until_stalled(&mut added_iface_fut),
975 Poll::Ready(Err(_))
976 );
977 }
978
979 #[fuchsia::test]
980 fn test_remove_iface_success() {
981 let mut test_values = test_setup();
982
983 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
985 let mut removed_iface_fut = pin!(removed_iface_fut);
986 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
987
988 let next_message = test_values.receiver.next();
990 let mut next_message = pin!(next_message);
991
992 assert_matches!(
993 test_values.exec.run_until_stalled(&mut next_message),
994 Poll::Ready(
995 Some(IfaceManagerRequest::RemoveIface(RemoveIfaceRequest{ iface_id: 123, responder }))
996 ) => {
997 responder.send(()).expect("failed to respond while adding iface");
998 }
999 );
1000
1001 assert_matches!(
1003 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1004 Poll::Ready(Ok(()))
1005 );
1006 }
1007
1008 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1009 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1010 #[fuchsia::test(add_test_attr = false)]
1011 fn remove_iface_negative_test(failure_mode: NegativeTestFailureMode) {
1012 let mut test_values = test_setup();
1013
1014 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
1016 let mut removed_iface_fut = pin!(removed_iface_fut);
1017 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
1018
1019 let service_fut =
1020 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1021 let mut service_fut = pin!(service_fut);
1022
1023 match failure_mode {
1024 NegativeTestFailureMode::RequestFailure => {}
1025 _ => {
1026 assert_matches!(
1028 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1029 Poll::Pending
1030 );
1031 assert_matches!(
1032 test_values.exec.run_until_stalled(&mut service_fut),
1033 Poll::Ready(())
1034 );
1035 }
1036 }
1037
1038 assert_matches!(
1040 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1041 Poll::Ready(Err(_))
1042 );
1043 }
1044
1045 #[fuchsia::test]
1046 fn test_get_scan_proxy_success() {
1047 let mut test_values = test_setup();
1048
1049 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1051 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1052 assert_matches!(test_values.exec.run_until_stalled(&mut scan_proxy_fut), Poll::Pending);
1053
1054 let next_message = test_values.receiver.next();
1056 let mut next_message = pin!(next_message);
1057
1058 assert_matches!(
1059 test_values.exec.run_until_stalled(&mut next_message),
1060 Poll::Ready(Some(IfaceManagerRequest::GetScanProxy(ScanProxyRequest{
1061 responder
1062 }))) => {
1063 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1064 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1065 responder.send(Ok(SmeForScan{proxy, iface_id: 0, defect_sender})).expect("failed to send scan sme proxy");
1066 }
1067 );
1068
1069 assert_matches!(
1071 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1072 Poll::Ready(Ok(_))
1073 );
1074 }
1075
1076 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1077 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1078 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1079 #[fuchsia::test(add_test_attr = false)]
1080 fn scan_proxy_negative_test(failure_mode: NegativeTestFailureMode) {
1081 let mut test_values = test_setup();
1082
1083 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1085 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1086
1087 let service_fut =
1088 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1089 let mut service_fut = pin!(service_fut);
1090
1091 match failure_mode {
1092 NegativeTestFailureMode::RequestFailure => {}
1093 _ => {
1094 assert_matches!(
1096 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1097 Poll::Pending
1098 );
1099 assert_matches!(
1100 test_values.exec.run_until_stalled(&mut service_fut),
1101 Poll::Ready(())
1102 );
1103 }
1104 }
1105
1106 assert_matches!(
1108 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1109 Poll::Ready(Err(_))
1110 );
1111 }
1112
1113 #[fuchsia::test]
1114 fn test_stop_client_connections_succeeds() {
1115 let mut test_values = test_setup();
1116
1117 let stop_fut = test_values.iface_manager.stop_client_connections(
1119 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1120 );
1121 let mut stop_fut = pin!(stop_fut);
1122 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1123
1124 let next_message = test_values.receiver.next();
1126 let mut next_message = pin!(next_message);
1127
1128 assert_matches!(
1129 test_values.exec.run_until_stalled(&mut next_message),
1130 Poll::Ready(Some(IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest{
1131 responder, reason
1132 }))) => {
1133 assert_eq!(reason, client_types::DisconnectReason::FidlStopClientConnectionsRequest);
1134 responder.send(Ok(())).expect("failed sending stop client connections response");
1135 }
1136 );
1137
1138 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(())));
1140 }
1141
1142 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1143 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1144 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1145 #[fuchsia::test(add_test_attr = false)]
1146 fn stop_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1147 let mut test_values = test_setup();
1148
1149 let stop_fut = test_values.iface_manager.stop_client_connections(
1151 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1152 );
1153 let mut stop_fut = pin!(stop_fut);
1154 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1155
1156 let service_fut =
1157 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1158 let mut service_fut = pin!(service_fut);
1159
1160 match failure_mode {
1161 NegativeTestFailureMode::RequestFailure => {}
1162 _ => {
1163 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1165 assert_matches!(
1166 test_values.exec.run_until_stalled(&mut service_fut),
1167 Poll::Ready(())
1168 );
1169 }
1170 }
1171
1172 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1174 }
1175
1176 #[fuchsia::test]
1177 fn test_start_client_connections_succeeds() {
1178 let mut test_values = test_setup();
1179
1180 let start_fut = test_values.iface_manager.start_client_connections();
1182 let mut start_fut = pin!(start_fut);
1183 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1184
1185 let next_message = test_values.receiver.next();
1187 let mut next_message = pin!(next_message);
1188
1189 assert_matches!(
1190 test_values.exec.run_until_stalled(&mut next_message),
1191 Poll::Ready(Some(IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest{
1192 responder
1193 }))) => {
1194 responder.send(Ok(())).expect("failed sending stop client connections response");
1195 }
1196 );
1197
1198 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(())));
1200 }
1201
1202 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1203 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1204 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1205 #[fuchsia::test(add_test_attr = false)]
1206 fn start_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1207 let mut test_values = test_setup();
1208
1209 let start_fut = test_values.iface_manager.start_client_connections();
1211 let mut start_fut = pin!(start_fut);
1212 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1213
1214 let service_fut =
1215 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1216 let mut service_fut = pin!(service_fut);
1217
1218 match failure_mode {
1219 NegativeTestFailureMode::RequestFailure => {}
1220 _ => {
1221 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1223 assert_matches!(
1224 test_values.exec.run_until_stalled(&mut service_fut),
1225 Poll::Ready(())
1226 );
1227 }
1228 }
1229
1230 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1232 }
1233
1234 fn create_ap_config() -> ap_fsm::ApConfig {
1235 ap_fsm::ApConfig {
1236 id: types::NetworkIdentifier {
1237 ssid: Ssid::try_from("foo").unwrap(),
1238 security_type: types::SecurityType::None,
1239 },
1240 credential: vec![],
1241 radio_config: RadioConfig::new(fidl_common::WlanPhyType::Ht, Cbw::Cbw20, 6),
1242 mode: types::ConnectivityMode::Unrestricted,
1243 band: types::OperatingBand::Any,
1244 }
1245 }
1246
1247 #[fuchsia::test]
1248 fn test_start_ap_succeeds() {
1249 let mut test_values = test_setup();
1250
1251 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1253 let mut start_fut = pin!(start_fut);
1254 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1255
1256 let next_message = test_values.receiver.next();
1258 let mut next_message = pin!(next_message);
1259
1260 assert_matches!(
1261 test_values.exec.run_until_stalled(&mut next_message),
1262 Poll::Ready(Some(IfaceManagerRequest::StartAp(StartApRequest{
1263 config, responder
1264 }))) => {
1265 assert_eq!(config, create_ap_config());
1266
1267 let (_, receiver) = oneshot::channel();
1268 responder.send(Ok(receiver)).expect("failed to send start AP response");
1269 }
1270 );
1271
1272 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1274 }
1275
1276 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1277 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1278 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1279 #[fuchsia::test(add_test_attr = false)]
1280 fn start_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1281 let mut test_values = test_setup();
1282
1283 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1285 let mut start_fut = pin!(start_fut);
1286 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1287
1288 let service_fut =
1289 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1290 let mut service_fut = pin!(service_fut);
1291
1292 match failure_mode {
1293 NegativeTestFailureMode::RequestFailure => {}
1294 _ => {
1295 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1297 assert_matches!(
1298 test_values.exec.run_until_stalled(&mut service_fut),
1299 Poll::Ready(())
1300 );
1301 }
1302 }
1303
1304 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1306 }
1307
1308 #[fuchsia::test]
1309 fn test_stop_ap_succeeds() {
1310 let mut test_values = test_setup();
1311
1312 let stop_fut = test_values
1314 .iface_manager
1315 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1316 let mut stop_fut = pin!(stop_fut);
1317 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1318
1319 let next_message = test_values.receiver.next();
1321 let mut next_message = pin!(next_message);
1322
1323 assert_matches!(
1324 test_values.exec.run_until_stalled(&mut next_message),
1325 Poll::Ready(Some(IfaceManagerRequest::StopAp(StopApRequest{
1326 ssid, password, responder
1327 }))) => {
1328 assert_eq!(ssid, Ssid::try_from("foo").unwrap());
1329 assert_eq!(password, "bar".as_bytes().to_vec());
1330
1331 responder.send(Ok(())).expect("failed to send stop AP response");
1332 }
1333 );
1334
1335 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1337 }
1338
1339 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1340 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1341 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1342 #[fuchsia::test(add_test_attr = false)]
1343 fn stop_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1344 let mut test_values = test_setup();
1345
1346 let stop_fut = test_values
1348 .iface_manager
1349 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1350 let mut stop_fut = pin!(stop_fut);
1351 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1352
1353 let service_fut =
1354 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1355 let mut service_fut = pin!(service_fut);
1356
1357 match failure_mode {
1358 NegativeTestFailureMode::RequestFailure => {}
1359 _ => {
1360 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1362 assert_matches!(
1363 test_values.exec.run_until_stalled(&mut service_fut),
1364 Poll::Ready(())
1365 );
1366 }
1367 }
1368
1369 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1371 }
1372
1373 #[fuchsia::test]
1374 fn test_stop_all_aps_succeeds() {
1375 let mut test_values = test_setup();
1376
1377 let stop_fut = test_values.iface_manager.stop_all_aps();
1379 let mut stop_fut = pin!(stop_fut);
1380 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1381
1382 let next_message = test_values.receiver.next();
1384 let mut next_message = pin!(next_message);
1385 assert_matches!(
1386 test_values.exec.run_until_stalled(&mut next_message),
1387 Poll::Ready(Some(IfaceManagerRequest::StopAllAps(StopAllApsRequest{
1388 responder
1389 }))) => {
1390 responder.send(Ok(())).expect("failed to send stop AP response");
1391 }
1392 );
1393
1394 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1396 }
1397
1398 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1399 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1400 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1401 #[fuchsia::test(add_test_attr = false)]
1402 fn stop_all_aps_negative_test(failure_mode: NegativeTestFailureMode) {
1403 let mut test_values = test_setup();
1404
1405 let stop_fut = test_values.iface_manager.stop_all_aps();
1407 let mut stop_fut = pin!(stop_fut);
1408 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1409
1410 let service_fut =
1411 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1412 let mut service_fut = pin!(service_fut);
1413
1414 match failure_mode {
1415 NegativeTestFailureMode::RequestFailure => {}
1416 _ => {
1417 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1419 assert_matches!(
1420 test_values.exec.run_until_stalled(&mut service_fut),
1421 Poll::Ready(())
1422 );
1423 }
1424 }
1425
1426 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1428 }
1429
1430 #[fuchsia::test]
1431 fn test_set_country_succeeds() {
1432 let mut test_values = test_setup();
1433
1434 let set_country_fut = test_values.iface_manager.set_country(None);
1436 let mut set_country_fut = pin!(set_country_fut);
1437 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1438
1439 let next_message = test_values.receiver.next();
1441 let mut next_message = pin!(next_message);
1442
1443 assert_matches!(
1444 test_values.exec.run_until_stalled(&mut next_message),
1445 Poll::Ready(Some(IfaceManagerRequest::SetCountry(SetCountryRequest{
1446 country_code: None,
1447 responder
1448 }))) => {
1449 responder.send(Ok(())).expect("failed to send stop AP response");
1450 }
1451 );
1452
1453 assert_matches!(
1455 test_values.exec.run_until_stalled(&mut set_country_fut),
1456 Poll::Ready(Ok(_))
1457 );
1458 }
1459
1460 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1461 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1462 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1463 #[fuchsia::test(add_test_attr = false)]
1464 fn set_country_negative_test(failure_mode: NegativeTestFailureMode) {
1465 let mut test_values = test_setup();
1466
1467 let set_country_fut = test_values.iface_manager.set_country(None);
1469 let mut set_country_fut = pin!(set_country_fut);
1470 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1471 let service_fut =
1472 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1473 let mut service_fut = pin!(service_fut);
1474
1475 match failure_mode {
1476 NegativeTestFailureMode::RequestFailure => {}
1477 _ => {
1478 assert_matches!(
1480 test_values.exec.run_until_stalled(&mut set_country_fut),
1481 Poll::Pending
1482 );
1483 assert_matches!(
1484 test_values.exec.run_until_stalled(&mut service_fut),
1485 Poll::Ready(())
1486 );
1487 }
1488 }
1489
1490 assert_matches!(
1492 test_values.exec.run_until_stalled(&mut set_country_fut),
1493 Poll::Ready(Err(_))
1494 );
1495 }
1496
1497 #[fuchsia::test]
1498 fn test_sme_for_scan() {
1499 let mut exec = fasync::TestExecutor::new();
1500
1501 let (proxy, server_end) = create_proxy::<fidl_sme::ClientSmeMarker>();
1503 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1504 let sme = SmeForScan::new(proxy, 0, defect_sender);
1505 let mut sme_stream = server_end.into_stream();
1506
1507 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1509 ssids: vec![vec![]],
1510 channels: vec![],
1511 });
1512
1513 let scan_result_fut = sme.scan(&scan_request);
1515 let mut scan_result_fut = pin!(scan_result_fut);
1516 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1517
1518 assert_matches!(
1520 exec.run_until_stalled(&mut sme_stream.next()),
1521 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1522 req, ..
1523 }))) => {
1524 assert_eq!(scan_request, req)
1525 }
1526 );
1527 }
1528
1529 #[fuchsia::test]
1530 fn sme_for_scan_defects() {
1531 let _exec = fasync::TestExecutor::new();
1532
1533 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1535 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1536 let iface_id = rand::random::<u16>();
1537 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1538
1539 sme.log_aborted_scan_defect();
1540 sme.log_failed_scan_defect();
1541 sme.log_empty_scan_defect();
1542
1543 assert_eq!(
1544 defect_receiver.try_next().expect("missing canceled scan error"),
1545 Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id })),
1546 );
1547 assert_eq!(
1548 defect_receiver.try_next().expect("missing failed scan error"),
1549 Some(Defect::Iface(IfaceFailure::FailedScan { iface_id })),
1550 );
1551 assert_eq!(
1552 defect_receiver.try_next().expect("missing empty scan results error"),
1553 Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id })),
1554 );
1555 }
1556
1557 #[fuchsia::test]
1558 fn sme_for_scan_timeout() {
1559 let mut exec = fasync::TestExecutor::new_with_fake_time();
1560 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1561
1562 let (proxy, _server) = create_proxy::<fidl_sme::ClientSmeMarker>();
1564 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1565 let iface_id = rand::random::<u16>();
1566 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1567
1568 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1570 ssids: vec![vec![]],
1571 channels: vec![],
1572 });
1573 let scan_result_fut = sme.scan(&scan_request);
1574 let mut scan_result_fut = pin!(scan_result_fut);
1575 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1576
1577 exec.set_fake_time(fasync::MonotonicInstant::after(
1579 SCAN_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1580 ));
1581
1582 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Ready(Err(_)));
1584 assert_eq!(
1585 defect_receiver.try_next().expect("missing empty scan results error"),
1586 Some(Defect::Iface(IfaceFailure::Timeout {
1587 iface_id,
1588 source: telemetry::TimeoutSource::Scan,
1589 })),
1590 );
1591 }
1592
1593 #[fuchsia::test]
1594 fn state_machine_sme_disconnects_successfully() {
1595 let mut exec = fasync::TestExecutor::new();
1596
1597 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1599 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1600 let iface_id = rand::random::<u16>();
1601 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1602
1603 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1605 let mut fut = pin!(fut);
1606 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1607
1608 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1610 assert_matches!(
1611 poll_sme_req(&mut exec, &mut sme_fut),
1612 Poll::Ready(fidl_sme::ClientSmeRequest::Disconnect{
1613 responder,
1614 reason: fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest
1615 }) => {
1616 responder.send().expect("could not send sme response");
1617 }
1618 );
1619
1620 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1622 }
1623
1624 #[fuchsia::test]
1625 fn state_machine_sme_fails_to_disconnect() {
1626 let mut exec = fasync::TestExecutor::new();
1627
1628 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1630 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1631 let iface_id = rand::random::<u16>();
1632 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1633
1634 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1636 let mut fut = pin!(fut);
1637 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1638 }
1639
1640 #[fuchsia::test]
1641 fn state_machine_sme_disconnect_timeout() {
1642 let mut exec = fasync::TestExecutor::new_with_fake_time();
1643 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1644
1645 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1647 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1648 let iface_id = rand::random::<u16>();
1649 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1650
1651 let fut = sme.disconnect(fidl_sme::UserDisconnectReason::FidlStopClientConnectionsRequest);
1653 let mut fut = pin!(fut);
1654 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1655
1656 exec.set_fake_time(fasync::MonotonicInstant::after(
1658 DISCONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1659 ));
1660
1661 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1663 assert_eq!(
1664 defect_receiver.try_next().expect("missing empty scan results error"),
1665 Some(Defect::Iface(IfaceFailure::Timeout {
1666 iface_id,
1667 source: telemetry::TimeoutSource::Disconnect,
1668 })),
1669 );
1670 }
1671
1672 #[fuchsia::test]
1673 fn state_machine_sme_roam_sends_request() {
1674 let mut exec = fasync::TestExecutor::new();
1675
1676 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1678 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1679 let iface_id = rand::random::<u16>();
1680 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1681
1682 let roam_request =
1684 fidl_sme::RoamRequest { bss_description: random_fidl_bss_description!() };
1685 sme.roam(&roam_request).unwrap();
1686
1687 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1689 assert_matches!(
1690 poll_sme_req(&mut exec, &mut sme_fut),
1691 Poll::Ready(fidl_sme::ClientSmeRequest::Roam {
1692 req, ..
1693 }) => {
1694 assert_eq!(req, roam_request);
1695 }
1696 );
1697 }
1698
1699 fn generate_connect_request() -> fidl_sme::ConnectRequest {
1700 let connection_selection = generate_connect_selection();
1701 fidl_sme::ConnectRequest {
1702 ssid: connection_selection.target.network.ssid.to_vec(),
1703 bss_description: Sequestered::release(connection_selection.target.bss.bss_description),
1704 multiple_bss_candidates: connection_selection.target.network_has_multiple_bss,
1705 authentication: connection_selection.target.authenticator.clone().into(),
1706 deprecated_scan_type: fidl_fuchsia_wlan_common::ScanType::Active,
1707 }
1708 }
1709
1710 #[fuchsia::test]
1711 fn state_machine_sme_connects_successfully() {
1712 let mut exec = fasync::TestExecutor::new();
1713
1714 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1716 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1717 let iface_id = rand::random::<u16>();
1718 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1719
1720 let connect_request = generate_connect_request();
1722 let fut = sme.connect(&connect_request);
1723 let mut fut = pin!(fut);
1724 match exec.run_until_stalled(&mut fut) {
1725 Poll::Pending => {}
1726 _ => panic!("connect request should be pending."),
1727 }
1728
1729 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1731 assert_matches!(
1732 poll_sme_req(&mut exec, &mut sme_fut),
1733 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1734 txn,
1735 ..
1736 }) => {
1737 let (_stream, ctrl) = txn.expect("connect txn unused")
1738 .into_stream_and_control_handle();
1739 ctrl
1740 .send_on_connect_result(&fidl_sme::ConnectResult {
1741 code: fidl_ieee80211::StatusCode::Success,
1742 is_credential_rejected: false,
1743 is_reconnect: false,
1744 })
1745 .expect("failed to send connection completion");
1746 }
1747 );
1748
1749 match exec.run_until_stalled(&mut fut) {
1751 Poll::Ready(Ok((result, txn))) => {
1752 assert_eq!(
1753 result,
1754 fidl_sme::ConnectResult {
1755 code: fidl_ieee80211::StatusCode::Success,
1756 is_credential_rejected: false,
1757 is_reconnect: false,
1758 }
1759 );
1760 drop(txn)
1763 }
1764 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1765 Poll::Pending => panic!("connect request should not be pending."),
1766 }
1767 }
1768
1769 #[fuchsia::test]
1770 fn state_machine_sme_connection_failure() {
1771 let mut exec = fasync::TestExecutor::new();
1772
1773 let (proxy, sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1775 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1776 let iface_id = rand::random::<u16>();
1777 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1778
1779 let connect_request = generate_connect_request();
1781 let fut = sme.connect(&connect_request);
1782 let mut fut = pin!(fut);
1783 match exec.run_until_stalled(&mut fut) {
1784 Poll::Pending => {}
1785 _ => panic!("connect request should be pending."),
1786 }
1787
1788 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1790 assert_matches!(
1791 poll_sme_req(&mut exec, &mut sme_fut),
1792 Poll::Ready(fidl_sme::ClientSmeRequest::Connect{
1793 txn,
1794 ..
1795 }) => {
1796 let (_stream, ctrl) = txn.expect("connect txn unused")
1797 .into_stream_and_control_handle();
1798 ctrl
1799 .send_on_connect_result(&fidl_sme::ConnectResult {
1800 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1801 is_credential_rejected: false,
1802 is_reconnect: false,
1803 })
1804 .expect("failed to send connection completion");
1805 }
1806 );
1807
1808 match exec.run_until_stalled(&mut fut) {
1810 Poll::Ready(Ok((result, txn))) => {
1811 assert_eq!(
1812 result,
1813 fidl_sme::ConnectResult {
1814 code: fidl_ieee80211::StatusCode::RefusedReasonUnspecified,
1815 is_credential_rejected: false,
1816 is_reconnect: false,
1817 }
1818 );
1819 drop(txn)
1822 }
1823 Poll::Ready(Err(_)) => panic!("connection should be successful"),
1824 Poll::Pending => panic!("connect request should not be pending."),
1825 }
1826 }
1827
1828 #[fuchsia::test]
1829 fn state_machine_sme_connect_request_fails() {
1830 let mut exec = fasync::TestExecutor::new();
1831
1832 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1834 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1835 let iface_id = rand::random::<u16>();
1836 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1837
1838 let connect_request = generate_connect_request();
1840 let fut = sme.connect(&connect_request);
1841 let mut fut = pin!(fut);
1842 match exec.run_until_stalled(&mut fut) {
1843 Poll::Ready(Err(_)) => {}
1844 _ => panic!("connect request should have failed."),
1845 }
1846 }
1847
1848 #[fuchsia::test]
1849 fn state_machine_sme_connect_timeout() {
1850 let mut exec = fasync::TestExecutor::new_with_fake_time();
1851 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1852
1853 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ClientSmeMarker>();
1855 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1856 let iface_id = rand::random::<u16>();
1857 let sme = SmeForClientStateMachine::new(proxy, iface_id, defect_sender);
1858
1859 let connect_request = generate_connect_request();
1861 let fut = sme.connect(&connect_request);
1862 let mut fut = pin!(fut);
1863 match exec.run_until_stalled(&mut fut) {
1864 Poll::Pending => {}
1865 _ => panic!("connect future completed unexpectedly"),
1866 }
1867
1868 exec.set_fake_time(fasync::MonotonicInstant::after(
1870 CONNECT_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1871 ));
1872
1873 match exec.run_until_stalled(&mut fut) {
1875 Poll::Ready(Err(_)) => {}
1876 Poll::Ready(Ok(_)) => panic!("connect future completed successfully"),
1877 Poll::Pending => panic!("connect future did not complete"),
1878 }
1879 assert_eq!(
1880 defect_receiver.try_next().expect("missing connection timeout"),
1881 Some(Defect::Iface(IfaceFailure::Timeout {
1882 iface_id,
1883 source: telemetry::TimeoutSource::Connect,
1884 })),
1885 );
1886 }
1887
1888 #[fuchsia::test]
1889 fn wait_for_connect_result_error() {
1890 let mut exec = fasync::TestExecutor::new();
1891 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1892 let mut response_stream = connect_txn.take_event_stream();
1893
1894 let fut = wait_for_connect_result(&mut response_stream);
1895
1896 let mut fut = pin!(fut);
1897 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1898
1899 drop(remote);
1901 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1902 }
1903
1904 #[fuchsia::test]
1905 fn wait_for_connect_result_ignores_other_events() {
1906 let mut exec = fasync::TestExecutor::new();
1907 let (connect_txn, remote) = create_proxy::<fidl_sme::ConnectTransactionMarker>();
1908 let request_handle = remote.into_stream().control_handle();
1909 let mut response_stream = connect_txn.take_event_stream();
1910
1911 let fut = wait_for_connect_result(&mut response_stream);
1912
1913 let mut fut = pin!(fut);
1914 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1915
1916 let ind = fidl_internal::SignalReportIndication { rssi_dbm: -20, snr_db: 25 };
1918 request_handle.send_on_signal_report(&ind).unwrap();
1919
1920 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1922
1923 let sme_result = fidl_sme::ConnectResult {
1925 code: fidl_ieee80211::StatusCode::Success,
1926 is_credential_rejected: false,
1927 is_reconnect: false,
1928 };
1929 request_handle.send_on_connect_result(&sme_result).unwrap();
1930 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(response)) => {
1931 assert_eq!(sme_result, response);
1932 });
1933 }
1934
1935 fn poll_ap_sme_req(
1936 exec: &mut fasync::TestExecutor,
1937 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
1938 ) -> Poll<fidl_sme::ApSmeRequest> {
1939 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
1940 *next_sme_req = stream.into_future();
1941 req.expect("did not expect the SME request stream to end")
1942 .expect("error polling SME request stream")
1943 })
1944 }
1945
1946 #[fuchsia::test]
1947 fn state_machine_sme_starts_ap_successfully() {
1948 let mut exec = fasync::TestExecutor::new();
1949
1950 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
1952 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1953 let iface_id = rand::random::<u16>();
1954 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1955
1956 let config = fidl_sme::ApConfig::from(create_ap_config());
1958 let fut = sme.start(&config);
1959 let mut fut = pin!(fut);
1960 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1961
1962 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1964 assert_matches!(
1965 poll_ap_sme_req(&mut exec, &mut sme_fut),
1966 Poll::Ready(fidl_sme::ApSmeRequest::Start { responder, .. }) => {
1967 responder.send(fidl_sme::StartApResultCode::Success)
1968 .expect("could not send sme response");
1969 }
1970 );
1971
1972 assert_matches!(
1974 exec.run_until_stalled(&mut fut),
1975 Poll::Ready(Ok(fidl_sme::StartApResultCode::Success))
1976 );
1977 }
1978
1979 #[fuchsia::test]
1980 fn state_machine_sme_fails_to_request_start_ap() {
1981 let mut exec = fasync::TestExecutor::new();
1982
1983 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
1985 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1986 let iface_id = rand::random::<u16>();
1987 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1988
1989 let config = fidl_sme::ApConfig::from(create_ap_config());
1991 let fut = sme.start(&config);
1992 let mut fut = pin!(fut);
1993 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1994 }
1995
1996 #[fuchsia::test]
1997 fn state_machine_sme_start_ap_timeout() {
1998 let mut exec = fasync::TestExecutor::new_with_fake_time();
1999 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2000
2001 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2003 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2004 let iface_id = rand::random::<u16>();
2005 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2006
2007 let config = fidl_sme::ApConfig::from(create_ap_config());
2009 let fut = sme.start(&config);
2010 let mut fut = pin!(fut);
2011 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2012
2013 exec.set_fake_time(fasync::MonotonicInstant::after(
2015 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2016 ));
2017
2018 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2020 assert_eq!(
2021 defect_receiver.try_next().expect("missing connection timeout"),
2022 Some(Defect::Iface(IfaceFailure::Timeout {
2023 iface_id,
2024 source: telemetry::TimeoutSource::ApStart,
2025 })),
2026 );
2027 }
2028
2029 #[fuchsia::test]
2030 fn state_machine_sme_stops_ap_successfully() {
2031 let mut exec = fasync::TestExecutor::new();
2032
2033 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2035 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2036 let iface_id = rand::random::<u16>();
2037 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2038
2039 let fut = sme.stop();
2041 let mut fut = pin!(fut);
2042 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2043
2044 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2046 assert_matches!(
2047 poll_ap_sme_req(&mut exec, &mut sme_fut),
2048 Poll::Ready(fidl_sme::ApSmeRequest::Stop { responder }) => {
2049 responder.send(fidl_sme::StopApResultCode::Success)
2050 .expect("could not send sme response");
2051 }
2052 );
2053
2054 assert_matches!(
2056 exec.run_until_stalled(&mut fut),
2057 Poll::Ready(Ok(fidl_sme::StopApResultCode::Success))
2058 );
2059 }
2060
2061 #[fuchsia::test]
2062 fn state_machine_sme_fails_to_request_stop_ap() {
2063 let mut exec = fasync::TestExecutor::new();
2064
2065 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2067 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2068 let iface_id = rand::random::<u16>();
2069 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2070
2071 let fut = sme.stop();
2073 let mut fut = pin!(fut);
2074 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2075 }
2076
2077 #[fuchsia::test]
2078 fn state_machine_sme_stop_ap_timeout() {
2079 let mut exec = fasync::TestExecutor::new_with_fake_time();
2080 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2081
2082 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2084 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2085 let iface_id = rand::random::<u16>();
2086 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2087
2088 let fut = sme.stop();
2090 let mut fut = pin!(fut);
2091 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2092
2093 exec.set_fake_time(fasync::MonotonicInstant::after(
2095 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2096 ));
2097
2098 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2100 assert_eq!(
2101 defect_receiver.try_next().expect("missing connection timeout"),
2102 Some(Defect::Iface(IfaceFailure::Timeout {
2103 iface_id,
2104 source: telemetry::TimeoutSource::ApStop,
2105 })),
2106 );
2107 }
2108
2109 #[fuchsia::test]
2110 fn state_machine_sme_successfully_queries_ap_status() {
2111 let mut exec = fasync::TestExecutor::new();
2112
2113 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2115 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2116 let iface_id = rand::random::<u16>();
2117 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2118
2119 let fut = sme.status();
2121 let mut fut = pin!(fut);
2122 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2123
2124 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2126 assert_matches!(
2127 poll_ap_sme_req(&mut exec, &mut sme_fut),
2128 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
2129 let response = fidl_sme::ApStatusResponse { running_ap: None };
2130 responder.send(&response).expect("could not send AP status response");
2131 }
2132 );
2133
2134 assert_matches!(
2136 exec.run_until_stalled(&mut fut),
2137 Poll::Ready(Ok(fidl_sme::ApStatusResponse { running_ap: None }))
2138 );
2139 }
2140
2141 #[fuchsia::test]
2142 fn state_machine_sme_fails_to_query_ap_status() {
2143 let mut exec = fasync::TestExecutor::new();
2144
2145 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2147 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2148 let iface_id = rand::random::<u16>();
2149 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2150
2151 let fut = sme.status();
2153 let mut fut = pin!(fut);
2154 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2155 }
2156
2157 #[fuchsia::test]
2158 fn state_machine_sme_query_ap_status_timeout() {
2159 let mut exec = fasync::TestExecutor::new_with_fake_time();
2160 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2161
2162 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2164 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2165 let iface_id = rand::random::<u16>();
2166 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2167
2168 let fut = sme.status();
2170 let mut fut = pin!(fut);
2171 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2172
2173 exec.set_fake_time(fasync::MonotonicInstant::after(
2175 AP_STATUS_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2176 ));
2177
2178 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2180 assert_eq!(
2181 defect_receiver.try_next().expect("missing connection timeout"),
2182 Some(Defect::Iface(IfaceFailure::Timeout {
2183 iface_id,
2184 source: telemetry::TimeoutSource::ApStatus,
2185 })),
2186 );
2187 }
2188}