1use crate::access_point::{state_machine as ap_fsm, types as ap_types};
6use crate::client::types as client_types;
7use crate::config_management::network_config::Credential;
8use crate::mode_management::iface_manager_types::*;
9use crate::mode_management::{Defect, IfaceFailure};
10use anyhow::{Error, bail, format_err};
11use async_trait::async_trait;
12use fidl::endpoints::create_proxy;
13use fidl_fuchsia_wlan_sme as fidl_sme;
14use fuchsia_async::TimeoutExt;
15use futures::channel::{mpsc, oneshot};
16use futures::{TryFutureExt, TryStreamExt};
17use log::{info, warn};
18use wlan_telemetry::TimeoutSource;
19
20const SCAN_TIMEOUT: fuchsia_async::MonotonicDuration =
23 fuchsia_async::MonotonicDuration::from_seconds(60);
24const CONNECT_TIMEOUT: fuchsia_async::MonotonicDuration =
25 fuchsia_async::MonotonicDuration::from_seconds(30);
26const DISCONNECT_TIMEOUT: fuchsia_async::MonotonicDuration =
27 fuchsia_async::MonotonicDuration::from_seconds(10);
28const START_AP_TIMEOUT: fuchsia_async::MonotonicDuration =
29 fuchsia_async::MonotonicDuration::from_seconds(30);
30const STOP_AP_TIMEOUT: fuchsia_async::MonotonicDuration =
31 fuchsia_async::MonotonicDuration::from_seconds(10);
32const AP_STATUS_TIMEOUT: fuchsia_async::MonotonicDuration =
33 fuchsia_async::MonotonicDuration::from_seconds(10);
34
35#[async_trait(?Send)]
36pub trait IfaceManagerApi {
37 async fn disconnect(
40 &mut self,
41 network_id: ap_types::NetworkIdentifier,
42 reason: client_types::DisconnectReason,
43 ) -> Result<(), Error>;
44
45 async fn connect(&mut self, connect_req: ConnectAttemptRequest) -> Result<(), Error>;
49
50 async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error>;
52
53 async fn has_idle_client(&mut self) -> Result<bool, Error>;
55
56 async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error>;
59
60 async fn handle_removed_iface(&mut self, iface_id: u16) -> Result<(), Error>;
62
63 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error>;
65
66 async fn stop_client_connections(
69 &mut self,
70 reason: client_types::DisconnectReason,
71 ) -> Result<(), Error>;
72
73 async fn start_client_connections(&mut self) -> Result<(), Error>;
75
76 async fn start_ap(&mut self, config: ap_fsm::ApConfig) -> Result<oneshot::Receiver<()>, Error>;
78
79 async fn stop_ap(&mut self, ssid: Ssid, password: Vec<u8>) -> Result<(), Error>;
81
82 async fn stop_all_aps(&mut self) -> Result<(), Error>;
84
85 async fn set_country(
87 &mut self,
88 country_code: Option<client_types::CountryCode>,
89 ) -> Result<(), Error>;
90}
91
92#[derive(Clone)]
93pub struct IfaceManager {
94 pub sender: mpsc::Sender<IfaceManagerRequest>,
95}
96
97#[async_trait(?Send)]
98impl IfaceManagerApi for IfaceManager {
99 async fn disconnect(
100 &mut self,
101 network_id: ap_types::NetworkIdentifier,
102 reason: client_types::DisconnectReason,
103 ) -> Result<(), Error> {
104 let (responder, receiver) = oneshot::channel();
105 let req = DisconnectRequest { network_id, responder, reason };
106 self.sender.try_send(IfaceManagerRequest::Disconnect(req))?;
107
108 receiver.await?
109 }
110
111 async fn connect(&mut self, connect_req: ConnectAttemptRequest) -> Result<(), Error> {
112 let (responder, receiver) = oneshot::channel();
113 let req = ConnectRequest { request: connect_req, responder };
114 self.sender.try_send(IfaceManagerRequest::Connect(req))?;
115
116 receiver.await?
117 }
118
119 async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error> {
120 let (responder, receiver) = oneshot::channel();
121 let req = RecordIdleIfaceRequest { iface_id, responder };
122 self.sender.try_send(IfaceManagerRequest::RecordIdleIface(req))?;
123 receiver.await?;
124 Ok(())
125 }
126
127 async fn has_idle_client(&mut self) -> Result<bool, Error> {
128 let (responder, receiver) = oneshot::channel();
129 let req = HasIdleIfaceRequest { responder };
130 self.sender.try_send(IfaceManagerRequest::HasIdleIface(req))?;
131 receiver.await.map_err(|e| e.into())
132 }
133
134 async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error> {
135 let (responder, receiver) = oneshot::channel();
136 let req = AddIfaceRequest { iface_id, responder };
137 self.sender.try_send(IfaceManagerRequest::AddIface(req))?;
138 receiver.await?;
139 Ok(())
140 }
141
142 async fn handle_removed_iface(&mut self, iface_id: u16) -> Result<(), Error> {
143 let (responder, receiver) = oneshot::channel();
144 let req = RemoveIfaceRequest { iface_id, responder };
145 self.sender.try_send(IfaceManagerRequest::RemoveIface(req))?;
146 receiver.await?;
147 Ok(())
148 }
149
150 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
151 let (responder, receiver) = oneshot::channel();
152 let req = ScanProxyRequest { responder };
153 self.sender.try_send(IfaceManagerRequest::GetScanProxy(req))?;
154 receiver.await?
155 }
156
157 async fn start_client_connections(&mut self) -> Result<(), Error> {
158 let (responder, receiver) = oneshot::channel();
159 let req = StartClientConnectionsRequest { responder };
160 self.sender.try_send(IfaceManagerRequest::StartClientConnections(req))?;
161 receiver.await?
162 }
163
164 async fn start_ap(&mut self, config: ap_fsm::ApConfig) -> Result<oneshot::Receiver<()>, Error> {
165 let (responder, receiver) = oneshot::channel();
166 let req = StartApRequest { config, responder };
167 self.sender.try_send(IfaceManagerRequest::StartAp(req))?;
168 receiver.await?
169 }
170
171 async fn stop_client_connections(
172 &mut self,
173 reason: client_types::DisconnectReason,
174 ) -> Result<(), Error> {
175 let (responder, receiver) = oneshot::channel();
176 let req = StopClientConnectionsRequest { responder, reason };
177 self.sender.try_send(IfaceManagerRequest::StopClientConnections(req))?;
178 receiver.await?
179 }
180
181 async fn stop_ap(&mut self, ssid: Ssid, password: Vec<u8>) -> Result<(), Error> {
182 let (responder, receiver) = oneshot::channel();
183 let req = StopApRequest { ssid, password, responder };
184 self.sender.try_send(IfaceManagerRequest::StopAp(req))?;
185 receiver.await?
186 }
187
188 async fn stop_all_aps(&mut self) -> Result<(), Error> {
189 let (responder, receiver) = oneshot::channel();
190 let req = StopAllApsRequest { responder };
191 self.sender.try_send(IfaceManagerRequest::StopAllAps(req))?;
192 receiver.await?
193 }
194
195 async fn set_country(
196 &mut self,
197 country_code: Option<client_types::CountryCode>,
198 ) -> Result<(), Error> {
199 let (responder, receiver) = oneshot::channel();
200 let req = SetCountryRequest { country_code, responder };
201 self.sender.try_send(IfaceManagerRequest::SetCountry(req))?;
202 receiver.await?
203 }
204}
205
206trait DefectReporter {
207 fn defect_sender(&self) -> mpsc::Sender<Defect>;
208
209 fn report_defect(&self, defect: Defect) {
210 let mut defect_sender = self.defect_sender();
211 if let Err(e) = defect_sender.try_send(defect) {
212 warn!("Failed to report defect {:?}: {:?}", defect, e)
213 }
214 }
215}
216
217#[derive(Debug)]
218pub struct SmeForScan {
219 proxy: fidl_sme::ClientSmeProxy,
220 iface_id: u16,
221 defect_sender: mpsc::Sender<Defect>,
222}
223
224impl SmeForScan {
225 pub fn new(
226 proxy: fidl_sme::ClientSmeProxy,
227 iface_id: u16,
228 defect_sender: mpsc::Sender<Defect>,
229 ) -> Self {
230 SmeForScan { proxy, iface_id, defect_sender }
231 }
232
233 pub async fn scan(
234 &self,
235 req: &fidl_sme::ScanRequest,
236 ) -> Result<fidl_sme::ClientSmeScanResult, Error> {
237 self.proxy
238 .scan(req)
239 .map_err(|e| format_err!("{:?}", e))
240 .on_timeout(SCAN_TIMEOUT, || {
241 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
242 iface_id: self.iface_id,
243 source: TimeoutSource::Scan,
244 }));
245 Err(format_err!("Timed out waiting on scan response from SME"))
246 })
247 .await
248 }
249
250 pub fn log_aborted_scan_defect(&self) {
251 self.report_defect(Defect::Iface(IfaceFailure::CanceledScan { iface_id: self.iface_id }))
252 }
253
254 pub fn log_failed_scan_defect(&self) {
255 self.report_defect(Defect::Iface(IfaceFailure::FailedScan { iface_id: self.iface_id }))
256 }
257
258 pub fn log_empty_scan_defect(&self) {
259 self.report_defect(Defect::Iface(IfaceFailure::EmptyScanResults {
260 iface_id: self.iface_id,
261 }))
262 }
263}
264
265impl DefectReporter for SmeForScan {
266 fn defect_sender(&self) -> mpsc::Sender<Defect> {
267 self.defect_sender.clone()
268 }
269}
270
271#[derive(Clone, Debug)]
272pub struct SmeForClientStateMachine {
273 proxy: fidl_sme::ClientSmeProxy,
274 iface_id: u16,
275 defect_sender: mpsc::Sender<Defect>,
276}
277
278impl SmeForClientStateMachine {
279 pub fn new(
280 proxy: fidl_sme::ClientSmeProxy,
281 iface_id: u16,
282 defect_sender: mpsc::Sender<Defect>,
283 ) -> Self {
284 Self { proxy, iface_id, defect_sender }
285 }
286
287 pub async fn connect(
288 &self,
289 req: &fidl_sme::ConnectRequest,
290 ) -> Result<(fidl_sme::ConnectResult, fidl_sme::ConnectTransactionEventStream), anyhow::Error>
291 {
292 let (connect_txn, remote) = create_proxy();
293
294 self.proxy
295 .connect(req, Some(remote))
296 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))?;
297
298 let mut stream = connect_txn.take_event_stream();
299 let result = wait_for_connect_result(&mut stream)
300 .on_timeout(CONNECT_TIMEOUT, || {
301 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
302 iface_id: self.iface_id,
303 source: TimeoutSource::Connect,
304 }));
305 Err(format_err!("Timed out waiting for connect result from SME."))
306 })
307 .await?;
308
309 Ok((result, stream))
310 }
311
312 pub async fn disconnect(&self, reason: fidl_sme::UserDisconnectReason) -> Result<(), Error> {
313 self.proxy
314 .disconnect(reason)
315 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
316 .on_timeout(DISCONNECT_TIMEOUT, || {
317 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
318 iface_id: self.iface_id,
319 source: TimeoutSource::Disconnect,
320 }));
321 Err(format_err!("Timed out waiting for disconnect"))
322 })
323 .await
324 }
325
326 pub fn roam(&self, req: &fidl_sme::RoamRequest) -> Result<(), Error> {
327 self.proxy.roam(req).map_err(|e| format_err!("Failed to send roam command: {:}", e))
328 }
329
330 pub fn take_event_stream(&self) -> fidl_sme::ClientSmeEventStream {
331 self.proxy.take_event_stream()
332 }
333
334 pub fn sme_for_scan(&self) -> SmeForScan {
335 SmeForScan {
336 proxy: self.proxy.clone(),
337 iface_id: self.iface_id,
338 defect_sender: self.defect_sender.clone(),
339 }
340 }
341}
342
343impl DefectReporter for SmeForClientStateMachine {
344 fn defect_sender(&self) -> mpsc::Sender<Defect> {
345 self.defect_sender.clone()
346 }
347}
348
349async fn wait_for_connect_result(
351 stream: &mut fidl_sme::ConnectTransactionEventStream,
352) -> Result<fidl_sme::ConnectResult, Error> {
353 loop {
354 let stream_fut = stream.try_next();
355 match stream_fut
356 .await
357 .map_err(|e| format_err!("Failed to receive connect result from sme: {:?}", e))?
358 {
359 Some(fidl_sme::ConnectTransactionEvent::OnConnectResult { result }) => {
360 return Ok(result);
361 }
362 Some(other) => {
363 info!(
364 "Expected ConnectTransactionEvent::OnConnectResult, got {}. Ignoring.",
365 connect_txn_event_name(&other)
366 );
367 }
368 None => {
369 bail!("Server closed the ConnectTransaction channel before sending a response");
370 }
371 };
372 }
373}
374
375fn connect_txn_event_name(event: &fidl_sme::ConnectTransactionEvent) -> &'static str {
376 match event {
377 fidl_sme::ConnectTransactionEvent::OnConnectResult { .. } => "OnConnectResult",
378 fidl_sme::ConnectTransactionEvent::OnRoamResult { .. } => "OnRoamResult",
379 fidl_sme::ConnectTransactionEvent::OnDisconnect { .. } => "OnDisconnect",
380 fidl_sme::ConnectTransactionEvent::OnSignalReport { .. } => "OnSignalReport",
381 fidl_sme::ConnectTransactionEvent::OnRssiThresholdBreached { .. } => {
382 "OnRssiThresholdBreached"
383 }
384 fidl_sme::ConnectTransactionEvent::OnChannelSwitched { .. } => "OnChannelSwitched",
385 }
386}
387
388#[derive(Clone, Debug)]
389pub struct SmeForApStateMachine {
390 proxy: fidl_sme::ApSmeProxy,
391 iface_id: u16,
392 defect_sender: mpsc::Sender<Defect>,
393}
394
395impl SmeForApStateMachine {
396 pub fn new(
397 proxy: fidl_sme::ApSmeProxy,
398 iface_id: u16,
399 defect_sender: mpsc::Sender<Defect>,
400 ) -> Self {
401 Self { proxy, iface_id, defect_sender }
402 }
403
404 pub async fn start(
405 &self,
406 config: &fidl_sme::ApConfig,
407 ) -> Result<fidl_sme::StartApResultCode, Error> {
408 self.proxy
409 .start(config)
410 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
411 .on_timeout(START_AP_TIMEOUT, || {
412 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
413 iface_id: self.iface_id,
414 source: TimeoutSource::ApStart,
415 }));
416 Err(format_err!("Timed out waiting for AP to start"))
417 })
418 .await
419 }
420
421 pub async fn stop(&self) -> Result<fidl_sme::StopApResultCode, Error> {
422 self.proxy
423 .stop()
424 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
425 .on_timeout(STOP_AP_TIMEOUT, || {
426 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
427 iface_id: self.iface_id,
428 source: TimeoutSource::ApStop,
429 }));
430 Err(format_err!("Timed out waiting for AP to stop"))
431 })
432 .await
433 }
434
435 pub async fn status(&self) -> Result<fidl_sme::ApStatusResponse, Error> {
436 self.proxy
437 .status()
438 .map_err(|e| format_err!("Failed to send command to wlanstack: {:?}", e))
439 .on_timeout(AP_STATUS_TIMEOUT, || {
440 self.report_defect(Defect::Iface(IfaceFailure::Timeout {
441 iface_id: self.iface_id,
442 source: TimeoutSource::ApStatus,
443 }));
444 Err(format_err!("Timed out waiting for AP status"))
445 })
446 .await
447 }
448
449 pub fn take_event_stream(&self) -> fidl_sme::ApSmeEventStream {
450 self.proxy.take_event_stream()
451 }
452}
453
454impl DefectReporter for SmeForApStateMachine {
455 fn defect_sender(&self) -> mpsc::Sender<Defect> {
456 self.defect_sender.clone()
457 }
458}
459
460#[cfg_attr(test, derive(Debug))]
462#[derive(Clone, PartialEq)]
463pub struct ConnectAttemptRequest {
464 pub network: client_types::NetworkIdentifier,
465 pub credential: Credential,
466 pub reason: client_types::ConnectReason,
467 pub attempts: u8,
468}
469
470impl ConnectAttemptRequest {
471 pub fn new(
472 network: client_types::NetworkIdentifier,
473 credential: Credential,
474 reason: client_types::ConnectReason,
475 ) -> Self {
476 ConnectAttemptRequest { network, credential, reason, attempts: 0 }
477 }
478}
479
480impl From<client_types::ConnectSelection> for ConnectAttemptRequest {
481 fn from(selection: client_types::ConnectSelection) -> ConnectAttemptRequest {
482 ConnectAttemptRequest::new(
483 selection.target.network,
484 selection.target.credential,
485 selection.reason,
486 )
487 }
488}
489
490#[cfg(test)]
491mod tests {
492 use super::*;
493 use crate::access_point::types;
494 use crate::util::testing::{generate_connect_selection, poll_sme_req};
495 use anyhow::format_err;
496 use assert_matches::assert_matches;
497 use fidl::endpoints::{RequestStream, create_proxy};
498 use fidl_fuchsia_wlan_ieee80211 as fidl_ieee80211;
499 use fidl_fuchsia_wlan_internal as fidl_internal;
500 use fuchsia_async as fasync;
501 use futures::StreamExt;
502 use futures::future::LocalBoxFuture;
503 use futures::stream::StreamFuture;
504 use futures::task::Poll;
505 use std::pin::pin;
506 use test_case::test_case;
507 use wlan_common::channel::Bandwidth;
508 use wlan_common::sequestered::Sequestered;
509 use wlan_common::{RadioConfig, random_fidl_bss_description};
510
511 struct TestValues {
512 exec: fasync::TestExecutor,
513 iface_manager: IfaceManager,
514 receiver: mpsc::Receiver<IfaceManagerRequest>,
515 }
516
517 fn test_setup() -> TestValues {
518 let exec = fasync::TestExecutor::new();
519 let (sender, receiver) = mpsc::channel(1);
520 TestValues { exec, iface_manager: IfaceManager { sender }, receiver }
521 }
522
523 #[allow(clippy::enum_variant_names, reason = "mass allow for https://fxbug.dev/381896734")]
524 #[derive(Clone)]
525 enum NegativeTestFailureMode {
526 RequestFailure,
527 OperationFailure,
528 ServiceFailure,
529 }
530
531 fn handle_negative_test_result_responder<T: std::fmt::Debug>(
532 responder: oneshot::Sender<Result<T, Error>>,
533 failure_mode: NegativeTestFailureMode,
534 ) {
535 match failure_mode {
536 NegativeTestFailureMode::RequestFailure => {
537 panic!("Test bug: this request should have been handled previously")
538 }
539 NegativeTestFailureMode::OperationFailure => {
540 responder
541 .send(Err(format_err!("operation failed")))
542 .expect("failed to send response");
543 }
544 NegativeTestFailureMode::ServiceFailure => {
545 drop(responder);
547 }
548 }
549 }
550
551 fn handle_negative_test_responder<T: std::fmt::Debug>(
552 responder: oneshot::Sender<T>,
553 failure_mode: NegativeTestFailureMode,
554 ) {
555 match failure_mode {
556 NegativeTestFailureMode::RequestFailure | NegativeTestFailureMode::OperationFailure => {
557 panic!("Test bug: invalid operation")
558 }
559 NegativeTestFailureMode::ServiceFailure => {
560 drop(responder);
562 }
563 }
564 }
565
566 fn iface_manager_api_negative_test(
567 mut receiver: mpsc::Receiver<IfaceManagerRequest>,
568 failure_mode: NegativeTestFailureMode,
569 ) -> LocalBoxFuture<'static, ()> {
570 if let NegativeTestFailureMode::RequestFailure = failure_mode {
571 drop(receiver);
573 let fut = async move {};
574 return Box::pin(fut);
575 }
576
577 let fut = async move {
578 let req = match receiver.next().await {
579 Some(req) => req,
580 None => panic!("no request available."),
581 };
582
583 match req {
584 IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest {
586 responder,
587 ..
588 })
589 | IfaceManagerRequest::Disconnect(DisconnectRequest { responder, .. })
590 | IfaceManagerRequest::StopAp(StopApRequest { responder, .. })
591 | IfaceManagerRequest::StopAllAps(StopAllApsRequest { responder, .. })
592 | IfaceManagerRequest::SetCountry(SetCountryRequest { responder, .. })
593 | IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest {
594 responder,
595 })
596 | IfaceManagerRequest::Connect(ConnectRequest { responder, .. }) => {
597 handle_negative_test_result_responder(responder, failure_mode);
598 }
599 IfaceManagerRequest::GetScanProxy(ScanProxyRequest { responder }) => {
601 handle_negative_test_result_responder(responder, failure_mode);
602 }
603 IfaceManagerRequest::StartAp(StartApRequest { responder, .. }) => {
605 handle_negative_test_result_responder(responder, failure_mode);
606 }
607 IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest {
609 responder, ..
610 })
611 | IfaceManagerRequest::AddIface(AddIfaceRequest { responder, .. })
612 | IfaceManagerRequest::RemoveIface(RemoveIfaceRequest { responder, .. }) => {
613 handle_negative_test_responder(responder, failure_mode);
614 }
615 IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest { responder }) => {
617 handle_negative_test_responder(responder, failure_mode);
618 }
619 }
620 };
621 Box::pin(fut)
622 }
623
624 #[fuchsia::test]
625 fn test_disconnect_succeeds() {
626 let mut test_values = test_setup();
627
628 let req = ap_types::NetworkIdentifier {
630 ssid: Ssid::try_from("foo").unwrap(),
631 security_type: ap_types::SecurityType::None,
632 };
633 let req_reason = client_types::DisconnectReason::NetworkUnsaved;
634 let disconnect_fut = test_values.iface_manager.disconnect(req.clone(), req_reason);
635 let mut disconnect_fut = pin!(disconnect_fut);
636
637 assert_matches!(test_values.exec.run_until_stalled(&mut disconnect_fut), Poll::Pending);
638
639 let next_message = test_values.receiver.next();
641 let mut next_message = pin!(next_message);
642
643 assert_matches!(
644 test_values.exec.run_until_stalled(&mut next_message),
645 Poll::Ready(Some(IfaceManagerRequest::Disconnect(DisconnectRequest {
646 network_id, responder, reason
647 }))) => {
648 assert_eq!(network_id, req);
649 assert_eq!(reason, req_reason);
650 responder.send(Ok(())).expect("failed to send disconnect response");
651 }
652 );
653
654 assert_matches!(
656 test_values.exec.run_until_stalled(&mut disconnect_fut),
657 Poll::Ready(Ok(()))
658 );
659 }
660
661 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
662 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
663 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
664 #[fuchsia::test(add_test_attr = false)]
665 fn disconnect_negative_test(failure_mode: NegativeTestFailureMode) {
666 let mut test_values = test_setup();
667
668 let req = ap_types::NetworkIdentifier {
670 ssid: Ssid::try_from("foo").unwrap(),
671 security_type: ap_types::SecurityType::None,
672 };
673 let disconnect_fut = test_values
674 .iface_manager
675 .disconnect(req.clone(), client_types::DisconnectReason::NetworkUnsaved);
676 let mut disconnect_fut = pin!(disconnect_fut);
677
678 let service_fut =
679 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
680 let mut service_fut = pin!(service_fut);
681
682 match failure_mode {
683 NegativeTestFailureMode::RequestFailure => {}
684 _ => {
685 assert_matches!(
687 test_values.exec.run_until_stalled(&mut disconnect_fut),
688 Poll::Pending
689 );
690 assert_matches!(
691 test_values.exec.run_until_stalled(&mut service_fut),
692 Poll::Ready(())
693 );
694 }
695 }
696
697 assert_matches!(
699 test_values.exec.run_until_stalled(&mut disconnect_fut),
700 Poll::Ready(Err(_))
701 );
702 }
703
704 #[fuchsia::test]
705 fn test_connect_succeeds() {
706 let mut test_values = test_setup();
707
708 let req = ConnectAttemptRequest::new(
710 client_types::NetworkIdentifier {
711 ssid: Ssid::try_from("foo").unwrap(),
712 security_type: client_types::SecurityType::None,
713 },
714 Credential::None,
715 client_types::ConnectReason::FidlConnectRequest,
716 );
717 let connect_fut = test_values.iface_manager.connect(req.clone());
718 let mut connect_fut = pin!(connect_fut);
719
720 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Pending);
721
722 let next_message = test_values.receiver.next();
724 let mut next_message = pin!(next_message);
725
726 assert_matches!(
727 test_values.exec.run_until_stalled(&mut next_message),
728 Poll::Ready(Some(IfaceManagerRequest::Connect(ConnectRequest {
729 request, responder
730 }))) => {
731 assert_eq!(request, req);
732 responder.send(Ok(())).expect("failed to send connect response");
733 }
734 );
735
736 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Ok(_)));
738 }
739
740 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
741 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
742 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
743 #[fuchsia::test(add_test_attr = false)]
744 fn connect_negative_test(failure_mode: NegativeTestFailureMode) {
745 let mut test_values = test_setup();
746
747 let req = ConnectAttemptRequest::new(
749 client_types::NetworkIdentifier {
750 ssid: Ssid::try_from("foo").unwrap(),
751 security_type: client_types::SecurityType::None,
752 },
753 Credential::None,
754 client_types::ConnectReason::FidlConnectRequest,
755 );
756 let connect_fut = test_values.iface_manager.connect(req.clone());
757 let mut connect_fut = pin!(connect_fut);
758
759 let service_fut =
760 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
761 let mut service_fut = pin!(service_fut);
762
763 match failure_mode {
764 NegativeTestFailureMode::RequestFailure => {}
765 _ => {
766 assert_matches!(
768 test_values.exec.run_until_stalled(&mut connect_fut),
769 Poll::Pending
770 );
771 assert_matches!(
772 test_values.exec.run_until_stalled(&mut service_fut),
773 Poll::Ready(())
774 );
775 }
776 }
777
778 assert_matches!(test_values.exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
780 }
781
782 #[fuchsia::test]
783 fn test_record_idle_client_succeeds() {
784 let mut test_values = test_setup();
785
786 let iface_id = 123;
788 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
789 let mut idle_client_fut = pin!(idle_client_fut);
790
791 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
792
793 let next_message = test_values.receiver.next();
795 let mut next_message = pin!(next_message);
796
797 assert_matches!(
798 test_values.exec.run_until_stalled(&mut next_message),
799 Poll::Ready(
800 Some(IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest{ iface_id: 123, responder}))
801 ) => {
802 responder.send(()).expect("failed to send idle iface response");
803 }
804 );
805
806 assert_matches!(
808 test_values.exec.run_until_stalled(&mut idle_client_fut),
809 Poll::Ready(Ok(()))
810 );
811 }
812
813 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
814 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
815 #[fuchsia::test(add_test_attr = false)]
816 fn test_record_idle_client_service_failure(failure_mode: NegativeTestFailureMode) {
817 let mut test_values = test_setup();
818
819 let iface_id = 123;
821 let idle_client_fut = test_values.iface_manager.record_idle_client(iface_id);
822 let mut idle_client_fut = pin!(idle_client_fut);
823
824 let service_fut =
825 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
826 let mut service_fut = pin!(service_fut);
827
828 match failure_mode {
829 NegativeTestFailureMode::RequestFailure => {}
830 _ => {
831 assert_matches!(
833 test_values.exec.run_until_stalled(&mut idle_client_fut),
834 Poll::Pending
835 );
836 assert_matches!(
837 test_values.exec.run_until_stalled(&mut service_fut),
838 Poll::Ready(())
839 );
840 }
841 }
842
843 assert_matches!(
845 test_values.exec.run_until_stalled(&mut idle_client_fut),
846 Poll::Ready(Err(_))
847 );
848 }
849
850 #[fuchsia::test]
851 fn test_has_idle_client_success() {
852 let mut test_values = test_setup();
853
854 let idle_client_fut = test_values.iface_manager.has_idle_client();
856 let mut idle_client_fut = pin!(idle_client_fut);
857 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
858
859 let next_message = test_values.receiver.next();
861 let mut next_message = pin!(next_message);
862
863 assert_matches!(
864 test_values.exec.run_until_stalled(&mut next_message),
865 Poll::Ready(
866 Some(IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest{ responder}))
867 ) => responder.send(true).expect("failed to reply to idle client query")
868 );
869
870 assert_matches!(
872 test_values.exec.run_until_stalled(&mut idle_client_fut),
873 Poll::Ready(Ok(true))
874 );
875 }
876
877 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
878 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
879 #[fuchsia::test(add_test_attr = false)]
880 fn idle_client_negative_test(failure_mode: NegativeTestFailureMode) {
881 let mut test_values = test_setup();
882
883 let idle_client_fut = test_values.iface_manager.has_idle_client();
885 let mut idle_client_fut = pin!(idle_client_fut);
886 assert_matches!(test_values.exec.run_until_stalled(&mut idle_client_fut), Poll::Pending);
887
888 let service_fut =
889 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
890 let mut service_fut = pin!(service_fut);
891
892 match failure_mode {
893 NegativeTestFailureMode::RequestFailure => {}
894 _ => {
895 assert_matches!(
897 test_values.exec.run_until_stalled(&mut idle_client_fut),
898 Poll::Pending
899 );
900 assert_matches!(
901 test_values.exec.run_until_stalled(&mut service_fut),
902 Poll::Ready(())
903 );
904 }
905 }
906
907 assert_matches!(
909 test_values.exec.run_until_stalled(&mut idle_client_fut),
910 Poll::Ready(Err(_))
911 );
912 }
913
914 #[fuchsia::test]
915 fn test_add_iface_success() {
916 let mut test_values = test_setup();
917
918 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
920 let mut added_iface_fut = pin!(added_iface_fut);
921 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
922
923 let next_message = test_values.receiver.next();
925 let mut next_message = pin!(next_message);
926
927 assert_matches!(
928 test_values.exec.run_until_stalled(&mut next_message),
929 Poll::Ready(
930 Some(IfaceManagerRequest::AddIface(AddIfaceRequest{ iface_id: 123, responder }))
931 ) => {
932 responder.send(()).expect("failed to respond while adding iface");
933 }
934 );
935
936 assert_matches!(
938 test_values.exec.run_until_stalled(&mut added_iface_fut),
939 Poll::Ready(Ok(()))
940 );
941 }
942
943 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
944 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
945 #[fuchsia::test(add_test_attr = false)]
946 fn add_iface_negative_test(failure_mode: NegativeTestFailureMode) {
947 let mut test_values = test_setup();
948
949 let added_iface_fut = test_values.iface_manager.handle_added_iface(123);
951 let mut added_iface_fut = pin!(added_iface_fut);
952 assert_matches!(test_values.exec.run_until_stalled(&mut added_iface_fut), Poll::Pending);
953
954 let service_fut =
955 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
956 let mut service_fut = pin!(service_fut);
957
958 match failure_mode {
959 NegativeTestFailureMode::RequestFailure => {}
960 _ => {
961 assert_matches!(
963 test_values.exec.run_until_stalled(&mut added_iface_fut),
964 Poll::Pending
965 );
966 assert_matches!(
967 test_values.exec.run_until_stalled(&mut service_fut),
968 Poll::Ready(())
969 );
970 }
971 }
972
973 assert_matches!(
975 test_values.exec.run_until_stalled(&mut added_iface_fut),
976 Poll::Ready(Err(_))
977 );
978 }
979
980 #[fuchsia::test]
981 fn test_remove_iface_success() {
982 let mut test_values = test_setup();
983
984 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
986 let mut removed_iface_fut = pin!(removed_iface_fut);
987 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
988
989 let next_message = test_values.receiver.next();
991 let mut next_message = pin!(next_message);
992
993 assert_matches!(
994 test_values.exec.run_until_stalled(&mut next_message),
995 Poll::Ready(
996 Some(IfaceManagerRequest::RemoveIface(RemoveIfaceRequest{ iface_id: 123, responder }))
997 ) => {
998 responder.send(()).expect("failed to respond while adding iface");
999 }
1000 );
1001
1002 assert_matches!(
1004 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1005 Poll::Ready(Ok(()))
1006 );
1007 }
1008
1009 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1010 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1011 #[fuchsia::test(add_test_attr = false)]
1012 fn remove_iface_negative_test(failure_mode: NegativeTestFailureMode) {
1013 let mut test_values = test_setup();
1014
1015 let removed_iface_fut = test_values.iface_manager.handle_removed_iface(123);
1017 let mut removed_iface_fut = pin!(removed_iface_fut);
1018 assert_matches!(test_values.exec.run_until_stalled(&mut removed_iface_fut), Poll::Pending);
1019
1020 let service_fut =
1021 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1022 let mut service_fut = pin!(service_fut);
1023
1024 match failure_mode {
1025 NegativeTestFailureMode::RequestFailure => {}
1026 _ => {
1027 assert_matches!(
1029 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1030 Poll::Pending
1031 );
1032 assert_matches!(
1033 test_values.exec.run_until_stalled(&mut service_fut),
1034 Poll::Ready(())
1035 );
1036 }
1037 }
1038
1039 assert_matches!(
1041 test_values.exec.run_until_stalled(&mut removed_iface_fut),
1042 Poll::Ready(Err(_))
1043 );
1044 }
1045
1046 #[fuchsia::test]
1047 fn test_get_scan_proxy_success() {
1048 let mut test_values = test_setup();
1049
1050 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1052 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1053 assert_matches!(test_values.exec.run_until_stalled(&mut scan_proxy_fut), Poll::Pending);
1054
1055 let next_message = test_values.receiver.next();
1057 let mut next_message = pin!(next_message);
1058
1059 assert_matches!(
1060 test_values.exec.run_until_stalled(&mut next_message),
1061 Poll::Ready(Some(IfaceManagerRequest::GetScanProxy(ScanProxyRequest{
1062 responder
1063 }))) => {
1064 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1065 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1066 responder.send(Ok(SmeForScan{proxy, iface_id: 0, defect_sender})).expect("failed to send scan sme proxy");
1067 }
1068 );
1069
1070 assert_matches!(
1072 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1073 Poll::Ready(Ok(_))
1074 );
1075 }
1076
1077 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1078 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1079 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1080 #[fuchsia::test(add_test_attr = false)]
1081 fn scan_proxy_negative_test(failure_mode: NegativeTestFailureMode) {
1082 let mut test_values = test_setup();
1083
1084 let scan_proxy_fut = test_values.iface_manager.get_sme_proxy_for_scan();
1086 let mut scan_proxy_fut = pin!(scan_proxy_fut);
1087
1088 let service_fut =
1089 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1090 let mut service_fut = pin!(service_fut);
1091
1092 match failure_mode {
1093 NegativeTestFailureMode::RequestFailure => {}
1094 _ => {
1095 assert_matches!(
1097 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1098 Poll::Pending
1099 );
1100 assert_matches!(
1101 test_values.exec.run_until_stalled(&mut service_fut),
1102 Poll::Ready(())
1103 );
1104 }
1105 }
1106
1107 assert_matches!(
1109 test_values.exec.run_until_stalled(&mut scan_proxy_fut),
1110 Poll::Ready(Err(_))
1111 );
1112 }
1113
1114 #[fuchsia::test]
1115 fn test_stop_client_connections_succeeds() {
1116 let mut test_values = test_setup();
1117
1118 let stop_fut = test_values.iface_manager.stop_client_connections(
1120 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1121 );
1122 let mut stop_fut = pin!(stop_fut);
1123 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1124
1125 let next_message = test_values.receiver.next();
1127 let mut next_message = pin!(next_message);
1128
1129 assert_matches!(
1130 test_values.exec.run_until_stalled(&mut next_message),
1131 Poll::Ready(Some(IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest{
1132 responder, reason
1133 }))) => {
1134 assert_eq!(reason, client_types::DisconnectReason::FidlStopClientConnectionsRequest);
1135 responder.send(Ok(())).expect("failed sending stop client connections response");
1136 }
1137 );
1138
1139 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(())));
1141 }
1142
1143 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1144 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1145 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1146 #[fuchsia::test(add_test_attr = false)]
1147 fn stop_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1148 let mut test_values = test_setup();
1149
1150 let stop_fut = test_values.iface_manager.stop_client_connections(
1152 client_types::DisconnectReason::FidlStopClientConnectionsRequest,
1153 );
1154 let mut stop_fut = pin!(stop_fut);
1155 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1156
1157 let service_fut =
1158 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1159 let mut service_fut = pin!(service_fut);
1160
1161 match failure_mode {
1162 NegativeTestFailureMode::RequestFailure => {}
1163 _ => {
1164 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1166 assert_matches!(
1167 test_values.exec.run_until_stalled(&mut service_fut),
1168 Poll::Ready(())
1169 );
1170 }
1171 }
1172
1173 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1175 }
1176
1177 #[fuchsia::test]
1178 fn test_start_client_connections_succeeds() {
1179 let mut test_values = test_setup();
1180
1181 let start_fut = test_values.iface_manager.start_client_connections();
1183 let mut start_fut = pin!(start_fut);
1184 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1185
1186 let next_message = test_values.receiver.next();
1188 let mut next_message = pin!(next_message);
1189
1190 assert_matches!(
1191 test_values.exec.run_until_stalled(&mut next_message),
1192 Poll::Ready(Some(IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest{
1193 responder
1194 }))) => {
1195 responder.send(Ok(())).expect("failed sending stop client connections response");
1196 }
1197 );
1198
1199 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(())));
1201 }
1202
1203 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1204 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1205 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1206 #[fuchsia::test(add_test_attr = false)]
1207 fn start_client_connections_negative_test(failure_mode: NegativeTestFailureMode) {
1208 let mut test_values = test_setup();
1209
1210 let start_fut = test_values.iface_manager.start_client_connections();
1212 let mut start_fut = pin!(start_fut);
1213 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1214
1215 let service_fut =
1216 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1217 let mut service_fut = pin!(service_fut);
1218
1219 match failure_mode {
1220 NegativeTestFailureMode::RequestFailure => {}
1221 _ => {
1222 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1224 assert_matches!(
1225 test_values.exec.run_until_stalled(&mut service_fut),
1226 Poll::Ready(())
1227 );
1228 }
1229 }
1230
1231 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1233 }
1234
1235 fn create_ap_config() -> ap_fsm::ApConfig {
1236 ap_fsm::ApConfig {
1237 id: types::NetworkIdentifier {
1238 ssid: Ssid::try_from("foo").unwrap(),
1239 security_type: types::SecurityType::None,
1240 },
1241 credential: vec![],
1242 radio_config: RadioConfig::new(
1243 fidl_fuchsia_wlan_ieee80211::WlanPhyType::Ht,
1244 Bandwidth::Cbw20,
1245 6,
1246 fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz,
1247 ),
1248 mode: types::ConnectivityMode::Unrestricted,
1249 band: types::OperatingBand::Any,
1250 }
1251 }
1252
1253 #[fuchsia::test]
1254 fn test_start_ap_succeeds() {
1255 let mut test_values = test_setup();
1256
1257 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1259 let mut start_fut = pin!(start_fut);
1260 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1261
1262 let next_message = test_values.receiver.next();
1264 let mut next_message = pin!(next_message);
1265
1266 assert_matches!(
1267 test_values.exec.run_until_stalled(&mut next_message),
1268 Poll::Ready(Some(IfaceManagerRequest::StartAp(StartApRequest{
1269 config, responder
1270 }))) => {
1271 assert_eq!(config, create_ap_config());
1272
1273 let (_, receiver) = oneshot::channel();
1274 responder.send(Ok(receiver)).expect("failed to send start AP response");
1275 }
1276 );
1277
1278 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
1280 }
1281
1282 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1283 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1284 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1285 #[fuchsia::test(add_test_attr = false)]
1286 fn start_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1287 let mut test_values = test_setup();
1288
1289 let start_fut = test_values.iface_manager.start_ap(create_ap_config());
1291 let mut start_fut = pin!(start_fut);
1292 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1293
1294 let service_fut =
1295 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1296 let mut service_fut = pin!(service_fut);
1297
1298 match failure_mode {
1299 NegativeTestFailureMode::RequestFailure => {}
1300 _ => {
1301 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Pending);
1303 assert_matches!(
1304 test_values.exec.run_until_stalled(&mut service_fut),
1305 Poll::Ready(())
1306 );
1307 }
1308 }
1309
1310 assert_matches!(test_values.exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
1312 }
1313
1314 #[fuchsia::test]
1315 fn test_stop_ap_succeeds() {
1316 let mut test_values = test_setup();
1317
1318 let stop_fut = test_values
1320 .iface_manager
1321 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1322 let mut stop_fut = pin!(stop_fut);
1323 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1324
1325 let next_message = test_values.receiver.next();
1327 let mut next_message = pin!(next_message);
1328
1329 assert_matches!(
1330 test_values.exec.run_until_stalled(&mut next_message),
1331 Poll::Ready(Some(IfaceManagerRequest::StopAp(StopApRequest{
1332 ssid, password, responder
1333 }))) => {
1334 assert_eq!(ssid, Ssid::try_from("foo").unwrap());
1335 assert_eq!(password, "bar".as_bytes().to_vec());
1336
1337 responder.send(Ok(())).expect("failed to send stop AP response");
1338 }
1339 );
1340
1341 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1343 }
1344
1345 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1346 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1347 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1348 #[fuchsia::test(add_test_attr = false)]
1349 fn stop_ap_negative_test(failure_mode: NegativeTestFailureMode) {
1350 let mut test_values = test_setup();
1351
1352 let stop_fut = test_values
1354 .iface_manager
1355 .stop_ap(Ssid::try_from("foo").unwrap(), "bar".as_bytes().to_vec());
1356 let mut stop_fut = pin!(stop_fut);
1357 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1358
1359 let service_fut =
1360 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1361 let mut service_fut = pin!(service_fut);
1362
1363 match failure_mode {
1364 NegativeTestFailureMode::RequestFailure => {}
1365 _ => {
1366 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1368 assert_matches!(
1369 test_values.exec.run_until_stalled(&mut service_fut),
1370 Poll::Ready(())
1371 );
1372 }
1373 }
1374
1375 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1377 }
1378
1379 #[fuchsia::test]
1380 fn test_stop_all_aps_succeeds() {
1381 let mut test_values = test_setup();
1382
1383 let stop_fut = test_values.iface_manager.stop_all_aps();
1385 let mut stop_fut = pin!(stop_fut);
1386 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1387
1388 let next_message = test_values.receiver.next();
1390 let mut next_message = pin!(next_message);
1391 assert_matches!(
1392 test_values.exec.run_until_stalled(&mut next_message),
1393 Poll::Ready(Some(IfaceManagerRequest::StopAllAps(StopAllApsRequest{
1394 responder
1395 }))) => {
1396 responder.send(Ok(())).expect("failed to send stop AP response");
1397 }
1398 );
1399
1400 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
1402 }
1403
1404 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1405 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1406 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1407 #[fuchsia::test(add_test_attr = false)]
1408 fn stop_all_aps_negative_test(failure_mode: NegativeTestFailureMode) {
1409 let mut test_values = test_setup();
1410
1411 let stop_fut = test_values.iface_manager.stop_all_aps();
1413 let mut stop_fut = pin!(stop_fut);
1414 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1415
1416 let service_fut =
1417 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1418 let mut service_fut = pin!(service_fut);
1419
1420 match failure_mode {
1421 NegativeTestFailureMode::RequestFailure => {}
1422 _ => {
1423 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Pending);
1425 assert_matches!(
1426 test_values.exec.run_until_stalled(&mut service_fut),
1427 Poll::Ready(())
1428 );
1429 }
1430 }
1431
1432 assert_matches!(test_values.exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
1434 }
1435
1436 #[fuchsia::test]
1437 fn test_set_country_succeeds() {
1438 let mut test_values = test_setup();
1439
1440 let set_country_fut = test_values.iface_manager.set_country(None);
1442 let mut set_country_fut = pin!(set_country_fut);
1443 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1444
1445 let next_message = test_values.receiver.next();
1447 let mut next_message = pin!(next_message);
1448
1449 assert_matches!(
1450 test_values.exec.run_until_stalled(&mut next_message),
1451 Poll::Ready(Some(IfaceManagerRequest::SetCountry(SetCountryRequest{
1452 country_code: None,
1453 responder
1454 }))) => {
1455 responder.send(Ok(())).expect("failed to send stop AP response");
1456 }
1457 );
1458
1459 assert_matches!(
1461 test_values.exec.run_until_stalled(&mut set_country_fut),
1462 Poll::Ready(Ok(_))
1463 );
1464 }
1465
1466 #[test_case(NegativeTestFailureMode::RequestFailure; "request failure")]
1467 #[test_case(NegativeTestFailureMode::OperationFailure; "operation failure")]
1468 #[test_case(NegativeTestFailureMode::ServiceFailure; "service failure")]
1469 #[fuchsia::test(add_test_attr = false)]
1470 fn set_country_negative_test(failure_mode: NegativeTestFailureMode) {
1471 let mut test_values = test_setup();
1472
1473 let set_country_fut = test_values.iface_manager.set_country(None);
1475 let mut set_country_fut = pin!(set_country_fut);
1476 assert_matches!(test_values.exec.run_until_stalled(&mut set_country_fut), Poll::Pending);
1477 let service_fut =
1478 iface_manager_api_negative_test(test_values.receiver, failure_mode.clone());
1479 let mut service_fut = pin!(service_fut);
1480
1481 match failure_mode {
1482 NegativeTestFailureMode::RequestFailure => {}
1483 _ => {
1484 assert_matches!(
1486 test_values.exec.run_until_stalled(&mut set_country_fut),
1487 Poll::Pending
1488 );
1489 assert_matches!(
1490 test_values.exec.run_until_stalled(&mut service_fut),
1491 Poll::Ready(())
1492 );
1493 }
1494 }
1495
1496 assert_matches!(
1498 test_values.exec.run_until_stalled(&mut set_country_fut),
1499 Poll::Ready(Err(_))
1500 );
1501 }
1502
1503 #[fuchsia::test]
1504 fn test_sme_for_scan() {
1505 let mut exec = fasync::TestExecutor::new();
1506
1507 let (proxy, server_end) = create_proxy::<fidl_sme::ClientSmeMarker>();
1509 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1510 let sme = SmeForScan::new(proxy, 0, defect_sender);
1511 let mut sme_stream = server_end.into_stream();
1512
1513 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1515 ssids: vec![vec![]],
1516 channels: vec![],
1517 });
1518
1519 let scan_result_fut = sme.scan(&scan_request);
1521 let mut scan_result_fut = pin!(scan_result_fut);
1522 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1523
1524 assert_matches!(
1526 exec.run_until_stalled(&mut sme_stream.next()),
1527 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1528 req, ..
1529 }))) => {
1530 assert_eq!(scan_request, req)
1531 }
1532 );
1533 }
1534
1535 #[fuchsia::test]
1536 fn sme_for_scan_defects() {
1537 let _exec = fasync::TestExecutor::new();
1538
1539 let (proxy, _) = create_proxy::<fidl_sme::ClientSmeMarker>();
1541 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1542 let iface_id = rand::random::<u16>();
1543 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1544
1545 sme.log_aborted_scan_defect();
1546 sme.log_failed_scan_defect();
1547 sme.log_empty_scan_defect();
1548
1549 assert_eq!(
1550 defect_receiver.try_recv().ok(),
1551 Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id })),
1552 );
1553 assert_eq!(
1554 defect_receiver.try_recv().ok(),
1555 Some(Defect::Iface(IfaceFailure::FailedScan { iface_id })),
1556 );
1557 assert_eq!(
1558 defect_receiver.try_recv().ok(),
1559 Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id })),
1560 );
1561 }
1562
1563 #[fuchsia::test]
1564 fn sme_for_scan_timeout() {
1565 let mut exec = fasync::TestExecutor::new_with_fake_time();
1566 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
1567
1568 let (proxy, _server) = create_proxy::<fidl_sme::ClientSmeMarker>();
1570 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
1571 let iface_id = rand::random::<u16>();
1572 let sme = SmeForScan::new(proxy, iface_id, defect_sender);
1573
1574 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
1576 ssids: vec![vec![]],
1577 channels: vec![],
1578 });
1579 let scan_result_fut = sme.scan(&scan_request);
1580 let mut scan_result_fut = pin!(scan_result_fut);
1581 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Pending);
1582
1583 exec.set_fake_time(fasync::MonotonicInstant::after(
1585 SCAN_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
1586 ));
1587
1588 assert_matches!(exec.run_until_stalled(&mut scan_result_fut), Poll::Ready(Err(_)));
1590 assert_eq!(
1591 defect_receiver.try_recv().ok(),
1592 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Scan })),
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_recv().ok(),
1668 Some(Defect::Iface(IfaceFailure::Timeout {
1669 iface_id,
1670 source: 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_recv().ok(),
1884 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::Connect })),
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 {
1918 rssi_dbm: Some(-20),
1919 snr_db: Some(25),
1920 tx_rate_500kbps: Some(0),
1921 ..Default::default()
1922 };
1923 request_handle.send_on_signal_report(&ind).unwrap();
1924
1925 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1927
1928 let sme_result = fidl_sme::ConnectResult {
1930 code: fidl_ieee80211::StatusCode::Success,
1931 is_credential_rejected: false,
1932 is_reconnect: false,
1933 };
1934 request_handle.send_on_connect_result(&sme_result).unwrap();
1935 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(response)) => {
1936 assert_eq!(sme_result, response);
1937 });
1938 }
1939
1940 fn poll_ap_sme_req(
1941 exec: &mut fasync::TestExecutor,
1942 next_sme_req: &mut StreamFuture<fidl_sme::ApSmeRequestStream>,
1943 ) -> Poll<fidl_sme::ApSmeRequest> {
1944 exec.run_until_stalled(next_sme_req).map(|(req, stream)| {
1945 *next_sme_req = stream.into_future();
1946 req.expect("did not expect the SME request stream to end")
1947 .expect("error polling SME request stream")
1948 })
1949 }
1950
1951 #[fuchsia::test]
1952 fn state_machine_sme_starts_ap_successfully() {
1953 let mut exec = fasync::TestExecutor::new();
1954
1955 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
1957 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1958 let iface_id = rand::random::<u16>();
1959 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1960
1961 let config = fidl_sme::ApConfig::from(create_ap_config());
1963 let fut = sme.start(&config);
1964 let mut fut = pin!(fut);
1965 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1966
1967 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
1969 assert_matches!(
1970 poll_ap_sme_req(&mut exec, &mut sme_fut),
1971 Poll::Ready(fidl_sme::ApSmeRequest::Start { responder, .. }) => {
1972 responder.send(fidl_sme::StartApResultCode::Success)
1973 .expect("could not send sme response");
1974 }
1975 );
1976
1977 assert_matches!(
1979 exec.run_until_stalled(&mut fut),
1980 Poll::Ready(Ok(fidl_sme::StartApResultCode::Success))
1981 );
1982 }
1983
1984 #[fuchsia::test]
1985 fn state_machine_sme_fails_to_request_start_ap() {
1986 let mut exec = fasync::TestExecutor::new();
1987
1988 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
1990 let (defect_sender, _defect_receiver) = mpsc::channel(100);
1991 let iface_id = rand::random::<u16>();
1992 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
1993
1994 let config = fidl_sme::ApConfig::from(create_ap_config());
1996 let fut = sme.start(&config);
1997 let mut fut = pin!(fut);
1998 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1999 }
2000
2001 #[fuchsia::test]
2002 fn state_machine_sme_start_ap_timeout() {
2003 let mut exec = fasync::TestExecutor::new_with_fake_time();
2004 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2005
2006 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2008 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2009 let iface_id = rand::random::<u16>();
2010 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2011
2012 let config = fidl_sme::ApConfig::from(create_ap_config());
2014 let fut = sme.start(&config);
2015 let mut fut = pin!(fut);
2016 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2017
2018 exec.set_fake_time(fasync::MonotonicInstant::after(
2020 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2021 ));
2022
2023 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2025 assert_eq!(
2026 defect_receiver.try_recv().ok(),
2027 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::ApStart })),
2028 );
2029 }
2030
2031 #[fuchsia::test]
2032 fn state_machine_sme_stops_ap_successfully() {
2033 let mut exec = fasync::TestExecutor::new();
2034
2035 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2037 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2038 let iface_id = rand::random::<u16>();
2039 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2040
2041 let fut = sme.stop();
2043 let mut fut = pin!(fut);
2044 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2045
2046 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2048 assert_matches!(
2049 poll_ap_sme_req(&mut exec, &mut sme_fut),
2050 Poll::Ready(fidl_sme::ApSmeRequest::Stop { responder }) => {
2051 responder.send(fidl_sme::StopApResultCode::Success)
2052 .expect("could not send sme response");
2053 }
2054 );
2055
2056 assert_matches!(
2058 exec.run_until_stalled(&mut fut),
2059 Poll::Ready(Ok(fidl_sme::StopApResultCode::Success))
2060 );
2061 }
2062
2063 #[fuchsia::test]
2064 fn state_machine_sme_fails_to_request_stop_ap() {
2065 let mut exec = fasync::TestExecutor::new();
2066
2067 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2069 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2070 let iface_id = rand::random::<u16>();
2071 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2072
2073 let fut = sme.stop();
2075 let mut fut = pin!(fut);
2076 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2077 }
2078
2079 #[fuchsia::test]
2080 fn state_machine_sme_stop_ap_timeout() {
2081 let mut exec = fasync::TestExecutor::new_with_fake_time();
2082 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2083
2084 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2086 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2087 let iface_id = rand::random::<u16>();
2088 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2089
2090 let fut = sme.stop();
2092 let mut fut = pin!(fut);
2093 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2094
2095 exec.set_fake_time(fasync::MonotonicInstant::after(
2097 START_AP_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2098 ));
2099
2100 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2102 assert_eq!(
2103 defect_receiver.try_recv().ok(),
2104 Some(Defect::Iface(IfaceFailure::Timeout { iface_id, source: TimeoutSource::ApStop })),
2105 );
2106 }
2107
2108 #[fuchsia::test]
2109 fn state_machine_sme_successfully_queries_ap_status() {
2110 let mut exec = fasync::TestExecutor::new();
2111
2112 let (proxy, sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2114 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2115 let iface_id = rand::random::<u16>();
2116 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2117
2118 let fut = sme.status();
2120 let mut fut = pin!(fut);
2121 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2122
2123 let mut sme_fut = pin!(sme_fut.into_stream().into_future());
2125 assert_matches!(
2126 poll_ap_sme_req(&mut exec, &mut sme_fut),
2127 Poll::Ready(fidl_sme::ApSmeRequest::Status{ responder }) => {
2128 let response = fidl_sme::ApStatusResponse { running_ap: None };
2129 responder.send(&response).expect("could not send AP status response");
2130 }
2131 );
2132
2133 assert_matches!(
2135 exec.run_until_stalled(&mut fut),
2136 Poll::Ready(Ok(fidl_sme::ApStatusResponse { running_ap: None }))
2137 );
2138 }
2139
2140 #[fuchsia::test]
2141 fn state_machine_sme_fails_to_query_ap_status() {
2142 let mut exec = fasync::TestExecutor::new();
2143
2144 let (proxy, _) = create_proxy::<fidl_sme::ApSmeMarker>();
2146 let (defect_sender, _defect_receiver) = mpsc::channel(100);
2147 let iface_id = rand::random::<u16>();
2148 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2149
2150 let fut = sme.status();
2152 let mut fut = pin!(fut);
2153 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2154 }
2155
2156 #[fuchsia::test]
2157 fn state_machine_sme_query_ap_status_timeout() {
2158 let mut exec = fasync::TestExecutor::new_with_fake_time();
2159 exec.set_fake_time(fasync::MonotonicInstant::from_nanos(0));
2160
2161 let (proxy, _sme_fut) = create_proxy::<fidl_sme::ApSmeMarker>();
2163 let (defect_sender, mut defect_receiver) = mpsc::channel(100);
2164 let iface_id = rand::random::<u16>();
2165 let sme = SmeForApStateMachine::new(proxy, iface_id, defect_sender);
2166
2167 let fut = sme.status();
2169 let mut fut = pin!(fut);
2170 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
2171
2172 exec.set_fake_time(fasync::MonotonicInstant::after(
2174 AP_STATUS_TIMEOUT + fasync::MonotonicDuration::from_seconds(1),
2175 ));
2176
2177 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
2179 assert_eq!(
2180 defect_receiver.try_recv().ok(),
2181 Some(Defect::Iface(IfaceFailure::Timeout {
2182 iface_id,
2183 source: TimeoutSource::ApStatus,
2184 })),
2185 );
2186 }
2187}