1use crate::client::types;
7use crate::config_management::SavedNetworksManagerApi;
8use crate::mode_management::iface_manager_api::{IfaceManagerApi, SmeForScan};
9use crate::telemetry::{ScanEventInspectData, ScanIssue, TelemetryEvent, TelemetrySender};
10use anyhow::{Error, format_err};
11use async_trait::async_trait;
12use fidl_fuchsia_location_sensor as fidl_location_sensor;
13use fidl_fuchsia_wlan_policy as fidl_policy;
14use fidl_fuchsia_wlan_sme as fidl_sme;
15use fuchsia_async::{self as fasync, DurationExt, TimeoutExt};
16use fuchsia_component::client::connect_to_protocol;
17use futures::channel::{mpsc, oneshot};
18use futures::future::{Fuse, FusedFuture, FutureExt};
19use futures::lock::Mutex;
20use futures::select;
21use futures::stream::{FuturesUnordered, StreamExt};
22use itertools::Itertools;
23use log::{debug, error, info, trace, warn};
24use std::collections::HashMap;
25use std::pin::pin;
26use std::sync::Arc;
27
28mod fidl_conversion;
29mod queue;
30
31pub use fidl_conversion::{
32 scan_result_to_policy_scan_result, send_scan_error_over_fidl, send_scan_results_over_fidl,
33};
34
35const SCAN_RETRY_DELAY_MS: i64 = 100;
37const SCAN_CONSUMER_MAX_SECONDS_ALLOWED: i64 = 5;
39pub const SCAN_REQUEST_BUFFER_SIZE: usize = 100;
41
42#[derive(Debug, PartialEq)]
44pub enum ScanReason {
45 ClientRequest,
46 NetworkSelection,
47 BssSelection,
48 BssSelectionAugmentation,
49 RoamSearch,
50}
51
52#[async_trait(?Send)]
53pub trait ScanRequestApi {
54 async fn perform_scan(
55 &self,
56 scan_reason: ScanReason,
57 ssids: Vec<types::Ssid>,
58 channels: Vec<types::WlanChan>,
59 ) -> Result<Vec<types::ScanResult>, types::ScanError>;
60}
61
62pub struct ScanRequester {
63 pub sender: mpsc::Sender<ApiScanRequest>,
64}
65
66pub enum ApiScanRequest {
67 Scan(
68 ScanReason,
69 Vec<types::Ssid>,
70 Vec<types::WlanChan>,
71 oneshot::Sender<Result<Vec<types::ScanResult>, types::ScanError>>,
72 ),
73}
74
75#[async_trait(?Send)]
76impl ScanRequestApi for ScanRequester {
77 async fn perform_scan(
78 &self,
79 scan_reason: ScanReason,
80 ssids: Vec<types::Ssid>,
81 channels: Vec<types::WlanChan>,
82 ) -> Result<Vec<types::ScanResult>, types::ScanError> {
83 let (responder, receiver) = oneshot::channel();
84 self.sender
85 .clone()
86 .try_send(ApiScanRequest::Scan(scan_reason, ssids, channels, responder))
87 .map_err(|e| {
88 error!("Failed to send ScanRequest: {:?}", e);
89 types::ScanError::GeneralError
90 })?;
91 receiver.await.map_err(|e| {
92 error!("Failed to receive ScanRequest response: {:?}", e);
93 types::ScanError::GeneralError
94 })?
95 }
96}
97
98#[derive(Debug, Clone)]
100struct ScanRequest {
101 pub sme_req: fidl_sme::ScanRequest,
102 pub is_retry: bool,
103}
104impl From<fidl_sme::ScanRequest> for ScanRequest {
105 fn from(sme_req: fidl_sme::ScanRequest) -> Self {
106 Self { sme_req, is_retry: false }
107 }
108}
109
110pub async fn serve_scanning_loop(
112 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
113 saved_networks_manager: Arc<dyn SavedNetworksManagerApi>,
114 telemetry_sender: TelemetrySender,
115 location_sensor_updater: impl ScanResultUpdate,
116 mut scan_request_channel: mpsc::Receiver<ApiScanRequest>,
117) -> Result<(), Error> {
118 let mut queue = queue::RequestQueue::new(telemetry_sender.clone());
119 let mut location_sensor_updates = FuturesUnordered::new();
120 let ongoing_scan = Fuse::terminated();
123 let mut ongoing_scan = pin!(ongoing_scan);
124
125 let transform_next_sme_req = |next_sme_req: Option<ScanRequest>| match next_sme_req {
126 None => Fuse::terminated(),
127 Some(next_sme_req) => perform_scan(
128 next_sme_req,
129 iface_manager.clone(),
130 saved_networks_manager.clone(),
131 telemetry_sender.clone(),
132 )
133 .fuse(),
134 };
135
136 loop {
137 select! {
138 request = scan_request_channel.next() => {
139 match request {
140 Some(ApiScanRequest::Scan(reason, ssids, channels, responder)) => {
141 queue.add_request(reason, ssids, channels, responder, zx::MonotonicInstant::get());
142 if ongoing_scan.is_terminated() {
144 ongoing_scan.set(transform_next_sme_req(queue.get_next_sme_request().map(|req| req.into())));
145 }
146 },
147 None => {
148 error!("Unexpected 'None' on scan_request_channel");
149 }
150 }
151 },
152 (completed_sme_request, scan_results) = ongoing_scan => {
153 if scan_results == Err(types::ScanError::Cancelled) && !completed_sme_request.is_retry {
154 info!("Driver requested a delay before retrying the cancelled scan request.");
156 fasync::Timer::new(zx::MonotonicDuration::from_millis(SCAN_RETRY_DELAY_MS).after_now()).await;
157 ongoing_scan.set(transform_next_sme_req(Some(ScanRequest {is_retry: true, ..completed_sme_request})));
158 continue;
159 }
160 match scan_results {
161 Ok(ref results) => {
162 queue.handle_completed_sme_scan(
164 completed_sme_request.sme_req.clone(),
165 scan_results.clone(),
166 zx::MonotonicInstant::get()
167 );
168 if !results.is_empty() {
170 location_sensor_updates.push(location_sensor_updater
171 .update_scan_results(results.clone())
172 .on_timeout(zx::MonotonicDuration::from_seconds(SCAN_CONSUMER_MAX_SECONDS_ALLOWED), || {
173 error!("Timed out waiting for location sensor to get results");
174 })
175 );
176 }
177 },
178 Err(error) => {
179 queue.handle_completed_sme_scan(
182 completed_sme_request.sme_req.clone(),
183 scan_results.clone(),
184 zx::MonotonicInstant::get()
185 );
186 if error == types::ScanError::Cancelled {
188 info!("After multiple cancelled attempts, driver requested a delay before serving new scan requests.");
189 fasync::Timer::new(zx::MonotonicDuration::from_millis(SCAN_RETRY_DELAY_MS).after_now()).await;
190 }
191 }
192 }
193 ongoing_scan.set(transform_next_sme_req(
195 queue.get_next_sme_request().map(|req| req.into())
196 ));
197 },
198 () = location_sensor_updates.select_next_some() => {},
199 complete => {
200 warn!("Unexpectedly reached end of scanning loop");
202 break
203 },
204 }
205 }
206
207 Err(format_err!("Unexpectedly reached end of scanning loop"))
208}
209
210#[async_trait(?Send)]
212pub trait ScanResultUpdate {
213 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>);
214}
215
216async fn sme_scan(
218 sme_proxy: &SmeForScan,
219 scan_request: &fidl_sme::ScanRequest,
220 scan_defects: &mut Vec<ScanIssue>,
221) -> Result<Vec<wlan_common::scan::ScanResult>, types::ScanError> {
222 debug!("Sending scan request to SME");
223 let scan_result = sme_proxy.scan(scan_request).await.map_err(|error| {
224 error!("Failed to send scan to SME: {:?}", error);
225 types::ScanError::GeneralError
226 })?;
227 debug!("Finished getting scan results from SME");
228 match scan_result {
229 Ok(vmo) => {
230 let scan_result_list = wlan_common::scan::read_vmo(vmo).map_err(|error| {
231 error!("Failed to read scan results from VMO: {:?}", error);
232 types::ScanError::GeneralError
233 })?;
234 Ok(scan_result_list
235 .into_iter()
236 .filter_map(|scan_result| {
237 wlan_common::scan::ScanResult::try_from(scan_result).map(Some).unwrap_or_else(
238 |e| {
239 error!("ScanResult conversion failed: {:?}", e);
242 None
243 },
244 )
245 })
246 .inspect(|scan_result| {
247 trace!(
250 "Scan result SSID: {}, BSSID: {}, channel: {}",
251 scan_result.bss_description.ssid,
252 scan_result.bss_description.bssid,
253 scan_result.bss_description.channel
254 )
255 })
256 .collect::<Vec<_>>())
257 }
258 Err(scan_error_code) => {
259 log_metric_for_scan_error(&scan_error_code, scan_defects);
260 match scan_error_code {
261 fidl_sme::ScanErrorCode::ShouldWait
262 | fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware => {
263 info!("Scan cancelled by SME, retry indicated: {:?}", scan_error_code);
264 Err(types::ScanError::Cancelled)
265 }
266 _ => {
267 error!("Scan error from SME: {:?}", scan_error_code);
268 Err(types::ScanError::GeneralError)
269 }
270 }
271 }
272 }
273}
274
275async fn perform_scan(
277 scan_request: ScanRequest,
278 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
279 saved_networks_manager: Arc<dyn SavedNetworksManagerApi>,
280 telemetry_sender: TelemetrySender,
281) -> (ScanRequest, Result<Vec<types::ScanResult>, types::ScanError>) {
282 let bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>>;
283 let mut scan_event_inspect_data = ScanEventInspectData::new();
284 let mut scan_defects: Vec<ScanIssue> = vec![];
285
286 let sme_proxy = match iface_manager.lock().await.get_sme_proxy_for_scan().await {
287 Ok(proxy) => proxy,
288 Err(_) => {
289 warn!("Failed to get sme proxy for passive scan");
290 return (scan_request, Err(types::ScanError::GeneralError));
291 }
292 };
293 let scan_results = sme_scan(&sme_proxy, &scan_request.sme_req, &mut scan_defects).await;
294 report_scan_defects_to_sme(&sme_proxy, &scan_results, &scan_request.sme_req).await;
295
296 match scan_results {
297 Ok(results) => {
298 let target_ssids = match scan_request.sme_req {
300 fidl_sme::ScanRequest::Passive(_) => vec![],
301 fidl_sme::ScanRequest::Active(ref req) => req
302 .ssids
303 .iter()
304 .map(|s| types::Ssid::from_bytes_unchecked(s.to_vec()))
305 .collect(),
306 };
307 bss_by_network =
308 bss_to_network_map(results, &target_ssids, &mut scan_event_inspect_data);
309 saved_networks_manager.record_scan_result(target_ssids, &bss_by_network).await;
310 }
311 Err(scan_err) => {
312 return (scan_request, Err(scan_err));
313 }
314 }
315
316 if let fidl_sme::ScanRequest::Passive(_) = scan_request.sme_req
318 && bss_by_network.is_empty()
319 {
320 scan_defects.push(ScanIssue::EmptyScanResults);
321 }
322
323 telemetry_sender
324 .send(TelemetryEvent::ScanEvent { inspect_data: scan_event_inspect_data, scan_defects });
325
326 let scan_results = network_map_to_scan_result(bss_by_network);
327 (scan_request, Ok(scan_results))
328}
329
330pub struct LocationSensorUpdater {}
333#[async_trait(?Send)]
334impl ScanResultUpdate for LocationSensorUpdater {
335 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>) {
336 async fn send_results(scan_results: Vec<fidl_policy::ScanResult>) -> Result<(), Error> {
337 let (iter, server) =
339 fidl::endpoints::create_endpoints::<fidl_policy::ScanResultIteratorMarker>();
340 let location_watcher_proxy =
341 connect_to_protocol::<fidl_location_sensor::WlanBaseStationWatcherMarker>()
342 .map_err(|err| {
343 format_err!("failed to connect to location sensor service: {:?}", err)
344 })?;
345 location_watcher_proxy
346 .report_current_stations(iter)
347 .map_err(|err| format_err!("failed to call location sensor service: {:?}", err))?;
348
349 fidl_conversion::send_scan_results_over_fidl(server, &scan_results).await
351 }
352
353 let scan_results = fidl_conversion::scan_result_to_policy_scan_result(&scan_results, true);
356 if let Err(e) = send_results(scan_results).await {
359 info!("Failed to send scan results to location sensor: {:?}", e)
360 } else {
361 debug!("Updated location sensor")
362 };
363 }
364}
365
366fn bss_to_network_map(
369 scan_result_list: Vec<wlan_common::scan::ScanResult>,
370 target_ssids: &[types::Ssid],
371 scan_event_inspect_data: &mut ScanEventInspectData,
372) -> HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> {
373 let mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> =
374 HashMap::new();
375 for scan_result in scan_result_list.into_iter() {
376 let security_type: types::SecurityTypeDetailed =
377 scan_result.bss_description.protection().into();
378 if security_type == types::SecurityTypeDetailed::Unknown {
379 let readable_ie =
381 scan_result.bss_description.ies().iter().map(|n| n.to_string()).join(",");
382 debug!("Encountered unknown protection, ies: [{:?}]", readable_ie.clone());
383 scan_event_inspect_data.unknown_protection_ies.push(readable_ie);
384 };
385 let entry = bss_by_network
386 .entry(types::NetworkIdentifierDetailed {
387 ssid: scan_result.bss_description.ssid.clone(),
388 security_type,
389 })
390 .or_default();
391
392 if !entry.iter().any(|existing_bss| existing_bss.bssid == scan_result.bss_description.bssid)
394 {
395 entry.push(types::Bss {
396 bssid: scan_result.bss_description.bssid,
397 signal: types::Signal {
398 rssi_dbm: scan_result.bss_description.rssi_dbm,
399 snr_db: scan_result.bss_description.snr_db,
400 },
401 channel: scan_result.bss_description.channel,
402 timestamp: scan_result.timestamp,
403 observation: if target_ssids.contains(&scan_result.bss_description.ssid) {
405 types::ScanObservation::Active
406 } else {
407 types::ScanObservation::Passive
408 },
409 compatibility: scan_result.compatibility,
410 bss_description: wlan_common::sequestered::Sequestered::from(
411 fidl_fuchsia_wlan_ieee80211::BssDescription::from(scan_result.bss_description),
412 ),
413 });
414 };
415 }
416 bss_by_network
417}
418
419fn network_map_to_scan_result(
420 mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>>,
421) -> Vec<types::ScanResult> {
422 let mut scan_results: Vec<types::ScanResult> = bss_by_network
423 .drain()
424 .map(|(types::NetworkIdentifierDetailed { ssid, security_type }, bss_entries)| {
425 let compatibility = if bss_entries.iter().any(|bss| bss.is_compatible()) {
426 fidl_policy::Compatibility::Supported
427 } else {
428 fidl_policy::Compatibility::DisallowedNotSupported
429 };
430 types::ScanResult {
431 ssid,
432 security_type_detailed: security_type,
433 entries: bss_entries,
434 compatibility,
435 }
436 })
437 .collect();
438
439 scan_results.sort_by(|a, b| a.ssid.cmp(&b.ssid));
440 scan_results
441}
442
443fn log_metric_for_scan_error(reason: &fidl_sme::ScanErrorCode, scan_defects: &mut Vec<ScanIssue>) {
444 let metric_type = match *reason {
445 fidl_sme::ScanErrorCode::NotSupported
446 | fidl_sme::ScanErrorCode::InternalError
447 | fidl_sme::ScanErrorCode::InternalMlmeError => ScanIssue::ScanFailure,
448 fidl_sme::ScanErrorCode::ShouldWait
449 | fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware => ScanIssue::AbortedScan,
450 };
451
452 scan_defects.push(metric_type);
453}
454
455async fn report_scan_defects_to_sme(
456 sme_proxy: &SmeForScan,
457 scan_result: &Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
458 scan_request: &fidl_sme::ScanRequest,
459) {
460 match scan_result {
461 Ok(results) => {
462 if results.is_empty()
464 && let fidl_sme::ScanRequest::Passive(_) = scan_request
465 {
466 sme_proxy.log_empty_scan_defect();
467 }
468 }
469 Err(types::ScanError::GeneralError) => sme_proxy.log_failed_scan_defect(),
470 Err(types::ScanError::Cancelled) => sme_proxy.log_aborted_scan_defect(),
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use super::*;
477 use crate::access_point::state_machine as ap_fsm;
478 use crate::mode_management::iface_manager_api::ConnectAttemptRequest;
479 use crate::mode_management::{Defect, IfaceFailure};
480 use crate::util::testing::fakes::FakeSavedNetworksManager;
481 use crate::util::testing::{
482 generate_channel, generate_random_sme_scan_result, run_until_completion,
483 };
484 use assert_matches::assert_matches;
485 use fidl::endpoints::{ControlHandle, Responder, create_proxy};
486 use fidl_fuchsia_wlan_internal as fidl_internal;
487 use fuchsia_async as fasync;
488 use futures::future;
489 use futures::task::Poll;
490 use std::pin::pin;
491 use test_case::test_case;
492 use wlan_common::ie::IeType;
493 use wlan_common::scan::{Compatible, Incompatible, write_vmo};
494 use wlan_common::security::SecurityDescriptor;
495 use wlan_common::test_utils::fake_frames::fake_unknown_rsne;
496 use wlan_common::test_utils::fake_stas::IesOverrides;
497 use wlan_common::{fake_bss_description, random_fidl_bss_description};
498
499 fn active_sme_req(ssids: Vec<&str>, channels: Vec<u8>) -> fidl_sme::ScanRequest {
500 fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
501 ssids: ssids.iter().map(|s| s.as_bytes().to_vec()).collect(),
502 channels,
503 })
504 }
505
506 fn passive_sme_req() -> fidl_sme::ScanRequest {
507 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] })
508 }
509
510 struct FakeIfaceManager {
511 pub sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
512 pub defect_sender: mpsc::Sender<Defect>,
513 pub defect_receiver: mpsc::Receiver<Defect>,
514 }
515
516 impl FakeIfaceManager {
517 pub fn new(proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy) -> Self {
518 let (defect_sender, defect_receiver) = mpsc::channel(100);
519 FakeIfaceManager { sme_proxy: proxy, defect_sender, defect_receiver }
520 }
521 }
522
523 #[async_trait(?Send)]
524 impl IfaceManagerApi for FakeIfaceManager {
525 async fn disconnect(
526 &mut self,
527 _network_id: types::NetworkIdentifier,
528 _reason: types::DisconnectReason,
529 ) -> Result<(), Error> {
530 unimplemented!()
531 }
532
533 async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
534 unimplemented!()
535 }
536
537 async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
538 unimplemented!()
539 }
540
541 async fn has_idle_client(&mut self) -> Result<bool, Error> {
542 unimplemented!()
543 }
544
545 async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
546 unimplemented!()
547 }
548
549 async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
550 unimplemented!()
551 }
552
553 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
554 Ok(SmeForScan::new(self.sme_proxy.clone(), 0, self.defect_sender.clone()))
555 }
556
557 async fn stop_client_connections(
558 &mut self,
559 _reason: types::DisconnectReason,
560 ) -> Result<(), Error> {
561 unimplemented!()
562 }
563
564 async fn start_client_connections(&mut self) -> Result<(), Error> {
565 unimplemented!()
566 }
567
568 async fn start_ap(
569 &mut self,
570 _config: ap_fsm::ApConfig,
571 ) -> Result<oneshot::Receiver<()>, Error> {
572 unimplemented!()
573 }
574
575 async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
576 unimplemented!()
577 }
578
579 async fn stop_all_aps(&mut self) -> Result<(), Error> {
580 unimplemented!()
581 }
582
583 async fn set_country(
584 &mut self,
585 _country_code: Option<types::CountryCode>,
586 ) -> Result<(), Error> {
587 unimplemented!()
588 }
589 }
590
591 async fn create_iface_manager()
593 -> (Arc<Mutex<FakeIfaceManager>>, fidl_sme::ClientSmeRequestStream) {
594 let (client_sme, remote) = create_proxy::<fidl_sme::ClientSmeMarker>();
595 let iface_manager = FakeIfaceManager::new(client_sme);
596 let iface_manager = Arc::new(Mutex::new(iface_manager));
597 (iface_manager, remote.into_stream())
598 }
599
600 async fn create_sme_proxy() -> (fidl_sme::ClientSmeProxy, fidl_sme::ClientSmeRequestStream) {
602 let (client_sme, remote) = create_proxy::<fidl_sme::ClientSmeMarker>();
603 (client_sme, remote.into_stream())
604 }
605
606 struct MockScanResultConsumer {
607 scan_results: Arc<Mutex<Option<Vec<types::ScanResult>>>>,
608 stalled: Arc<Mutex<bool>>,
609 }
610 impl MockScanResultConsumer {
611 #[allow(clippy::type_complexity)]
612 fn new() -> (Self, Arc<Mutex<Option<Vec<types::ScanResult>>>>, Arc<Mutex<bool>>) {
613 let scan_results = Arc::new(Mutex::new(None));
614 let stalled = Arc::new(Mutex::new(false));
615 (
616 Self { scan_results: scan_results.clone(), stalled: stalled.clone() },
617 scan_results,
618 stalled,
619 )
620 }
621 }
622 #[async_trait(?Send)]
623 impl ScanResultUpdate for MockScanResultConsumer {
624 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>) {
625 if *self.stalled.lock().await {
626 let () = future::pending().await;
627 unreachable!();
628 }
629 let mut guard = self.scan_results.lock().await;
630 *guard = Some(scan_results);
631 }
632 }
633
634 struct MockScanData {
636 sme_results: Vec<fidl_sme::ScanResult>,
637 internal_results: Vec<types::ScanResult>,
638 }
639 fn create_scan_ap_data(observation: types::ScanObservation) -> MockScanData {
640 let sme_result_1 = fidl_sme::ScanResult {
641 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
642 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
643 }),
644 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
645 bss_description: random_fidl_bss_description!(
646 Wpa3,
647 bssid: [0, 0, 0, 0, 0, 0],
648 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
649 rssi_dbm: 0,
650 snr_db: 1,
651 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
652 ),
653 };
654 let sme_result_2 = fidl_sme::ScanResult {
655 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
656 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa2Personal],
657 }),
658 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
659 bss_description: random_fidl_bss_description!(
660 Wpa2,
661 bssid: [1, 2, 3, 4, 5, 6],
662 ssid: types::Ssid::try_from("unique ssid").unwrap(),
663 rssi_dbm: 7,
664 snr_db: 2,
665 channel: types::WlanChan::new(8, types::Cbw::Cbw20),
666 ),
667 };
668 let sme_result_3 = fidl_sme::ScanResult {
669 compatibility: fidl_sme::Compatibility::Incompatible(fidl_sme::Incompatible {
670 description: String::from("unknown"),
671 disjoint_security_protocols: None,
672 }),
673 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
674 bss_description: random_fidl_bss_description!(
675 Wpa3,
676 bssid: [7, 8, 9, 10, 11, 12],
677 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
678 rssi_dbm: 13,
679 snr_db: 3,
680 channel: types::WlanChan::new(11, types::Cbw::Cbw20),
681 ),
682 };
683
684 let sme_results = vec![sme_result_1.clone(), sme_result_2.clone(), sme_result_3.clone()];
685 let internal_results = vec![
688 types::ScanResult {
689 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
690 security_type_detailed: types::SecurityTypeDetailed::Wpa3Personal,
691 entries: vec![
692 types::Bss {
693 bssid: types::Bssid::from([0, 0, 0, 0, 0, 0]),
694 signal: types::Signal { rssi_dbm: 0, snr_db: 1 },
695 timestamp: zx::MonotonicInstant::from_nanos(sme_result_1.timestamp_nanos),
696 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
697 observation,
698 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
699 bss_description: sme_result_1.bss_description.clone().into(),
700 },
701 types::Bss {
702 bssid: types::Bssid::from([7, 8, 9, 10, 11, 12]),
703 signal: types::Signal { rssi_dbm: 13, snr_db: 3 },
704 timestamp: zx::MonotonicInstant::from_nanos(sme_result_3.timestamp_nanos),
705 channel: types::WlanChan::new(11, types::Cbw::Cbw20),
706 observation,
707 compatibility: Incompatible::unknown(),
708 bss_description: sme_result_3.bss_description.clone().into(),
709 },
710 ],
711 compatibility: types::Compatibility::Supported,
712 },
713 types::ScanResult {
714 ssid: types::Ssid::try_from("unique ssid").unwrap(),
715 security_type_detailed: types::SecurityTypeDetailed::Wpa2Personal,
716 entries: vec![types::Bss {
717 bssid: types::Bssid::from([1, 2, 3, 4, 5, 6]),
718 signal: types::Signal { rssi_dbm: 7, snr_db: 2 },
719 timestamp: zx::MonotonicInstant::from_nanos(sme_result_2.timestamp_nanos),
720 channel: types::WlanChan::new(8, types::Cbw::Cbw20),
721 observation,
722 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA2_PERSONAL]),
723 bss_description: sme_result_2.bss_description.clone().into(),
724 }],
725 compatibility: types::Compatibility::Supported,
726 },
727 ];
728
729 MockScanData { sme_results, internal_results }
730 }
731
732 fn create_telemetry_sender_and_receiver() -> (TelemetrySender, mpsc::Receiver<TelemetryEvent>) {
733 let (sender, receiver) = mpsc::channel::<TelemetryEvent>(100);
734 let sender = TelemetrySender::new(sender);
735 (sender, receiver)
736 }
737
738 fn get_fake_defects(
739 exec: &mut fasync::TestExecutor,
740 iface_manager: Arc<Mutex<FakeIfaceManager>>,
741 ) -> Vec<Defect> {
742 let defects_fut = async move {
743 let mut iface_manager = iface_manager.lock().await;
744 let mut defects = Vec::<Defect>::new();
745 while let Ok(Some(defect)) = iface_manager.defect_receiver.try_next() {
746 defects.push(defect)
747 }
748
749 defects
750 };
751 let mut defects_fut = pin!(defects_fut);
752 assert_matches!(exec.run_until_stalled(&mut defects_fut), Poll::Ready(defects) => defects)
753 }
754
755 #[fuchsia::test]
756 fn sme_scan_with_passive_request() {
757 let mut exec = fasync::TestExecutor::new();
758 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
759 let (defect_sender, _) = mpsc::channel(100);
760 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
761
762 let scan_request =
764 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] });
765 let mut scan_defects = vec![];
766 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
767 let mut scan_fut = pin!(scan_fut);
768
769 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
771
772 let MockScanData { sme_results: input_aps, internal_results: _ } =
774 create_scan_ap_data(types::ScanObservation::Passive);
775 assert_matches!(
777 exec.run_until_stalled(&mut sme_stream.next()),
778 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
779 req, responder,
780 }))) => {
781 assert_eq!(req, scan_request);
782 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
783 responder.send(Ok(vmo)).expect("failed to send scan data");
784 }
785 );
786
787 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
789 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
790 .iter().map(|r| r.clone().into()).collect();
791 assert_eq!(scan_results, input_aps);
792 });
793
794 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
796 }
797
798 #[fuchsia::test]
799 fn sme_scan_with_active_request() {
800 let mut exec = fasync::TestExecutor::new();
801 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
802 let (defect_sender, _) = mpsc::channel(100);
803 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
804
805 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
807 ssids: vec![
808 types::Ssid::try_from("foo_ssid").unwrap().into(),
809 types::Ssid::try_from("bar_ssid").unwrap().into(),
810 ],
811 channels: vec![1, 20],
812 });
813 let mut scan_defects = vec![];
814 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
815 let mut scan_fut = pin!(scan_fut);
816
817 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
819
820 let MockScanData { sme_results: input_aps, internal_results: _ } =
822 create_scan_ap_data(types::ScanObservation::Active);
823 assert_matches!(
825 exec.run_until_stalled(&mut sme_stream.next()),
826 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
827 req, responder,
828 }))) => {
829 assert_eq!(req, scan_request);
830 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
831 responder.send(Ok(vmo)).expect("failed to send scan data");
832 }
833 );
834
835 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
837 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
838 .iter().map(|r| r.clone().into()).collect();
839 assert_eq!(scan_results, input_aps);
840 });
841
842 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
844 }
845
846 #[fuchsia::test]
847 fn sme_channel_closed_while_awaiting_scan_results() {
848 let mut exec = fasync::TestExecutor::new();
849 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
850 let (defect_sender, _) = mpsc::channel(100);
851 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
852
853 let scan_request =
855 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] });
856 let mut scan_defects = vec![];
857 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
858 let mut scan_fut = pin!(scan_fut);
859
860 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
862
863 assert_matches!(
865 exec.run_until_stalled(&mut sme_stream.next()),
866 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
867 req: _, responder,
868 }))) => {
869 responder.control_handle().shutdown();
871 drop(sme_stream);
873 }
874 );
875
876 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
878 let error = result.expect_err("did not expect scan results");
879 assert_eq!(error, types::ScanError::GeneralError);
880 });
881 }
882
883 #[fuchsia::test]
884 fn basic_scan() {
885 let mut exec = fasync::TestExecutor::new();
886 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
887 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
888 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
889 let sme_scan = passive_sme_req();
891 let scan_fut =
892 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
893 let mut scan_fut = pin!(scan_fut);
894
895 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
897
898 let MockScanData { sme_results: input_aps, internal_results: internal_aps } =
900 create_scan_ap_data(types::ScanObservation::Passive);
901 assert_matches!(
902 exec.run_until_stalled(&mut sme_stream.next()),
903 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
904 req, responder,
905 }))) => {
906 assert_eq!(req, sme_scan.clone());
907 let vmo = write_vmo(input_aps).expect("failed to write VMO");
908 responder.send(Ok(vmo)).expect("failed to send scan data");
909 }
910 );
911
912 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
914 assert_eq!(request.sme_req, sme_scan);
915 assert_eq!(results.unwrap(), internal_aps);
916 });
917
918 assert_matches!(
921 telemetry_receiver.try_next(),
922 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
923 assert_eq!(inspect_data, ScanEventInspectData::new());
924 assert_eq!(scan_defects, vec![]);
925 });
926 }
927
928 #[fuchsia::test]
929 fn empty_passive_scan_results() {
930 let mut exec = fasync::TestExecutor::new();
931 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
932 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
933 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
934
935 let sme_scan = passive_sme_req();
937 let scan_fut = perform_scan(
938 sme_scan.clone().into(),
939 client.clone(),
940 saved_networks_manager,
941 telemetry_sender,
942 );
943 let mut scan_fut = pin!(scan_fut);
944
945 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
947
948 assert_matches!(
950 exec.run_until_stalled(&mut sme_stream.next()),
951 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
952 req, responder,
953 }))) => {
954 assert_eq!(req, sme_scan.clone());
955 let vmo = write_vmo(vec![]).expect("failed to write VMO");
956 responder.send(Ok(vmo)).expect("failed to send scan data");
957 }
958 );
959
960 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
962 assert_eq!(request.sme_req, sme_scan);
963 assert!(results.unwrap().is_empty());
964 });
965
966 assert_matches!(
968 telemetry_receiver.try_next(),
969 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
970 assert_eq!(inspect_data, ScanEventInspectData::new());
971 assert_eq!(scan_defects, vec![ScanIssue::EmptyScanResults]);
972 });
973
974 let logged_defects = get_fake_defects(&mut exec, client);
976 let expected_defects = vec![Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })];
977 assert_eq!(logged_defects, expected_defects);
978 }
979
980 #[fuchsia::test]
981 fn empty_active_scan_results() {
982 let mut exec = fasync::TestExecutor::new();
983 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
984 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
985 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
986
987 let sme_scan = active_sme_req(vec!["foo"], vec![]);
989 let scan_fut = perform_scan(
990 sme_scan.clone().into(),
991 client.clone(),
992 saved_networks_manager,
993 telemetry_sender,
994 );
995 let mut scan_fut = pin!(scan_fut);
996
997 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
999
1000 assert_matches!(
1002 exec.run_until_stalled(&mut sme_stream.next()),
1003 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1004 req, responder,
1005 }))) => {
1006 assert_eq!(req, sme_scan.clone());
1007 let vmo = write_vmo(vec![]).expect("failed to write VMO");
1008 responder.send(Ok(vmo)).expect("failed to send scan data");
1009 }
1010 );
1011
1012 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1014 assert_eq!(request.sme_req, sme_scan);
1015 assert!(results.unwrap().is_empty());
1016 });
1017
1018 assert_matches!(telemetry_receiver.try_next(), Ok(Some(TelemetryEvent::ScanEvent { scan_defects, .. })) => {
1021 assert!(scan_defects.is_empty());
1022 });
1023
1024 let logged_defects = get_fake_defects(&mut exec, client);
1026 let expected_defects = vec![];
1027 assert_eq!(logged_defects, expected_defects);
1028 }
1029
1030 #[test_case(active_sme_req(vec![], vec![]) ; "active_sme_req, no ssid")]
1032 #[test_case(active_sme_req(vec![""], vec![]) ; "active_sme_req, wildcard ssid")]
1033 #[test_case(active_sme_req(vec!["", "foo"], vec![]) ; "active_sme_req, wildcard and foo ssid")]
1034 #[test_case(active_sme_req(vec!["foo"], vec![]) ; "active_sme_req, foo ssid")]
1035 #[test_case(passive_sme_req())]
1036 #[fuchsia::test(add_test_attr = false)]
1037 fn scan_updates_hidden_network_probabilities(sme_scan_request: fidl_sme::ScanRequest) {
1038 let mut exec = fasync::TestExecutor::new();
1039 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1040 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1041 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1042
1043 let MockScanData { sme_results: input_aps, internal_results: scan_results } =
1045 create_scan_ap_data(types::ScanObservation::Unknown);
1046
1047 let scan_fut = perform_scan(
1049 sme_scan_request.clone().into(),
1050 client,
1051 saved_networks_manager.clone(),
1052 telemetry_sender,
1053 );
1054 let mut scan_fut = pin!(scan_fut);
1055
1056 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1058
1059 assert_matches!(
1061 exec.run_until_stalled(&mut sme_stream.next()),
1062 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1063 req, responder,
1064 }))) => {
1065 assert_eq!(req, sme_scan_request);
1066 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1067 responder.send(Ok(vmo)).expect("failed to send scan data");
1068 }
1069 );
1070
1071 let _ = exec.run_until_stalled(&mut scan_fut);
1074
1075 let target_ssids = match sme_scan_request {
1077 fidl_sme::ScanRequest::Passive(_) => vec![],
1078 fidl_sme::ScanRequest::Active(ref req) => {
1079 req.ssids.iter().map(|s| types::Ssid::from_bytes_unchecked(s.to_vec())).collect()
1080 }
1081 };
1082 let mut scan_results_ids: Vec<types::NetworkIdentifierDetailed> = scan_results
1083 .iter()
1084 .map(|scan_result| types::NetworkIdentifierDetailed {
1085 ssid: scan_result.ssid.clone(),
1086 security_type: scan_result.security_type_detailed,
1087 })
1088 .collect();
1089
1090 let scan_result_record_guard =
1091 exec.run_singlethreaded(saved_networks_manager.scan_result_records.lock());
1092 assert_eq!(scan_result_record_guard.len(), 1);
1093 assert_eq!(scan_result_record_guard[0].0, target_ssids);
1094
1095 let mut recorded_ids = scan_result_record_guard[0]
1097 .1
1098 .keys()
1099 .cloned()
1100 .collect::<Vec<types::NetworkIdentifierDetailed>>();
1101
1102 recorded_ids.sort();
1103 scan_results_ids.sort();
1104 assert_eq!(scan_results_ids, recorded_ids);
1105
1106 }
1109
1110 #[fuchsia::test]
1111 fn bss_to_network_map_duplicated_bss() {
1112 let first_result = fidl_sme::ScanResult {
1114 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1115 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1116 }),
1117 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1118 bss_description: random_fidl_bss_description!(
1119 Wpa3,
1120 bssid: [0, 0, 0, 0, 0, 0],
1121 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1122 rssi_dbm: 0,
1123 snr_db: 1,
1124 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
1125 ),
1126 };
1127 let second_result = fidl_sme::ScanResult {
1128 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1129 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1130 }),
1131 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1132 bss_description: random_fidl_bss_description!(
1133 Wpa3,
1134 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1135 bssid: [1, 2, 3, 4, 5, 6],
1136 rssi_dbm: 101,
1137 snr_db: 101,
1138 channel: types::WlanChan::new(101, types::Cbw::Cbw40),
1139 ),
1140 };
1141
1142 let sme_results = [
1143 first_result.clone(),
1144 second_result.clone(),
1145 fidl_sme::ScanResult {
1147 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1148 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1149 }),
1150 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1151 bss_description: random_fidl_bss_description!(
1152 Wpa3,
1153 bssid: [0, 0, 0, 0, 0, 0],
1154 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1155 rssi_dbm: 13,
1156 snr_db: 3,
1157 channel: types::WlanChan::new(14, types::Cbw::Cbw20),
1158 ),
1159 },
1160 ];
1161
1162 let expected_id = types::NetworkIdentifierDetailed {
1163 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1164 security_type: types::SecurityTypeDetailed::Wpa3Personal,
1165 };
1166
1167 let expected_bss = vec![
1170 types::Bss {
1171 bssid: types::Bssid::from([0, 0, 0, 0, 0, 0]),
1172 signal: types::Signal { rssi_dbm: 0, snr_db: 1 },
1173 timestamp: zx::MonotonicInstant::from_nanos(first_result.timestamp_nanos),
1174 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
1175 observation: types::ScanObservation::Passive,
1176 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1177 bss_description: first_result.bss_description.clone().into(),
1178 },
1179 types::Bss {
1180 bssid: types::Bssid::from([1, 2, 3, 4, 5, 6]),
1181 signal: types::Signal { rssi_dbm: 101, snr_db: 101 },
1182 timestamp: zx::MonotonicInstant::from_nanos(second_result.timestamp_nanos),
1183 channel: types::WlanChan::new(101, types::Cbw::Cbw40),
1184 observation: types::ScanObservation::Passive,
1185 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1186 bss_description: second_result.bss_description.clone().into(),
1187 },
1188 ];
1189
1190 let bss_by_network = bss_to_network_map(
1191 sme_results
1192 .iter()
1193 .map(|scan_result| {
1194 scan_result.clone().try_into().expect("Failed to convert ScanResult")
1195 })
1196 .collect::<Vec<wlan_common::scan::ScanResult>>(),
1197 &[],
1198 &mut ScanEventInspectData::new(),
1199 );
1200 assert_eq!(bss_by_network.len(), 1);
1201 assert_eq!(bss_by_network[&expected_id], expected_bss);
1202 }
1203
1204 #[test_case(
1205 fidl_sme::ScanErrorCode::InternalError,
1206 types::ScanError::GeneralError,
1207 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1208 )]
1209 #[test_case(
1210 fidl_sme::ScanErrorCode::InternalMlmeError,
1211 types::ScanError::GeneralError,
1212 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1213 )]
1214 #[test_case(
1215 fidl_sme::ScanErrorCode::NotSupported,
1216 types::ScanError::GeneralError,
1217 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1218 )]
1219 #[fuchsia::test(add_test_attr = false)]
1220 fn scan_error_no_retries(
1221 sme_failure_mode: fidl_sme::ScanErrorCode,
1222 policy_failure_mode: types::ScanError,
1223 expected_defect: Defect,
1224 ) {
1225 let mut exec = fasync::TestExecutor::new();
1226 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1227 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1228 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1229
1230 let sme_scan = active_sme_req(vec![], vec![1]);
1232 let scan_fut = perform_scan(
1233 sme_scan.clone().into(),
1234 client.clone(),
1235 saved_networks_manager,
1236 telemetry_sender,
1237 );
1238 let mut scan_fut = pin!(scan_fut);
1239 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1240
1241 assert_matches!(
1243 exec.run_until_stalled(&mut sme_stream.next()),
1244 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1245 responder.send(Err(sme_failure_mode)).expect("failed to send scan error");
1247 }
1248 );
1249
1250 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1252 assert_eq!(request.sme_req, sme_scan);
1253 assert_eq!(results, Err(policy_failure_mode));
1254 });
1255
1256 let logged_defects = get_fake_defects(&mut exec, client);
1258 let expected_defects = vec![expected_defect];
1259 assert_eq!(logged_defects, expected_defects);
1260 }
1261
1262 #[fuchsia::test]
1263 fn scan_returns_error_on_timeout() {
1264 let mut exec = fasync::TestExecutor::new_with_fake_time();
1265 let (client, _sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1266 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1267 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1268
1269 let sme_scan = passive_sme_req();
1271 let scan_fut =
1272 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
1273 let mut scan_fut = pin!(scan_fut);
1274
1275 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1277
1278 assert!(exec.wake_next_timer().is_some());
1280
1281 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1283 assert_eq!(request.sme_req, sme_scan);
1284 assert_eq!(results, Err(types::ScanError::GeneralError));
1285 });
1286 }
1287
1288 #[test_case(fidl_sme::ScanErrorCode::NotSupported, ScanIssue::ScanFailure)]
1289 #[test_case(fidl_sme::ScanErrorCode::InternalError, ScanIssue::ScanFailure)]
1290 #[test_case(fidl_sme::ScanErrorCode::InternalMlmeError, ScanIssue::ScanFailure)]
1291 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, ScanIssue::AbortedScan)]
1292 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, ScanIssue::AbortedScan)]
1293 #[fuchsia::test(add_test_attr = false)]
1294 fn test_scan_error_metric_conversion(
1295 scan_error: fidl_sme::ScanErrorCode,
1296 expected_issue: ScanIssue,
1297 ) {
1298 let mut scan_defects = vec![];
1299 log_metric_for_scan_error(&scan_error, &mut scan_defects);
1300 assert_eq!(scan_defects, vec![expected_issue]);
1301 }
1302
1303 #[test_case(Err(types::ScanError::GeneralError), Some(Defect::Iface(IfaceFailure::FailedScan { iface_id: 0 })))]
1304 #[test_case(Err(types::ScanError::Cancelled), Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })))]
1305 #[test_case(Ok(vec![]), Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })))]
1306 #[test_case(Ok(vec![wlan_common::scan::ScanResult::try_from(
1307 fidl_sme::ScanResult {
1308 bss_description: random_fidl_bss_description!(Wpa2, ssid: types::Ssid::try_from("other ssid").unwrap()),
1309 ..generate_random_sme_scan_result()
1310 },
1311 ).expect("failed scan result conversion")]),
1312 None
1313 )]
1314 #[fuchsia::test(add_test_attr = false)]
1315 fn test_scan_defect_reporting(
1316 scan_result: Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
1317 expected_defect: Option<Defect>,
1318 ) {
1319 let mut exec = fasync::TestExecutor::new();
1320 let (iface_manager, _) = exec.run_singlethreaded(create_iface_manager());
1321 let scan_request = passive_sme_req();
1322
1323 let sme = {
1325 let cloned_iface_manager = iface_manager.clone();
1326 let fut = async move {
1327 let mut iface_manager = cloned_iface_manager.lock().await;
1328 iface_manager.get_sme_proxy_for_scan().await
1329 };
1330 let mut fut = pin!(fut);
1331 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(sme)) => sme)
1332 };
1333
1334 let fut = report_scan_defects_to_sme(&sme, &scan_result, &scan_request);
1336 let mut fut = pin!(fut);
1337 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1338
1339 let logged_defects = get_fake_defects(&mut exec, iface_manager);
1343 match expected_defect {
1344 Some(defect) => {
1345 assert_eq!(logged_defects, vec![defect])
1346 }
1347 None => assert!(logged_defects.is_empty()),
1348 }
1349 }
1350
1351 #[fuchsia::test]
1352 fn scanning_loop_handles_sequential_requests() {
1353 let mut exec = fasync::TestExecutor::new();
1354 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1355 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1356 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1357 let (location_sensor, _, _) = MockScanResultConsumer::new();
1358 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1359 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1360 let scanning_loop = serve_scanning_loop(
1361 iface_mgr.clone(),
1362 saved_networks_manager.clone(),
1363 telemetry_sender,
1364 location_sensor,
1365 scan_request_receiver,
1366 );
1367 let mut scanning_loop = pin!(scanning_loop);
1368
1369 let first_req_channels = vec![13];
1371 let scan_req_fut1 = scan_requester.perform_scan(
1372 ScanReason::BssSelection,
1373 vec!["foo".try_into().unwrap()],
1374 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1375 );
1376 let mut scan_req_fut1 = pin!(scan_req_fut1);
1377 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1378 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1379
1380 assert_matches!(
1382 exec.run_until_stalled(&mut sme_stream.next()),
1383 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1384 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1386 assert_eq!(req.channels, first_req_channels)
1387 });
1388 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1390 }
1391 );
1392 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1393
1394 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1396 assert_eq!(results, Err(types::ScanError::GeneralError));
1397 });
1398
1399 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1401
1402 let second_req_channels = vec![55];
1404 let scan_req_fut2 = scan_requester.perform_scan(
1405 ScanReason::BssSelection,
1406 vec!["foo".try_into().unwrap()],
1407 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1408 );
1409 let mut scan_req_fut2 = pin!(scan_req_fut2);
1410 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1411 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1412
1413 assert_matches!(
1415 exec.run_until_stalled(&mut sme_stream.next()),
1416 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1417 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1419 assert_eq!(req.channels, second_req_channels)
1420 });
1421 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1423 }
1424 );
1425 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1426
1427 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1429 assert_eq!(results, Err(types::ScanError::GeneralError));
1430 });
1431
1432 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1434 }
1435
1436 #[fuchsia::test]
1437 fn scanning_loop_handles_overlapping_requests() {
1438 let mut exec = fasync::TestExecutor::new();
1439 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1440 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1441 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1442 let (location_sensor, _, _) = MockScanResultConsumer::new();
1443 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1444 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1445 let scanning_loop = serve_scanning_loop(
1446 iface_mgr.clone(),
1447 saved_networks_manager.clone(),
1448 telemetry_sender,
1449 location_sensor,
1450 scan_request_receiver,
1451 );
1452 let mut scanning_loop = pin!(scanning_loop);
1453
1454 let first_req_channels = vec![13];
1456 let scan_req_fut1 = scan_requester.perform_scan(
1457 ScanReason::BssSelection,
1458 vec!["foo".try_into().unwrap()],
1459 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1460 );
1461 let mut scan_req_fut1 = pin!(scan_req_fut1);
1462 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1463 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1464
1465 let responder1 = assert_matches!(
1467 exec.run_until_stalled(&mut sme_stream.next()),
1468 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1469 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1471 assert_eq!(req.channels, first_req_channels)
1472 });
1473 responder
1474 }
1475 );
1476 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1477
1478 let second_req_channels = vec![55];
1480 let scan_req_fut2 = scan_requester.perform_scan(
1481 ScanReason::BssSelection,
1482 vec!["foo".try_into().unwrap()],
1483 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1484 );
1485 let mut scan_req_fut2 = pin!(scan_req_fut2);
1486 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1487 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1488
1489 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1491 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1492 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1494
1495 responder1
1497 .send(Err(fidl_sme::ScanErrorCode::InternalError))
1498 .expect("failed to send scan error");
1499 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1500
1501 assert_matches!(
1503 exec.run_until_stalled(&mut sme_stream.next()),
1504 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1505 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1507 assert_eq!(req.channels, second_req_channels)
1508 });
1509 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1511 }
1512 );
1513 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1514
1515 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1517 assert_eq!(results, Err(types::ScanError::GeneralError));
1518 });
1519 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1520 assert_eq!(results, Err(types::ScanError::GeneralError));
1521 });
1522
1523 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1525 }
1526
1527 #[fuchsia::test]
1528 fn scanning_loop_sends_results_to_requester_and_location_sensor() {
1529 let mut exec = fasync::TestExecutor::new();
1530 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1531 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1532 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1533 let (location_sensor, location_sensor_results, _) = MockScanResultConsumer::new();
1534 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1535 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1536 let scanning_loop = serve_scanning_loop(
1537 iface_mgr.clone(),
1538 saved_networks_manager.clone(),
1539 telemetry_sender,
1540 location_sensor,
1541 scan_request_receiver,
1542 );
1543 let mut scanning_loop = pin!(scanning_loop);
1544
1545 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1547 let mut scan_req_fut = pin!(scan_req_fut);
1548 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1549 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1550
1551 assert_matches!(
1553 exec.run_until_stalled(&mut sme_stream.next()),
1554 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1555 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1556 let vmo = write_vmo(results).expect("failed to write VMO");
1557 responder.send(Ok(vmo)).expect("failed to send scan error");
1558 }
1559 );
1560 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1561
1562 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1564 assert_eq!(results.len(), 2);
1565 });
1566
1567 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1569 assert_matches!(
1570 &*exec.run_singlethreaded(location_sensor_results.lock()),
1571 Some(results) => {
1572 assert_eq!(results.len(), 2);
1573 }
1574 );
1575 }
1576
1577 #[fuchsia::test]
1578 fn scanning_loop_location_sensor_timeout_works() {
1579 let mut exec = fasync::TestExecutor::new();
1580 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1581 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1582 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1583 let (location_sensor, location_sensor_results, location_sensor_stalled) =
1584 MockScanResultConsumer::new();
1585 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1586 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1587 let scanning_loop = serve_scanning_loop(
1588 iface_mgr.clone(),
1589 saved_networks_manager.clone(),
1590 telemetry_sender,
1591 location_sensor,
1592 scan_request_receiver,
1593 );
1594 let mut scanning_loop = pin!(scanning_loop);
1595
1596 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = true;
1598
1599 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1601 let mut scan_req_fut = pin!(scan_req_fut);
1602 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1603 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1604
1605 assert_matches!(
1607 exec.run_until_stalled(&mut sme_stream.next()),
1608 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1609 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1610 let vmo = write_vmo(results).expect("failed to write VMO");
1611 responder.send(Ok(vmo)).expect("failed to send scan error");
1612 }
1613 );
1614 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1615
1616 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1618 assert_matches!(&*exec.run_singlethreaded(location_sensor_results.lock()), None);
1619
1620 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = false;
1622
1623 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1625 let mut scan_req_fut = pin!(scan_req_fut);
1626 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1627 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1628
1629 assert_matches!(
1631 exec.run_until_stalled(&mut sme_stream.next()),
1632 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1633 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1634 let vmo = write_vmo(results).expect("failed to write VMO");
1635 responder.send(Ok(vmo)).expect("failed to send scan error");
1636 }
1637 );
1638 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1639
1640 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1642 assert_matches!(
1643 &*exec.run_singlethreaded(location_sensor_results.lock()),
1644 Some(results) => {
1645 assert_eq!(results.len(), 2);
1646 }
1647 );
1648 }
1649
1650 #[fuchsia::test]
1651 fn scanning_loops_sends_inspect_data_to_telemetry() {
1652 let mut exec = fasync::TestExecutor::new();
1653 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1654 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1655 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
1656 let (location_sensor, _, _) = MockScanResultConsumer::new();
1657 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1658 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1659 let scanning_loop = serve_scanning_loop(
1660 iface_mgr.clone(),
1661 saved_networks_manager.clone(),
1662 telemetry_sender,
1663 location_sensor,
1664 scan_request_receiver,
1665 );
1666 let mut scanning_loop = pin!(scanning_loop);
1667
1668 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1670 let mut scan_req_fut = pin!(scan_req_fut);
1671 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1672 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1673
1674 let bss_description = fake_bss_description!(Wpa2, ies_overrides: IesOverrides::new().set(IeType::RSNE, fake_unknown_rsne()[2..].to_vec()));
1676 let scan_result = fidl_sme::ScanResult {
1677 bss_description: bss_description.into(),
1678 ..generate_random_sme_scan_result()
1679 };
1680
1681 assert_matches!(
1683 exec.run_until_stalled(&mut sme_stream.next()),
1684 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1685 req, responder,
1686 }))) => {
1687 assert_eq!(req, passive_sme_req());
1688 let vmo = write_vmo(vec![scan_result.clone()]).expect("failed to write VMO");
1689 responder.send(Ok(vmo)).expect("failed to send scan data");
1690 }
1691 );
1692
1693 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1695
1696 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1698 assert_eq!(results.len(), 1);
1699 });
1700
1701 let readable_ie: String =
1703 scan_result.bss_description.ies.iter().map(|n| n.to_string()).join(",");
1704 assert_matches!(
1705 telemetry_receiver.try_next(),
1706 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
1707 assert_eq!(scan_defects, vec![]);
1708 assert_eq!(inspect_data.unknown_protection_ies, vec![readable_ie]);
1709 });
1710 }
1711
1712 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, false; "Scan error ShouldWait with failed retry")]
1713 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, true; "Scan error ShouldWait with successful retry")]
1714 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, true; "Scan error CanceledByDriverOrFirmware with successful retry")]
1715 #[fuchsia::test]
1716 fn scanning_loop_retries_cancelled_request_once(
1717 error_code: fidl_sme::ScanErrorCode,
1718 retry_succeeds: bool,
1719 ) {
1720 let mut exec = fasync::TestExecutor::new_with_fake_time();
1721 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1722 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1723 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1724 let (location_sensor, _, _) = MockScanResultConsumer::new();
1725 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1726 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1727 let scanning_loop = serve_scanning_loop(
1728 iface_mgr.clone(),
1729 saved_networks_manager.clone(),
1730 telemetry_sender,
1731 location_sensor,
1732 scan_request_receiver,
1733 );
1734 let mut scanning_loop = pin!(scanning_loop);
1735
1736 let req_channels = vec![13];
1738 let scan_req_fut = scan_requester.perform_scan(
1739 ScanReason::BssSelection,
1740 vec!["foo".try_into().unwrap()],
1741 req_channels.iter().map(|c| generate_channel(*c)).collect(),
1742 );
1743 let mut scan_req_fut = pin!(scan_req_fut);
1744 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1745 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1746
1747 let responder = assert_matches!(
1749 exec.run_until_stalled(&mut sme_stream.next()),
1750 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1751 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1753 assert_eq!(req.channels, req_channels)
1754 });
1755 responder
1756 }
1757 );
1758 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1759
1760 responder.send(Err(error_code)).expect("failed to send scan error");
1762 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1763
1764 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1766
1767 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1769
1770 assert!(exec.wake_next_timer().is_some());
1772 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1773
1774 let responder = assert_matches!(
1776 exec.run_until_stalled(&mut sme_stream.next()),
1777 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1778 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1779 assert_eq!(req.channels, req_channels)
1780 });
1781 responder
1782 }
1783 );
1784
1785 if retry_succeeds {
1786 let MockScanData { sme_results: input_aps, internal_results: _internal_aps } =
1789 create_scan_ap_data(types::ScanObservation::Passive);
1790 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1791 responder.send(Ok(vmo)).expect("failed to send scan data");
1792 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1793
1794 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1796 let expected_defects = vec![Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })];
1797 assert_eq!(logged_defects, expected_defects);
1798 } else {
1799 responder.send(Err(error_code)).expect("failed to send scan error");
1801 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1802
1803 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1805 let expected_defects = vec![
1806 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1807 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1808 ];
1809 assert_eq!(logged_defects, expected_defects);
1810 }
1811 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(_));
1813
1814 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1816 }
1817
1818 #[fuchsia::test]
1819 fn scanning_loop_backs_off_after_cancelled_request() {
1820 let mut exec = fasync::TestExecutor::new_with_fake_time();
1821 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1822 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1823 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1824 let (location_sensor, _, _) = MockScanResultConsumer::new();
1825 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1826 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1827 let scanning_loop = serve_scanning_loop(
1828 iface_mgr.clone(),
1829 saved_networks_manager.clone(),
1830 telemetry_sender,
1831 location_sensor,
1832 scan_request_receiver,
1833 );
1834 let mut scanning_loop = pin!(scanning_loop);
1835
1836 let first_req_channels = vec![13];
1838 let scan_req_fut1 = scan_requester.perform_scan(
1839 ScanReason::BssSelection,
1840 vec!["foo".try_into().unwrap()],
1841 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1842 );
1843 let mut scan_req_fut1 = pin!(scan_req_fut1);
1844 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1845 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1846
1847 let responder = assert_matches!(
1849 exec.run_until_stalled(&mut sme_stream.next()),
1850 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1851 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1853 assert_eq!(req.channels, first_req_channels)
1854 });
1855 responder
1856 }
1857 );
1858
1859 let second_req_channels = vec![55];
1861 let scan_req_fut2 = scan_requester.perform_scan(
1862 ScanReason::BssSelection,
1863 vec!["foo".try_into().unwrap()],
1864 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1865 );
1866 let mut scan_req_fut2 = pin!(scan_req_fut2);
1867 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1868 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1869
1870 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1872
1873 responder
1875 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1876 .expect("failed to send scan error");
1877 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1878
1879 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1881
1882 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1885
1886 assert!(exec.wake_next_timer().is_some());
1888 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1889
1890 let responder = assert_matches!(
1892 exec.run_until_stalled(&mut sme_stream.next()),
1893 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1894 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1896 assert_eq!(req.channels, first_req_channels)
1897 });
1898 responder
1899 }
1900 );
1901
1902 responder
1904 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1905 .expect("failed to send scan error");
1906 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1907
1908 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1910 assert_eq!(results, Err(types::ScanError::Cancelled));
1911 });
1912
1913 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1916
1917 assert!(exec.wake_next_timer().is_some());
1919 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1920
1921 assert_matches!(
1923 exec.run_until_stalled(&mut sme_stream.next()),
1924 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, .. }))) => {
1925 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1927 assert_eq!(req.channels, second_req_channels)
1928 });
1929 }
1930 );
1931 }
1932}