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 telemetry_sender.send(TelemetryEvent::SmeScanStart);
294 let scan_results = sme_scan(&sme_proxy, &scan_request.sme_req, &mut scan_defects).await;
295 let sme_scan_result = match &scan_results {
296 Ok(results) => wlan_telemetry::ScanResult::Complete { num_results: results.len() },
297 Err(types::ScanError::Cancelled) => wlan_telemetry::ScanResult::Cancelled,
298 Err(_) => wlan_telemetry::ScanResult::Failed,
299 };
300 telemetry_sender.send(TelemetryEvent::SmeScanResult { result: sme_scan_result });
301 report_scan_defects_to_sme(&sme_proxy, &scan_results, &scan_request.sme_req).await;
302
303 match scan_results {
304 Ok(results) => {
305 let target_ssids = match scan_request.sme_req {
307 fidl_sme::ScanRequest::Passive(_) => vec![],
308 fidl_sme::ScanRequest::Active(ref req) => req
309 .ssids
310 .iter()
311 .map(|s| types::Ssid::from_bytes_unchecked(s.to_vec()))
312 .collect(),
313 };
314 bss_by_network =
315 bss_to_network_map(results, &target_ssids, &mut scan_event_inspect_data);
316 saved_networks_manager.record_scan_result(target_ssids, &bss_by_network).await;
317 }
318 Err(scan_err) => {
319 return (scan_request, Err(scan_err));
320 }
321 }
322
323 if let fidl_sme::ScanRequest::Passive(_) = scan_request.sme_req
325 && bss_by_network.is_empty()
326 {
327 scan_defects.push(ScanIssue::EmptyScanResults);
328 }
329
330 telemetry_sender
331 .send(TelemetryEvent::ScanEvent { inspect_data: scan_event_inspect_data, scan_defects });
332
333 let scan_results = network_map_to_scan_result(bss_by_network);
334 (scan_request, Ok(scan_results))
335}
336
337pub struct LocationSensorUpdater {}
340#[async_trait(?Send)]
341impl ScanResultUpdate for LocationSensorUpdater {
342 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>) {
343 async fn send_results(scan_results: Vec<fidl_policy::ScanResult>) -> Result<(), Error> {
344 let (iter, server) =
346 fidl::endpoints::create_endpoints::<fidl_policy::ScanResultIteratorMarker>();
347 let location_watcher_proxy =
348 connect_to_protocol::<fidl_location_sensor::WlanBaseStationWatcherMarker>()
349 .map_err(|err| {
350 format_err!("failed to connect to location sensor service: {:?}", err)
351 })?;
352 location_watcher_proxy
353 .report_current_stations(iter)
354 .map_err(|err| format_err!("failed to call location sensor service: {:?}", err))?;
355
356 fidl_conversion::send_scan_results_over_fidl(server, &scan_results).await
358 }
359
360 let scan_results = fidl_conversion::scan_result_to_policy_scan_result(&scan_results);
361 if let Err(e) = send_results(scan_results).await {
364 info!("Failed to send scan results to location sensor: {:?}", e)
365 } else {
366 debug!("Updated location sensor")
367 };
368 }
369}
370
371fn bss_to_network_map(
374 scan_result_list: Vec<wlan_common::scan::ScanResult>,
375 target_ssids: &[types::Ssid],
376 scan_event_inspect_data: &mut ScanEventInspectData,
377) -> HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> {
378 let mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> =
379 HashMap::new();
380 for scan_result in scan_result_list.into_iter() {
381 let security_type: types::SecurityTypeDetailed =
382 scan_result.bss_description.protection().into();
383 if security_type == types::SecurityTypeDetailed::Unknown {
384 let readable_ie =
386 scan_result.bss_description.ies().iter().map(|n| n.to_string()).join(",");
387 debug!("Encountered unknown protection, ies: [{:?}]", readable_ie);
388 scan_event_inspect_data.unknown_protection_ies.push(readable_ie);
389 };
390 let entry = bss_by_network
391 .entry(types::NetworkIdentifierDetailed {
392 ssid: scan_result.bss_description.ssid.clone(),
393 security_type,
394 })
395 .or_default();
396
397 if !entry.iter().any(|existing_bss| existing_bss.bssid == scan_result.bss_description.bssid)
399 {
400 entry.push(types::Bss {
401 bssid: scan_result.bss_description.bssid,
402 signal: types::Signal {
403 rssi_dbm: scan_result.bss_description.rssi_dbm,
404 snr_db: scan_result.bss_description.snr_db,
405 },
406 channel: scan_result.bss_description.channel,
407 timestamp: scan_result.timestamp,
408 observation: if target_ssids.contains(&scan_result.bss_description.ssid) {
410 types::ScanObservation::Active
411 } else {
412 types::ScanObservation::Passive
413 },
414 compatibility: scan_result.compatibility,
415 bss_description: wlan_common::sequestered::Sequestered::from(
416 fidl_fuchsia_wlan_ieee80211::BssDescription::from(scan_result.bss_description),
417 ),
418 });
419 };
420 }
421 bss_by_network
422}
423
424fn network_map_to_scan_result(
425 mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>>,
426) -> Vec<types::ScanResult> {
427 let mut scan_results: Vec<types::ScanResult> = bss_by_network
428 .drain()
429 .map(|(types::NetworkIdentifierDetailed { ssid, security_type }, bss_entries)| {
430 let compatibility = if bss_entries.iter().any(|bss| bss.is_compatible()) {
431 fidl_policy::Compatibility::Supported
432 } else {
433 fidl_policy::Compatibility::DisallowedNotSupported
434 };
435 types::ScanResult {
436 ssid,
437 security_type_detailed: security_type,
438 entries: bss_entries,
439 compatibility,
440 }
441 })
442 .collect();
443
444 scan_results.sort_by(|a, b| a.ssid.cmp(&b.ssid));
445 scan_results
446}
447
448fn log_metric_for_scan_error(reason: &fidl_sme::ScanErrorCode, scan_defects: &mut Vec<ScanIssue>) {
449 let metric_type = match *reason {
450 fidl_sme::ScanErrorCode::NotSupported
451 | fidl_sme::ScanErrorCode::InternalError
452 | fidl_sme::ScanErrorCode::InternalMlmeError => ScanIssue::ScanFailure,
453 fidl_sme::ScanErrorCode::ShouldWait
454 | fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware => ScanIssue::AbortedScan,
455 };
456
457 scan_defects.push(metric_type);
458}
459
460async fn report_scan_defects_to_sme(
461 sme_proxy: &SmeForScan,
462 scan_result: &Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
463 scan_request: &fidl_sme::ScanRequest,
464) {
465 match scan_result {
466 Ok(results) => {
467 if results.is_empty()
469 && let fidl_sme::ScanRequest::Passive(_) = scan_request
470 {
471 sme_proxy.log_empty_scan_defect();
472 }
473 }
474 Err(types::ScanError::GeneralError) => sme_proxy.log_failed_scan_defect(),
475 Err(types::ScanError::Cancelled) => sme_proxy.log_aborted_scan_defect(),
476 }
477}
478
479#[cfg(test)]
480mod tests {
481 use super::*;
482 use crate::access_point::state_machine as ap_fsm;
483 use crate::mode_management::iface_manager_api::ConnectAttemptRequest;
484 use crate::mode_management::{Defect, IfaceFailure};
485 use crate::util::testing::fakes::FakeSavedNetworksManager;
486 use crate::util::testing::{
487 generate_channel, generate_random_sme_scan_result, run_until_completion,
488 };
489 use assert_matches::assert_matches;
490 use fidl::endpoints::{ControlHandle, Responder, create_proxy};
491 use fidl_fuchsia_wlan_ieee80211::WlanBand::{FiveGhz, TwoGhz};
492 use fidl_fuchsia_wlan_internal as fidl_internal;
493 use fuchsia_async as fasync;
494 use futures::future;
495 use futures::task::Poll;
496 use std::pin::pin;
497 use test_case::test_case;
498 use wlan_common::ie::IeType;
499 use wlan_common::scan::{Compatible, Incompatible, write_vmo};
500 use wlan_common::security::SecurityDescriptor;
501 use wlan_common::test_utils::fake_frames::fake_unknown_rsne;
502 use wlan_common::test_utils::fake_stas::IesOverrides;
503 use wlan_common::{fake_bss_description, random_fidl_bss_description};
504
505 fn active_sme_req(ssids: Vec<&str>, channels: Vec<u8>) -> fidl_sme::ScanRequest {
506 fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
507 ssids: ssids.iter().map(|s| s.as_bytes().to_vec()).collect(),
508 channels,
509 })
510 }
511
512 fn passive_sme_req() -> fidl_sme::ScanRequest {
513 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] })
514 }
515
516 struct FakeIfaceManager {
517 pub sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
518 pub defect_sender: mpsc::Sender<Defect>,
519 pub defect_receiver: mpsc::Receiver<Defect>,
520 }
521
522 impl FakeIfaceManager {
523 pub fn new(proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy) -> Self {
524 let (defect_sender, defect_receiver) = mpsc::channel(100);
525 FakeIfaceManager { sme_proxy: proxy, defect_sender, defect_receiver }
526 }
527 }
528
529 #[async_trait(?Send)]
530 impl IfaceManagerApi for FakeIfaceManager {
531 async fn disconnect(
532 &mut self,
533 _network_id: types::NetworkIdentifier,
534 _reason: types::DisconnectReason,
535 ) -> Result<(), Error> {
536 unimplemented!()
537 }
538
539 async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
540 unimplemented!()
541 }
542
543 async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
544 unimplemented!()
545 }
546
547 async fn has_idle_client(&mut self) -> Result<bool, Error> {
548 unimplemented!()
549 }
550
551 async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
552 unimplemented!()
553 }
554
555 async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
556 unimplemented!()
557 }
558
559 async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
560 Ok(SmeForScan::new(self.sme_proxy.clone(), 0, self.defect_sender.clone()))
561 }
562
563 async fn stop_client_connections(
564 &mut self,
565 _reason: types::DisconnectReason,
566 ) -> Result<(), Error> {
567 unimplemented!()
568 }
569
570 async fn start_client_connections(&mut self) -> Result<(), Error> {
571 unimplemented!()
572 }
573
574 async fn start_ap(
575 &mut self,
576 _config: ap_fsm::ApConfig,
577 ) -> Result<oneshot::Receiver<()>, Error> {
578 unimplemented!()
579 }
580
581 async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
582 unimplemented!()
583 }
584
585 async fn stop_all_aps(&mut self) -> Result<(), Error> {
586 unimplemented!()
587 }
588
589 async fn set_country(
590 &mut self,
591 _country_code: Option<types::CountryCode>,
592 ) -> Result<(), Error> {
593 unimplemented!()
594 }
595 }
596
597 async fn create_iface_manager()
599 -> (Arc<Mutex<FakeIfaceManager>>, fidl_sme::ClientSmeRequestStream) {
600 let (client_sme, remote) = create_proxy::<fidl_sme::ClientSmeMarker>();
601 let iface_manager = FakeIfaceManager::new(client_sme);
602 let iface_manager = Arc::new(Mutex::new(iface_manager));
603 (iface_manager, remote.into_stream())
604 }
605
606 async fn create_sme_proxy() -> (fidl_sme::ClientSmeProxy, fidl_sme::ClientSmeRequestStream) {
608 let (client_sme, remote) = create_proxy::<fidl_sme::ClientSmeMarker>();
609 (client_sme, remote.into_stream())
610 }
611
612 struct MockScanResultConsumer {
613 scan_results: Arc<Mutex<Option<Vec<types::ScanResult>>>>,
614 stalled: Arc<Mutex<bool>>,
615 }
616 impl MockScanResultConsumer {
617 #[allow(clippy::type_complexity)]
618 fn new() -> (Self, Arc<Mutex<Option<Vec<types::ScanResult>>>>, Arc<Mutex<bool>>) {
619 let scan_results = Arc::new(Mutex::new(None));
620 let stalled = Arc::new(Mutex::new(false));
621 (
622 Self { scan_results: scan_results.clone(), stalled: stalled.clone() },
623 scan_results,
624 stalled,
625 )
626 }
627 }
628 #[async_trait(?Send)]
629 impl ScanResultUpdate for MockScanResultConsumer {
630 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>) {
631 if *self.stalled.lock().await {
632 let () = future::pending().await;
633 unreachable!();
634 }
635 let mut guard = self.scan_results.lock().await;
636 *guard = Some(scan_results);
637 }
638 }
639
640 struct MockScanData {
642 sme_results: Vec<fidl_sme::ScanResult>,
643 internal_results: Vec<types::ScanResult>,
644 }
645 fn create_scan_ap_data(observation: types::ScanObservation) -> MockScanData {
646 let sme_result_1 = fidl_sme::ScanResult {
647 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
648 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
649 }),
650 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
651 bss_description: random_fidl_bss_description!(
652 Wpa3,
653 bssid: [0, 0, 0, 0, 0, 0],
654 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
655 rssi_dbm: 0,
656 snr_db: 1,
657 channel: types::WlanChan::new(1, types::Bandwidth::Cbw20, TwoGhz),
658 ),
659 };
660 let sme_result_2 = fidl_sme::ScanResult {
661 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
662 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa2Personal],
663 }),
664 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
665 bss_description: random_fidl_bss_description!(
666 Wpa2,
667 bssid: [1, 2, 3, 4, 5, 6],
668 ssid: types::Ssid::try_from("unique ssid").unwrap(),
669 rssi_dbm: 7,
670 snr_db: 2,
671 channel: types::WlanChan::new(8, types::Bandwidth::Cbw20, TwoGhz),
672 ),
673 };
674 let sme_result_3 = fidl_sme::ScanResult {
675 compatibility: fidl_sme::Compatibility::Incompatible(fidl_sme::Incompatible {
676 description: String::from("unknown"),
677 disjoint_security_protocols: None,
678 }),
679 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
680 bss_description: random_fidl_bss_description!(
681 Wpa3,
682 bssid: [7, 8, 9, 10, 11, 12],
683 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
684 rssi_dbm: 13,
685 snr_db: 3,
686 channel: types::WlanChan::new(11, types::Bandwidth::Cbw20, TwoGhz),
687 ),
688 };
689
690 let sme_results = vec![sme_result_1.clone(), sme_result_2.clone(), sme_result_3.clone()];
691 let internal_results = vec![
694 types::ScanResult {
695 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
696 security_type_detailed: types::SecurityTypeDetailed::Wpa3Personal,
697 entries: vec![
698 types::Bss {
699 bssid: types::Bssid::from([0, 0, 0, 0, 0, 0]),
700 signal: types::Signal { rssi_dbm: 0, snr_db: 1 },
701 timestamp: zx::MonotonicInstant::from_nanos(sme_result_1.timestamp_nanos),
702 channel: types::WlanChan::new(1, types::Bandwidth::Cbw20, TwoGhz),
703 observation,
704 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
705 bss_description: sme_result_1.bss_description.clone().into(),
706 },
707 types::Bss {
708 bssid: types::Bssid::from([7, 8, 9, 10, 11, 12]),
709 signal: types::Signal { rssi_dbm: 13, snr_db: 3 },
710 timestamp: zx::MonotonicInstant::from_nanos(sme_result_3.timestamp_nanos),
711 channel: types::WlanChan::new(11, types::Bandwidth::Cbw20, TwoGhz),
712 observation,
713 compatibility: Incompatible::unknown(),
714 bss_description: sme_result_3.bss_description.clone().into(),
715 },
716 ],
717 compatibility: types::Compatibility::Supported,
718 },
719 types::ScanResult {
720 ssid: types::Ssid::try_from("unique ssid").unwrap(),
721 security_type_detailed: types::SecurityTypeDetailed::Wpa2Personal,
722 entries: vec![types::Bss {
723 bssid: types::Bssid::from([1, 2, 3, 4, 5, 6]),
724 signal: types::Signal { rssi_dbm: 7, snr_db: 2 },
725 timestamp: zx::MonotonicInstant::from_nanos(sme_result_2.timestamp_nanos),
726 channel: types::WlanChan::new(8, types::Bandwidth::Cbw20, TwoGhz),
727 observation,
728 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA2_PERSONAL]),
729 bss_description: sme_result_2.bss_description.clone().into(),
730 }],
731 compatibility: types::Compatibility::Supported,
732 },
733 ];
734
735 MockScanData { sme_results, internal_results }
736 }
737
738 fn create_telemetry_sender_and_receiver() -> (TelemetrySender, mpsc::Receiver<TelemetryEvent>) {
739 let (sender, receiver) = mpsc::channel::<TelemetryEvent>(100);
740 let sender = TelemetrySender::new(sender);
741 (sender, receiver)
742 }
743
744 fn get_fake_defects(
745 exec: &mut fasync::TestExecutor,
746 iface_manager: Arc<Mutex<FakeIfaceManager>>,
747 ) -> Vec<Defect> {
748 let defects_fut = async move {
749 let mut iface_manager = iface_manager.lock().await;
750 let mut defects = Vec::<Defect>::new();
751 while let Ok(defect) = iface_manager.defect_receiver.try_recv() {
752 defects.push(defect)
753 }
754
755 defects
756 };
757 let mut defects_fut = pin!(defects_fut);
758 assert_matches!(exec.run_until_stalled(&mut defects_fut), Poll::Ready(defects) => defects)
759 }
760
761 #[fuchsia::test]
762 fn sme_scan_with_passive_request() {
763 let mut exec = fasync::TestExecutor::new();
764 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
765 let (defect_sender, _) = mpsc::channel(100);
766 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
767
768 let scan_request =
770 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] });
771 let mut scan_defects = vec![];
772 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
773 let mut scan_fut = pin!(scan_fut);
774
775 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
777
778 let MockScanData { sme_results: input_aps, internal_results: _ } =
780 create_scan_ap_data(types::ScanObservation::Passive);
781 assert_matches!(
783 exec.run_until_stalled(&mut sme_stream.next()),
784 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
785 req, responder,
786 }))) => {
787 assert_eq!(req, scan_request);
788 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
789 responder.send(Ok(vmo)).expect("failed to send scan data");
790 }
791 );
792
793 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
795 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
796 .iter().map(|r| r.clone().into()).collect();
797 assert_eq!(scan_results, input_aps);
798 });
799
800 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
802 }
803
804 #[fuchsia::test]
805 fn sme_scan_with_active_request() {
806 let mut exec = fasync::TestExecutor::new();
807 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
808 let (defect_sender, _) = mpsc::channel(100);
809 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
810
811 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
813 ssids: vec![
814 types::Ssid::try_from("foo_ssid").unwrap().into(),
815 types::Ssid::try_from("bar_ssid").unwrap().into(),
816 ],
817 channels: vec![1, 20],
818 });
819 let mut scan_defects = vec![];
820 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
821 let mut scan_fut = pin!(scan_fut);
822
823 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
825
826 let MockScanData { sme_results: input_aps, internal_results: _ } =
828 create_scan_ap_data(types::ScanObservation::Active);
829 assert_matches!(
831 exec.run_until_stalled(&mut sme_stream.next()),
832 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
833 req, responder,
834 }))) => {
835 assert_eq!(req, scan_request);
836 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
837 responder.send(Ok(vmo)).expect("failed to send scan data");
838 }
839 );
840
841 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
843 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
844 .iter().map(|r| r.clone().into()).collect();
845 assert_eq!(scan_results, input_aps);
846 });
847
848 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
850 }
851
852 #[fuchsia::test]
853 fn sme_channel_closed_while_awaiting_scan_results() {
854 let mut exec = fasync::TestExecutor::new();
855 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
856 let (defect_sender, _) = mpsc::channel(100);
857 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
858
859 let scan_request =
861 fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest { channels: vec![] });
862 let mut scan_defects = vec![];
863 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
864 let mut scan_fut = pin!(scan_fut);
865
866 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
868
869 assert_matches!(
871 exec.run_until_stalled(&mut sme_stream.next()),
872 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
873 req: _, responder,
874 }))) => {
875 responder.control_handle().shutdown();
877 drop(sme_stream);
879 }
880 );
881
882 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
884 let error = result.expect_err("did not expect scan results");
885 assert_eq!(error, types::ScanError::GeneralError);
886 });
887 }
888
889 #[fuchsia::test]
890 fn basic_scan() {
891 let mut exec = fasync::TestExecutor::new();
892 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
893 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
894 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
895 let sme_scan = passive_sme_req();
897 let scan_fut =
898 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
899 let mut scan_fut = pin!(scan_fut);
900
901 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
903
904 let MockScanData { sme_results: input_aps, internal_results: internal_aps } =
906 create_scan_ap_data(types::ScanObservation::Passive);
907 assert_matches!(
908 exec.run_until_stalled(&mut sme_stream.next()),
909 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
910 req, responder,
911 }))) => {
912 assert_eq!(req, sme_scan.clone());
913 let vmo = write_vmo(input_aps).expect("failed to write VMO");
914 responder.send(Ok(vmo)).expect("failed to send scan data");
915 }
916 );
917
918 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
920 assert_eq!(request.sme_req, sme_scan);
921 assert_eq!(results.unwrap(), internal_aps);
922 });
923
924 assert_matches!(telemetry_receiver.try_recv(), Ok(TelemetryEvent::SmeScanStart));
927 assert_matches!(
928 telemetry_receiver.try_recv(),
929 Ok(TelemetryEvent::SmeScanResult {
930 result: wlan_telemetry::ScanResult::Complete { num_results: 3 }
931 })
932 );
933 assert_matches!(
934 telemetry_receiver.try_recv(),
935 Ok(TelemetryEvent::ScanEvent {inspect_data, scan_defects}) => {
936 assert_eq!(inspect_data, ScanEventInspectData::new());
937 assert_eq!(scan_defects, vec![]);
938 });
939 }
940
941 #[fuchsia::test]
942 fn empty_passive_scan_results() {
943 let mut exec = fasync::TestExecutor::new();
944 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
945 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
946 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
947
948 let sme_scan = passive_sme_req();
950 let scan_fut = perform_scan(
951 sme_scan.clone().into(),
952 client.clone(),
953 saved_networks_manager,
954 telemetry_sender,
955 );
956 let mut scan_fut = pin!(scan_fut);
957
958 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
960
961 assert_matches!(
963 exec.run_until_stalled(&mut sme_stream.next()),
964 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
965 req, responder,
966 }))) => {
967 assert_eq!(req, sme_scan.clone());
968 let vmo = write_vmo(vec![]).expect("failed to write VMO");
969 responder.send(Ok(vmo)).expect("failed to send scan data");
970 }
971 );
972
973 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
975 assert_eq!(request.sme_req, sme_scan);
976 assert!(results.unwrap().is_empty());
977 });
978
979 assert_matches!(telemetry_receiver.try_recv(), Ok(TelemetryEvent::SmeScanStart));
981 assert_matches!(
982 telemetry_receiver.try_recv(),
983 Ok(TelemetryEvent::SmeScanResult {
984 result: wlan_telemetry::ScanResult::Complete { num_results: 0 }
985 })
986 );
987 assert_matches!(
988 telemetry_receiver.try_recv(),
989 Ok(TelemetryEvent::ScanEvent {inspect_data, scan_defects}) => {
990 assert_eq!(inspect_data, ScanEventInspectData::new());
991 assert_eq!(scan_defects, vec![ScanIssue::EmptyScanResults]);
992 });
993
994 let logged_defects = get_fake_defects(&mut exec, client);
996 let expected_defects = vec![Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })];
997 assert_eq!(logged_defects, expected_defects);
998 }
999
1000 #[fuchsia::test]
1001 fn empty_active_scan_results() {
1002 let mut exec = fasync::TestExecutor::new();
1003 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1004 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1005 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
1006
1007 let sme_scan = active_sme_req(vec!["foo"], vec![]);
1009 let scan_fut = perform_scan(
1010 sme_scan.clone().into(),
1011 client.clone(),
1012 saved_networks_manager,
1013 telemetry_sender,
1014 );
1015 let mut scan_fut = pin!(scan_fut);
1016
1017 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1019
1020 assert_matches!(
1022 exec.run_until_stalled(&mut sme_stream.next()),
1023 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1024 req, responder,
1025 }))) => {
1026 assert_eq!(req, sme_scan.clone());
1027 let vmo = write_vmo(vec![]).expect("failed to write VMO");
1028 responder.send(Ok(vmo)).expect("failed to send scan data");
1029 }
1030 );
1031
1032 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1034 assert_eq!(request.sme_req, sme_scan);
1035 assert!(results.unwrap().is_empty());
1036 });
1037
1038 assert_matches!(telemetry_receiver.try_recv(), Ok(TelemetryEvent::SmeScanStart));
1041 assert_matches!(
1042 telemetry_receiver.try_recv(),
1043 Ok(TelemetryEvent::SmeScanResult {
1044 result: wlan_telemetry::ScanResult::Complete { num_results: 0 }
1045 })
1046 );
1047 assert_matches!(telemetry_receiver.try_recv(), Ok(TelemetryEvent::ScanEvent { scan_defects, .. }) => {
1048 assert!(scan_defects.is_empty());
1049 });
1050
1051 let logged_defects = get_fake_defects(&mut exec, client);
1053 let expected_defects = vec![];
1054 assert_eq!(logged_defects, expected_defects);
1055 }
1056
1057 #[test_case(active_sme_req(vec![], vec![]) ; "active_sme_req, no ssid")]
1059 #[test_case(active_sme_req(vec![""], vec![]) ; "active_sme_req, wildcard ssid")]
1060 #[test_case(active_sme_req(vec!["", "foo"], vec![]) ; "active_sme_req, wildcard and foo ssid")]
1061 #[test_case(active_sme_req(vec!["foo"], vec![]) ; "active_sme_req, foo ssid")]
1062 #[test_case(passive_sme_req())]
1063 #[fuchsia::test(add_test_attr = false)]
1064 fn scan_updates_hidden_network_probabilities(sme_scan_request: fidl_sme::ScanRequest) {
1065 let mut exec = fasync::TestExecutor::new();
1066 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1067 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1068 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1069
1070 let MockScanData { sme_results: input_aps, internal_results: scan_results } =
1072 create_scan_ap_data(types::ScanObservation::Unknown);
1073
1074 let scan_fut = perform_scan(
1076 sme_scan_request.clone().into(),
1077 client,
1078 saved_networks_manager.clone(),
1079 telemetry_sender,
1080 );
1081 let mut scan_fut = pin!(scan_fut);
1082
1083 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1085
1086 assert_matches!(
1088 exec.run_until_stalled(&mut sme_stream.next()),
1089 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1090 req, responder,
1091 }))) => {
1092 assert_eq!(req, sme_scan_request);
1093 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1094 responder.send(Ok(vmo)).expect("failed to send scan data");
1095 }
1096 );
1097
1098 let _ = exec.run_until_stalled(&mut scan_fut);
1101
1102 let target_ssids = match sme_scan_request {
1104 fidl_sme::ScanRequest::Passive(_) => vec![],
1105 fidl_sme::ScanRequest::Active(ref req) => {
1106 req.ssids.iter().map(|s| types::Ssid::from_bytes_unchecked(s.to_vec())).collect()
1107 }
1108 };
1109 let mut scan_results_ids: Vec<types::NetworkIdentifierDetailed> = scan_results
1110 .iter()
1111 .map(|scan_result| types::NetworkIdentifierDetailed {
1112 ssid: scan_result.ssid.clone(),
1113 security_type: scan_result.security_type_detailed,
1114 })
1115 .collect();
1116
1117 let scan_result_record_guard =
1118 exec.run_singlethreaded(saved_networks_manager.scan_result_records.lock());
1119 assert_eq!(scan_result_record_guard.len(), 1);
1120 assert_eq!(scan_result_record_guard[0].0, target_ssids);
1121
1122 let mut recorded_ids = scan_result_record_guard[0]
1124 .1
1125 .keys()
1126 .cloned()
1127 .collect::<Vec<types::NetworkIdentifierDetailed>>();
1128
1129 recorded_ids.sort();
1130 scan_results_ids.sort();
1131 assert_eq!(scan_results_ids, recorded_ids);
1132
1133 }
1136
1137 #[fuchsia::test]
1138 fn bss_to_network_map_duplicated_bss() {
1139 let first_result = fidl_sme::ScanResult {
1141 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1142 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1143 }),
1144 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1145 bss_description: random_fidl_bss_description!(
1146 Wpa3,
1147 bssid: [0, 0, 0, 0, 0, 0],
1148 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1149 rssi_dbm: 0,
1150 snr_db: 1,
1151 channel: types::WlanChan::new(1, types::Bandwidth::Cbw20, TwoGhz),
1152 ),
1153 };
1154 let second_result = fidl_sme::ScanResult {
1155 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1156 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1157 }),
1158 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1159 bss_description: random_fidl_bss_description!(
1160 Wpa3,
1161 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1162 bssid: [1, 2, 3, 4, 5, 6],
1163 rssi_dbm: 101,
1164 snr_db: 101,
1165 channel: types::WlanChan::new(101, types::Bandwidth::Cbw40, FiveGhz),
1166 ),
1167 };
1168
1169 let sme_results = [
1170 first_result.clone(),
1171 second_result.clone(),
1172 fidl_sme::ScanResult {
1174 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1175 mutual_security_protocols: vec![fidl_internal::Protocol::Wpa3Personal],
1176 }),
1177 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1178 bss_description: random_fidl_bss_description!(
1179 Wpa3,
1180 bssid: [0, 0, 0, 0, 0, 0],
1181 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1182 rssi_dbm: 13,
1183 snr_db: 3,
1184 channel: types::WlanChan::new(14, types::Bandwidth::Cbw20, TwoGhz),
1185 ),
1186 },
1187 ];
1188
1189 let expected_id = types::NetworkIdentifierDetailed {
1190 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1191 security_type: types::SecurityTypeDetailed::Wpa3Personal,
1192 };
1193
1194 let expected_bss = vec![
1197 types::Bss {
1198 bssid: types::Bssid::from([0, 0, 0, 0, 0, 0]),
1199 signal: types::Signal { rssi_dbm: 0, snr_db: 1 },
1200 timestamp: zx::MonotonicInstant::from_nanos(first_result.timestamp_nanos),
1201 channel: types::WlanChan::new(1, types::Bandwidth::Cbw20, TwoGhz),
1202 observation: types::ScanObservation::Passive,
1203 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1204 bss_description: first_result.bss_description.clone().into(),
1205 },
1206 types::Bss {
1207 bssid: types::Bssid::from([1, 2, 3, 4, 5, 6]),
1208 signal: types::Signal { rssi_dbm: 101, snr_db: 101 },
1209 timestamp: zx::MonotonicInstant::from_nanos(second_result.timestamp_nanos),
1210 channel: types::WlanChan::new(101, types::Bandwidth::Cbw40, FiveGhz),
1211 observation: types::ScanObservation::Passive,
1212 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1213 bss_description: second_result.bss_description.clone().into(),
1214 },
1215 ];
1216
1217 let bss_by_network = bss_to_network_map(
1218 sme_results
1219 .iter()
1220 .map(|scan_result| {
1221 scan_result.clone().try_into().expect("Failed to convert ScanResult")
1222 })
1223 .collect::<Vec<wlan_common::scan::ScanResult>>(),
1224 &[],
1225 &mut ScanEventInspectData::new(),
1226 );
1227 assert_eq!(bss_by_network.len(), 1);
1228 assert_eq!(bss_by_network[&expected_id], expected_bss);
1229 }
1230
1231 #[test_case(
1232 fidl_sme::ScanErrorCode::InternalError,
1233 types::ScanError::GeneralError,
1234 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1235 )]
1236 #[test_case(
1237 fidl_sme::ScanErrorCode::InternalMlmeError,
1238 types::ScanError::GeneralError,
1239 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1240 )]
1241 #[test_case(
1242 fidl_sme::ScanErrorCode::NotSupported,
1243 types::ScanError::GeneralError,
1244 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1245 )]
1246 #[fuchsia::test(add_test_attr = false)]
1247 fn scan_error_no_retries(
1248 sme_failure_mode: fidl_sme::ScanErrorCode,
1249 policy_failure_mode: types::ScanError,
1250 expected_defect: Defect,
1251 ) {
1252 let mut exec = fasync::TestExecutor::new();
1253 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1254 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1255 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1256
1257 let sme_scan = active_sme_req(vec![], vec![1]);
1259 let scan_fut = perform_scan(
1260 sme_scan.clone().into(),
1261 client.clone(),
1262 saved_networks_manager,
1263 telemetry_sender,
1264 );
1265 let mut scan_fut = pin!(scan_fut);
1266 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1267
1268 assert_matches!(
1270 exec.run_until_stalled(&mut sme_stream.next()),
1271 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1272 responder.send(Err(sme_failure_mode)).expect("failed to send scan error");
1274 }
1275 );
1276
1277 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1279 assert_eq!(request.sme_req, sme_scan);
1280 assert_eq!(results, Err(policy_failure_mode));
1281 });
1282
1283 let logged_defects = get_fake_defects(&mut exec, client);
1285 let expected_defects = vec![expected_defect];
1286 assert_eq!(logged_defects, expected_defects);
1287 }
1288
1289 #[fuchsia::test]
1290 fn scan_returns_error_on_timeout() {
1291 let mut exec = fasync::TestExecutor::new_with_fake_time();
1292 let (client, _sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1293 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1294 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1295
1296 let sme_scan = passive_sme_req();
1298 let scan_fut =
1299 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
1300 let mut scan_fut = pin!(scan_fut);
1301
1302 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1304
1305 assert!(exec.wake_next_timer().is_some());
1307
1308 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1310 assert_eq!(request.sme_req, sme_scan);
1311 assert_eq!(results, Err(types::ScanError::GeneralError));
1312 });
1313 }
1314
1315 #[test_case(fidl_sme::ScanErrorCode::NotSupported, ScanIssue::ScanFailure)]
1316 #[test_case(fidl_sme::ScanErrorCode::InternalError, ScanIssue::ScanFailure)]
1317 #[test_case(fidl_sme::ScanErrorCode::InternalMlmeError, ScanIssue::ScanFailure)]
1318 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, ScanIssue::AbortedScan)]
1319 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, ScanIssue::AbortedScan)]
1320 #[fuchsia::test(add_test_attr = false)]
1321 fn test_scan_error_metric_conversion(
1322 scan_error: fidl_sme::ScanErrorCode,
1323 expected_issue: ScanIssue,
1324 ) {
1325 let mut scan_defects = vec![];
1326 log_metric_for_scan_error(&scan_error, &mut scan_defects);
1327 assert_eq!(scan_defects, vec![expected_issue]);
1328 }
1329
1330 #[test_case(Err(types::ScanError::GeneralError), Some(Defect::Iface(IfaceFailure::FailedScan { iface_id: 0 })))]
1331 #[test_case(Err(types::ScanError::Cancelled), Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })))]
1332 #[test_case(Ok(vec![]), Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })))]
1333 #[test_case(Ok(vec![wlan_common::scan::ScanResult::try_from(
1334 fidl_sme::ScanResult {
1335 bss_description: random_fidl_bss_description!(Wpa2, ssid: types::Ssid::try_from("other ssid").unwrap()),
1336 ..generate_random_sme_scan_result()
1337 },
1338 ).expect("failed scan result conversion")]),
1339 None
1340 )]
1341 #[fuchsia::test(add_test_attr = false)]
1342 fn test_scan_defect_reporting(
1343 scan_result: Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
1344 expected_defect: Option<Defect>,
1345 ) {
1346 let mut exec = fasync::TestExecutor::new();
1347 let (iface_manager, _) = exec.run_singlethreaded(create_iface_manager());
1348 let scan_request = passive_sme_req();
1349
1350 let sme = {
1352 let cloned_iface_manager = iface_manager.clone();
1353 let fut = async move {
1354 let mut iface_manager = cloned_iface_manager.lock().await;
1355 iface_manager.get_sme_proxy_for_scan().await
1356 };
1357 let mut fut = pin!(fut);
1358 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(sme)) => sme)
1359 };
1360
1361 let fut = report_scan_defects_to_sme(&sme, &scan_result, &scan_request);
1363 let mut fut = pin!(fut);
1364 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1365
1366 let logged_defects = get_fake_defects(&mut exec, iface_manager);
1370 match expected_defect {
1371 Some(defect) => {
1372 assert_eq!(logged_defects, vec![defect])
1373 }
1374 None => assert!(logged_defects.is_empty()),
1375 }
1376 }
1377
1378 #[fuchsia::test]
1379 fn scanning_loop_handles_sequential_requests() {
1380 let mut exec = fasync::TestExecutor::new();
1381 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1382 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1383 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1384 let (location_sensor, _, _) = MockScanResultConsumer::new();
1385 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1386 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1387 let scanning_loop = serve_scanning_loop(
1388 iface_mgr.clone(),
1389 saved_networks_manager.clone(),
1390 telemetry_sender,
1391 location_sensor,
1392 scan_request_receiver,
1393 );
1394 let mut scanning_loop = pin!(scanning_loop);
1395
1396 let first_req_channels = vec![13];
1398 let scan_req_fut1 = scan_requester.perform_scan(
1399 ScanReason::BssSelection,
1400 vec!["foo".try_into().unwrap()],
1401 vec![generate_channel(13, fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz)],
1402 );
1403 let mut scan_req_fut1 = pin!(scan_req_fut1);
1404 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1405 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1406
1407 assert_matches!(
1409 exec.run_until_stalled(&mut sme_stream.next()),
1410 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1411 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1413 assert_eq!(req.channels, first_req_channels)
1414 });
1415 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1417 }
1418 );
1419 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1420
1421 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1423 assert_eq!(results, Err(types::ScanError::GeneralError));
1424 });
1425
1426 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1428
1429 let second_req_channels = vec![55];
1431 let scan_req_fut2 = scan_requester.perform_scan(
1432 ScanReason::BssSelection,
1433 vec!["foo".try_into().unwrap()],
1434 vec![generate_channel(55, fidl_fuchsia_wlan_ieee80211::WlanBand::FiveGhz)],
1435 );
1436 let mut scan_req_fut2 = pin!(scan_req_fut2);
1437 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1438 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1439
1440 assert_matches!(
1442 exec.run_until_stalled(&mut sme_stream.next()),
1443 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1444 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1446 assert_eq!(req.channels, second_req_channels)
1447 });
1448 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1450 }
1451 );
1452 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1453
1454 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1456 assert_eq!(results, Err(types::ScanError::GeneralError));
1457 });
1458
1459 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1461 }
1462
1463 #[fuchsia::test]
1464 fn scanning_loop_handles_overlapping_requests() {
1465 let mut exec = fasync::TestExecutor::new();
1466 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1467 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1468 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1469 let (location_sensor, _, _) = MockScanResultConsumer::new();
1470 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1471 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1472 let scanning_loop = serve_scanning_loop(
1473 iface_mgr.clone(),
1474 saved_networks_manager.clone(),
1475 telemetry_sender,
1476 location_sensor,
1477 scan_request_receiver,
1478 );
1479 let mut scanning_loop = pin!(scanning_loop);
1480
1481 let first_req_channels = vec![13];
1483 let scan_req_fut1 = scan_requester.perform_scan(
1484 ScanReason::BssSelection,
1485 vec!["foo".try_into().unwrap()],
1486 vec![generate_channel(13, fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz)],
1487 );
1488 let mut scan_req_fut1 = pin!(scan_req_fut1);
1489 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1490 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1491
1492 let responder1 = assert_matches!(
1494 exec.run_until_stalled(&mut sme_stream.next()),
1495 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1496 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1498 assert_eq!(req.channels, first_req_channels)
1499 });
1500 responder
1501 }
1502 );
1503 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1504
1505 let second_req_channels = vec![55];
1507 let scan_req_fut2 = scan_requester.perform_scan(
1508 ScanReason::BssSelection,
1509 vec!["foo".try_into().unwrap()],
1510 vec![generate_channel(55, fidl_fuchsia_wlan_ieee80211::WlanBand::FiveGhz)],
1511 );
1512 let mut scan_req_fut2 = pin!(scan_req_fut2);
1513 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1514 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1515
1516 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1518 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1519 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1521
1522 responder1
1524 .send(Err(fidl_sme::ScanErrorCode::InternalError))
1525 .expect("failed to send scan error");
1526 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1527
1528 assert_matches!(
1530 exec.run_until_stalled(&mut sme_stream.next()),
1531 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1532 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1534 assert_eq!(req.channels, second_req_channels)
1535 });
1536 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1538 }
1539 );
1540 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1541
1542 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1544 assert_eq!(results, Err(types::ScanError::GeneralError));
1545 });
1546 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1547 assert_eq!(results, Err(types::ScanError::GeneralError));
1548 });
1549
1550 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1552 }
1553
1554 #[fuchsia::test]
1555 fn scanning_loop_sends_results_to_requester_and_location_sensor() {
1556 let mut exec = fasync::TestExecutor::new();
1557 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1558 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1559 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1560 let (location_sensor, location_sensor_results, _) = MockScanResultConsumer::new();
1561 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1562 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1563 let scanning_loop = serve_scanning_loop(
1564 iface_mgr.clone(),
1565 saved_networks_manager.clone(),
1566 telemetry_sender,
1567 location_sensor,
1568 scan_request_receiver,
1569 );
1570 let mut scanning_loop = pin!(scanning_loop);
1571
1572 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1574 let mut scan_req_fut = pin!(scan_req_fut);
1575 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1576 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1577
1578 assert_matches!(
1580 exec.run_until_stalled(&mut sme_stream.next()),
1581 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1582 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1583 let vmo = write_vmo(results).expect("failed to write VMO");
1584 responder.send(Ok(vmo)).expect("failed to send scan error");
1585 }
1586 );
1587 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1588
1589 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1591 assert_eq!(results.len(), 2);
1592 });
1593
1594 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1596 assert_matches!(
1597 &*exec.run_singlethreaded(location_sensor_results.lock()),
1598 Some(results) => {
1599 assert_eq!(results.len(), 2);
1600 }
1601 );
1602 }
1603
1604 #[fuchsia::test]
1605 fn scanning_loop_location_sensor_timeout_works() {
1606 let mut exec = fasync::TestExecutor::new();
1607 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1608 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1609 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1610 let (location_sensor, location_sensor_results, location_sensor_stalled) =
1611 MockScanResultConsumer::new();
1612 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1613 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1614 let scanning_loop = serve_scanning_loop(
1615 iface_mgr.clone(),
1616 saved_networks_manager.clone(),
1617 telemetry_sender,
1618 location_sensor,
1619 scan_request_receiver,
1620 );
1621 let mut scanning_loop = pin!(scanning_loop);
1622
1623 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = true;
1625
1626 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1628 let mut scan_req_fut = pin!(scan_req_fut);
1629 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1630 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1631
1632 assert_matches!(
1634 exec.run_until_stalled(&mut sme_stream.next()),
1635 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1636 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1637 let vmo = write_vmo(results).expect("failed to write VMO");
1638 responder.send(Ok(vmo)).expect("failed to send scan error");
1639 }
1640 );
1641 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1642
1643 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1645 assert_matches!(&*exec.run_singlethreaded(location_sensor_results.lock()), None);
1646
1647 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = false;
1649
1650 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1652 let mut scan_req_fut = pin!(scan_req_fut);
1653 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1654 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1655
1656 assert_matches!(
1658 exec.run_until_stalled(&mut sme_stream.next()),
1659 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1660 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1661 let vmo = write_vmo(results).expect("failed to write VMO");
1662 responder.send(Ok(vmo)).expect("failed to send scan error");
1663 }
1664 );
1665 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1666
1667 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1669 assert_matches!(
1670 &*exec.run_singlethreaded(location_sensor_results.lock()),
1671 Some(results) => {
1672 assert_eq!(results.len(), 2);
1673 }
1674 );
1675 }
1676
1677 #[fuchsia::test]
1678 fn scanning_loops_sends_inspect_data_to_telemetry() {
1679 let mut exec = fasync::TestExecutor::new();
1680 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1681 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1682 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
1683 let (location_sensor, _, _) = MockScanResultConsumer::new();
1684 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1685 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1686 let scanning_loop = serve_scanning_loop(
1687 iface_mgr.clone(),
1688 saved_networks_manager.clone(),
1689 telemetry_sender,
1690 location_sensor,
1691 scan_request_receiver,
1692 );
1693 let mut scanning_loop = pin!(scanning_loop);
1694
1695 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1697 let mut scan_req_fut = pin!(scan_req_fut);
1698 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1699 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1700
1701 let bss_description = fake_bss_description!(Wpa2, ies_overrides: IesOverrides::new().set(IeType::RSNE, fake_unknown_rsne()[2..].to_vec()));
1703 let scan_result = fidl_sme::ScanResult {
1704 bss_description: bss_description.into(),
1705 ..generate_random_sme_scan_result()
1706 };
1707
1708 assert_matches!(
1710 exec.run_until_stalled(&mut sme_stream.next()),
1711 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1712 req, responder,
1713 }))) => {
1714 assert_eq!(req, passive_sme_req());
1715 let vmo = write_vmo(vec![scan_result.clone()]).expect("failed to write VMO");
1716 responder.send(Ok(vmo)).expect("failed to send scan data");
1717 }
1718 );
1719
1720 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1722
1723 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1725 assert_eq!(results.len(), 1);
1726 });
1727
1728 let readable_ie: String =
1730 scan_result.bss_description.ies.iter().map(|n| n.to_string()).join(",");
1731 assert_matches!(telemetry_receiver.try_recv(), Ok(TelemetryEvent::SmeScanStart));
1732 assert_matches!(
1733 telemetry_receiver.try_recv(),
1734 Ok(TelemetryEvent::SmeScanResult {
1735 result: wlan_telemetry::ScanResult::Complete { num_results: 1 }
1736 })
1737 );
1738 assert_matches!(
1739 telemetry_receiver.try_recv(),
1740 Ok(TelemetryEvent::ScanEvent {inspect_data, scan_defects}) => {
1741 assert_eq!(scan_defects, vec![]);
1742 assert_eq!(inspect_data.unknown_protection_ies, vec![readable_ie]);
1743 });
1744 }
1745
1746 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, false; "Scan error ShouldWait with failed retry")]
1747 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, true; "Scan error ShouldWait with successful retry")]
1748 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, true; "Scan error CanceledByDriverOrFirmware with successful retry")]
1749 #[fuchsia::test]
1750 fn scanning_loop_retries_cancelled_request_once(
1751 error_code: fidl_sme::ScanErrorCode,
1752 retry_succeeds: bool,
1753 ) {
1754 let mut exec = fasync::TestExecutor::new_with_fake_time();
1755 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1756 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1757 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1758 let (location_sensor, _, _) = MockScanResultConsumer::new();
1759 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1760 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1761 let scanning_loop = serve_scanning_loop(
1762 iface_mgr.clone(),
1763 saved_networks_manager.clone(),
1764 telemetry_sender,
1765 location_sensor,
1766 scan_request_receiver,
1767 );
1768 let mut scanning_loop = pin!(scanning_loop);
1769
1770 let req_channels = vec![13];
1772 let scan_req_fut = scan_requester.perform_scan(
1773 ScanReason::BssSelection,
1774 vec!["foo".try_into().unwrap()],
1775 vec![generate_channel(13, fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz)],
1776 );
1777 let mut scan_req_fut = pin!(scan_req_fut);
1778 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1779 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1780
1781 let responder = assert_matches!(
1783 exec.run_until_stalled(&mut sme_stream.next()),
1784 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1785 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1787 assert_eq!(req.channels, req_channels)
1788 });
1789 responder
1790 }
1791 );
1792 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1793
1794 responder.send(Err(error_code)).expect("failed to send scan error");
1796 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1797
1798 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1800
1801 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1803
1804 assert!(exec.wake_next_timer().is_some());
1806 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1807
1808 let responder = assert_matches!(
1810 exec.run_until_stalled(&mut sme_stream.next()),
1811 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1812 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1813 assert_eq!(req.channels, req_channels)
1814 });
1815 responder
1816 }
1817 );
1818
1819 if retry_succeeds {
1820 let MockScanData { sme_results: input_aps, internal_results: _internal_aps } =
1823 create_scan_ap_data(types::ScanObservation::Passive);
1824 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1825 responder.send(Ok(vmo)).expect("failed to send scan data");
1826 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1827
1828 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1830 let expected_defects = vec![Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })];
1831 assert_eq!(logged_defects, expected_defects);
1832 } else {
1833 responder.send(Err(error_code)).expect("failed to send scan error");
1835 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1836
1837 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1839 let expected_defects = vec![
1840 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1841 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1842 ];
1843 assert_eq!(logged_defects, expected_defects);
1844 }
1845 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(_));
1847
1848 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1850 }
1851
1852 #[fuchsia::test]
1853 fn scanning_loop_backs_off_after_cancelled_request() {
1854 let mut exec = fasync::TestExecutor::new_with_fake_time();
1855 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1856 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1857 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1858 let (location_sensor, _, _) = MockScanResultConsumer::new();
1859 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1860 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1861 let scanning_loop = serve_scanning_loop(
1862 iface_mgr.clone(),
1863 saved_networks_manager.clone(),
1864 telemetry_sender,
1865 location_sensor,
1866 scan_request_receiver,
1867 );
1868 let mut scanning_loop = pin!(scanning_loop);
1869
1870 let first_req_channels = vec![13];
1872 let scan_req_fut1 = scan_requester.perform_scan(
1873 ScanReason::BssSelection,
1874 vec!["foo".try_into().unwrap()],
1875 vec![generate_channel(13, fidl_fuchsia_wlan_ieee80211::WlanBand::TwoGhz)],
1876 );
1877 let mut scan_req_fut1 = pin!(scan_req_fut1);
1878 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1879 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1880
1881 let responder = assert_matches!(
1883 exec.run_until_stalled(&mut sme_stream.next()),
1884 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1885 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1887 assert_eq!(req.channels, first_req_channels)
1888 });
1889 responder
1890 }
1891 );
1892
1893 let second_req_channels = vec![55];
1895 let scan_req_fut2 = scan_requester.perform_scan(
1896 ScanReason::BssSelection,
1897 vec!["foo".try_into().unwrap()],
1898 vec![generate_channel(55, fidl_fuchsia_wlan_ieee80211::WlanBand::FiveGhz)],
1899 );
1900 let mut scan_req_fut2 = pin!(scan_req_fut2);
1901 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1902 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1903
1904 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1906
1907 responder
1909 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1910 .expect("failed to send scan error");
1911 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1912
1913 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1915
1916 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1919
1920 assert!(exec.wake_next_timer().is_some());
1922 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1923
1924 let responder = assert_matches!(
1926 exec.run_until_stalled(&mut sme_stream.next()),
1927 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1928 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1930 assert_eq!(req.channels, first_req_channels)
1931 });
1932 responder
1933 }
1934 );
1935
1936 responder
1938 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1939 .expect("failed to send scan error");
1940 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1941
1942 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1944 assert_eq!(results, Err(types::ScanError::Cancelled));
1945 });
1946
1947 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1950
1951 assert!(exec.wake_next_timer().is_some());
1953 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1954
1955 assert_matches!(
1957 exec.run_until_stalled(&mut sme_stream.next()),
1958 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, .. }))) => {
1959 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1961 assert_eq!(req.channels, second_req_channels)
1962 });
1963 }
1964 );
1965 }
1966}