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 fuchsia_async::{self as fasync, DurationExt, TimeoutExt};
13use fuchsia_component::client::connect_to_protocol;
14use futures::channel::{mpsc, oneshot};
15use futures::future::{Fuse, FusedFuture, FutureExt};
16use futures::lock::Mutex;
17use futures::select;
18use futures::stream::{FuturesUnordered, StreamExt};
19use itertools::Itertools;
20use log::{debug, error, info, trace, warn};
21use std::collections::HashMap;
22use std::pin::pin;
23use std::sync::Arc;
24use {
25 fidl_fuchsia_location_sensor as fidl_location_sensor, fidl_fuchsia_wlan_common as fidl_common,
26 fidl_fuchsia_wlan_policy as fidl_policy, fidl_fuchsia_wlan_sme as fidl_sme,
27};
28
29mod fidl_conversion;
30mod queue;
31
32pub use fidl_conversion::{
33 scan_result_to_policy_scan_result, send_scan_error_over_fidl, send_scan_results_over_fidl,
34};
35
36const SCAN_RETRY_DELAY_MS: i64 = 100;
38const SCAN_CONSUMER_MAX_SECONDS_ALLOWED: i64 = 5;
40pub const SCAN_REQUEST_BUFFER_SIZE: usize = 100;
42
43#[derive(Debug, PartialEq)]
45pub enum ScanReason {
46 ClientRequest,
47 NetworkSelection,
48 BssSelection,
49 BssSelectionAugmentation,
50 RoamSearch,
51}
52
53#[async_trait(?Send)]
54pub trait ScanRequestApi {
55 async fn perform_scan(
56 &self,
57 scan_reason: ScanReason,
58 ssids: Vec<types::Ssid>,
59 channels: Vec<types::WlanChan>,
60 ) -> Result<Vec<types::ScanResult>, types::ScanError>;
61}
62
63pub struct ScanRequester {
64 pub sender: mpsc::Sender<ApiScanRequest>,
65}
66
67pub enum ApiScanRequest {
68 Scan(
69 ScanReason,
70 Vec<types::Ssid>,
71 Vec<types::WlanChan>,
72 oneshot::Sender<Result<Vec<types::ScanResult>, types::ScanError>>,
73 ),
74}
75
76#[async_trait(?Send)]
77impl ScanRequestApi for ScanRequester {
78 async fn perform_scan(
79 &self,
80 scan_reason: ScanReason,
81 ssids: Vec<types::Ssid>,
82 channels: Vec<types::WlanChan>,
83 ) -> Result<Vec<types::ScanResult>, types::ScanError> {
84 let (responder, receiver) = oneshot::channel();
85 self.sender
86 .clone()
87 .try_send(ApiScanRequest::Scan(scan_reason, ssids, channels, responder))
88 .map_err(|e| {
89 error!("Failed to send ScanRequest: {:?}", e);
90 types::ScanError::GeneralError
91 })?;
92 receiver.await.map_err(|e| {
93 error!("Failed to receive ScanRequest response: {:?}", e);
94 types::ScanError::GeneralError
95 })?
96 }
97}
98
99#[derive(Debug, Clone)]
101struct ScanRequest {
102 pub sme_req: fidl_sme::ScanRequest,
103 pub is_retry: bool,
104}
105impl From<fidl_sme::ScanRequest> for ScanRequest {
106 fn from(sme_req: fidl_sme::ScanRequest) -> Self {
107 Self { sme_req, is_retry: false }
108 }
109}
110
111pub async fn serve_scanning_loop(
113 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
114 saved_networks_manager: Arc<dyn SavedNetworksManagerApi>,
115 telemetry_sender: TelemetrySender,
116 location_sensor_updater: impl ScanResultUpdate,
117 mut scan_request_channel: mpsc::Receiver<ApiScanRequest>,
118) -> Result<(), Error> {
119 let mut queue = queue::RequestQueue::new(telemetry_sender.clone());
120 let mut location_sensor_updates = FuturesUnordered::new();
121 let ongoing_scan = Fuse::terminated();
124 let mut ongoing_scan = pin!(ongoing_scan);
125
126 let transform_next_sme_req = |next_sme_req: Option<ScanRequest>| match next_sme_req {
127 None => Fuse::terminated(),
128 Some(next_sme_req) => perform_scan(
129 next_sme_req,
130 iface_manager.clone(),
131 saved_networks_manager.clone(),
132 telemetry_sender.clone(),
133 )
134 .fuse(),
135 };
136
137 loop {
138 select! {
139 request = scan_request_channel.next() => {
140 match request {
141 Some(ApiScanRequest::Scan(reason, ssids, channels, responder)) => {
142 queue.add_request(reason, ssids, channels, responder, zx::MonotonicInstant::get());
143 if ongoing_scan.is_terminated() {
145 ongoing_scan.set(transform_next_sme_req(queue.get_next_sme_request().map(|req| req.into())));
146 }
147 },
148 None => {
149 error!("Unexpected 'None' on scan_request_channel");
150 }
151 }
152 },
153 (completed_sme_request, scan_results) = ongoing_scan => {
154 if scan_results == Err(types::ScanError::Cancelled) && !completed_sme_request.is_retry {
155 info!("Driver requested a delay before retrying the cancelled scan request.");
157 fasync::Timer::new(zx::MonotonicDuration::from_millis(SCAN_RETRY_DELAY_MS).after_now()).await;
158 ongoing_scan.set(transform_next_sme_req(Some(ScanRequest {is_retry: true, ..completed_sme_request})));
159 continue;
160 }
161 match scan_results {
162 Ok(ref results) => {
163 queue.handle_completed_sme_scan(
165 completed_sme_request.sme_req.clone(),
166 scan_results.clone(),
167 zx::MonotonicInstant::get()
168 );
169 if !results.is_empty() {
171 location_sensor_updates.push(location_sensor_updater
172 .update_scan_results(results.clone())
173 .on_timeout(zx::MonotonicDuration::from_seconds(SCAN_CONSUMER_MAX_SECONDS_ALLOWED), || {
174 error!("Timed out waiting for location sensor to get results");
175 })
176 );
177 }
178 },
179 Err(error) => {
180 queue.handle_completed_sme_scan(
183 completed_sme_request.sme_req.clone(),
184 scan_results.clone(),
185 zx::MonotonicInstant::get()
186 );
187 if error == types::ScanError::Cancelled {
189 info!("After multiple cancelled attempts, driver requested a delay before serving new scan requests.");
190 fasync::Timer::new(zx::MonotonicDuration::from_millis(SCAN_RETRY_DELAY_MS).after_now()).await;
191 }
192 }
193 }
194 ongoing_scan.set(transform_next_sme_req(
196 queue.get_next_sme_request().map(|req| req.into())
197 ));
198 },
199 () = location_sensor_updates.select_next_some() => {},
200 complete => {
201 warn!("Unexpectedly reached end of scanning loop");
203 break
204 },
205 }
206 }
207
208 Err(format_err!("Unexpectedly reached end of scanning loop"))
209}
210
211#[async_trait(?Send)]
213pub trait ScanResultUpdate {
214 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>);
215}
216
217async fn sme_scan(
219 sme_proxy: &SmeForScan,
220 scan_request: &fidl_sme::ScanRequest,
221 scan_defects: &mut Vec<ScanIssue>,
222) -> Result<Vec<wlan_common::scan::ScanResult>, types::ScanError> {
223 debug!("Sending scan request to SME");
224 let scan_result = sme_proxy.scan(scan_request).await.map_err(|error| {
225 error!("Failed to send scan to SME: {:?}", error);
226 types::ScanError::GeneralError
227 })?;
228 debug!("Finished getting scan results from SME");
229 match scan_result {
230 Ok(vmo) => {
231 let scan_result_list = wlan_common::scan::read_vmo(vmo).map_err(|error| {
232 error!("Failed to read scan results from VMO: {:?}", error);
233 types::ScanError::GeneralError
234 })?;
235 Ok(scan_result_list
236 .into_iter()
237 .filter_map(|scan_result| {
238 wlan_common::scan::ScanResult::try_from(scan_result).map(Some).unwrap_or_else(
239 |e| {
240 error!("ScanResult conversion failed: {:?}", e);
243 None
244 },
245 )
246 })
247 .inspect(|scan_result| {
248 trace!(
251 "Scan result SSID: {}, BSSID: {}, channel: {}",
252 scan_result.bss_description.ssid,
253 scan_result.bss_description.bssid,
254 scan_result.bss_description.channel
255 )
256 })
257 .collect::<Vec<_>>())
258 }
259 Err(scan_error_code) => {
260 log_metric_for_scan_error(&scan_error_code, scan_defects);
261 match scan_error_code {
262 fidl_sme::ScanErrorCode::ShouldWait
263 | fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware => {
264 info!("Scan cancelled by SME, retry indicated: {:?}", scan_error_code);
265 Err(types::ScanError::Cancelled)
266 }
267 _ => {
268 error!("Scan error from SME: {:?}", scan_error_code);
269 Err(types::ScanError::GeneralError)
270 }
271 }
272 }
273 }
274}
275
276async fn perform_scan(
278 scan_request: ScanRequest,
279 iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
280 saved_networks_manager: Arc<dyn SavedNetworksManagerApi>,
281 telemetry_sender: TelemetrySender,
282) -> (ScanRequest, Result<Vec<types::ScanResult>, types::ScanError>) {
283 let bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>>;
284 let mut scan_event_inspect_data = ScanEventInspectData::new();
285 let mut scan_defects: Vec<ScanIssue> = vec![];
286
287 let sme_proxy = match iface_manager.lock().await.get_sme_proxy_for_scan().await {
288 Ok(proxy) => proxy,
289 Err(_) => {
290 warn!("Failed to get sme proxy for passive scan");
291 return (scan_request, Err(types::ScanError::GeneralError));
292 }
293 };
294 let scan_results = sme_scan(&sme_proxy, &scan_request.sme_req, &mut scan_defects).await;
295 report_scan_defects_to_sme(&sme_proxy, &scan_results, &scan_request.sme_req).await;
296
297 match scan_results {
298 Ok(results) => {
299 let target_ssids = match scan_request.sme_req {
301 fidl_sme::ScanRequest::Passive(_) => vec![],
302 fidl_sme::ScanRequest::Active(ref req) => req
303 .ssids
304 .iter()
305 .map(|s| types::Ssid::from_bytes_unchecked(s.to_vec()))
306 .collect(),
307 };
308 bss_by_network =
309 bss_to_network_map(results, &target_ssids, &mut scan_event_inspect_data);
310 saved_networks_manager.record_scan_result(target_ssids, &bss_by_network).await;
311 }
312 Err(scan_err) => {
313 return (scan_request, Err(scan_err));
314 }
315 }
316
317 if let fidl_sme::ScanRequest::Passive(_) = scan_request.sme_req
319 && bss_by_network.is_empty()
320 {
321 scan_defects.push(ScanIssue::EmptyScanResults);
322 }
323
324 telemetry_sender
325 .send(TelemetryEvent::ScanEvent { inspect_data: scan_event_inspect_data, scan_defects });
326
327 let scan_results = network_map_to_scan_result(bss_by_network);
328 (scan_request, Ok(scan_results))
329}
330
331pub struct LocationSensorUpdater {}
334#[async_trait(?Send)]
335impl ScanResultUpdate for LocationSensorUpdater {
336 async fn update_scan_results(&self, scan_results: Vec<types::ScanResult>) {
337 async fn send_results(scan_results: Vec<fidl_policy::ScanResult>) -> Result<(), Error> {
338 let (iter, server) =
340 fidl::endpoints::create_endpoints::<fidl_policy::ScanResultIteratorMarker>();
341 let location_watcher_proxy =
342 connect_to_protocol::<fidl_location_sensor::WlanBaseStationWatcherMarker>()
343 .map_err(|err| {
344 format_err!("failed to connect to location sensor service: {:?}", err)
345 })?;
346 location_watcher_proxy
347 .report_current_stations(iter)
348 .map_err(|err| format_err!("failed to call location sensor service: {:?}", err))?;
349
350 fidl_conversion::send_scan_results_over_fidl(server, &scan_results).await
352 }
353
354 let scan_results = fidl_conversion::scan_result_to_policy_scan_result(&scan_results, true);
357 if let Err(e) = send_results(scan_results).await {
360 info!("Failed to send scan results to location sensor: {:?}", e)
361 } else {
362 debug!("Updated location sensor")
363 };
364 }
365}
366
367fn bss_to_network_map(
370 scan_result_list: Vec<wlan_common::scan::ScanResult>,
371 target_ssids: &[types::Ssid],
372 scan_event_inspect_data: &mut ScanEventInspectData,
373) -> HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> {
374 let mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>> =
375 HashMap::new();
376 for scan_result in scan_result_list.into_iter() {
377 let security_type: types::SecurityTypeDetailed =
378 scan_result.bss_description.protection().into();
379 if security_type == types::SecurityTypeDetailed::Unknown {
380 let readable_ie =
382 scan_result.bss_description.ies().iter().map(|n| n.to_string()).join(",");
383 debug!("Encountered unknown protection, ies: [{:?}]", readable_ie.clone());
384 scan_event_inspect_data.unknown_protection_ies.push(readable_ie);
385 };
386 let entry = bss_by_network
387 .entry(types::NetworkIdentifierDetailed {
388 ssid: scan_result.bss_description.ssid.clone(),
389 security_type,
390 })
391 .or_default();
392
393 if !entry.iter().any(|existing_bss| existing_bss.bssid == scan_result.bss_description.bssid)
395 {
396 entry.push(types::Bss {
397 bssid: scan_result.bss_description.bssid,
398 signal: types::Signal {
399 rssi_dbm: scan_result.bss_description.rssi_dbm,
400 snr_db: scan_result.bss_description.snr_db,
401 },
402 channel: scan_result.bss_description.channel,
403 timestamp: scan_result.timestamp,
404 observation: if target_ssids.contains(&scan_result.bss_description.ssid) {
406 types::ScanObservation::Active
407 } else {
408 types::ScanObservation::Passive
409 },
410 compatibility: scan_result.compatibility,
411 bss_description: wlan_common::sequestered::Sequestered::from(
412 fidl_common::BssDescription::from(scan_result.bss_description),
413 ),
414 });
415 };
416 }
417 bss_by_network
418}
419
420fn network_map_to_scan_result(
421 mut bss_by_network: HashMap<types::NetworkIdentifierDetailed, Vec<types::Bss>>,
422) -> Vec<types::ScanResult> {
423 let mut scan_results: Vec<types::ScanResult> = bss_by_network
424 .drain()
425 .map(|(types::NetworkIdentifierDetailed { ssid, security_type }, bss_entries)| {
426 let compatibility = if bss_entries.iter().any(|bss| bss.is_compatible()) {
427 fidl_policy::Compatibility::Supported
428 } else {
429 fidl_policy::Compatibility::DisallowedNotSupported
430 };
431 types::ScanResult {
432 ssid,
433 security_type_detailed: security_type,
434 entries: bss_entries,
435 compatibility,
436 }
437 })
438 .collect();
439
440 scan_results.sort_by(|a, b| a.ssid.cmp(&b.ssid));
441 scan_results
442}
443
444fn log_metric_for_scan_error(reason: &fidl_sme::ScanErrorCode, scan_defects: &mut Vec<ScanIssue>) {
445 let metric_type = match *reason {
446 fidl_sme::ScanErrorCode::NotSupported
447 | fidl_sme::ScanErrorCode::InternalError
448 | fidl_sme::ScanErrorCode::InternalMlmeError => ScanIssue::ScanFailure,
449 fidl_sme::ScanErrorCode::ShouldWait
450 | fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware => ScanIssue::AbortedScan,
451 };
452
453 scan_defects.push(metric_type);
454}
455
456async fn report_scan_defects_to_sme(
457 sme_proxy: &SmeForScan,
458 scan_result: &Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
459 scan_request: &fidl_sme::ScanRequest,
460) {
461 match scan_result {
462 Ok(results) => {
463 if results.is_empty()
465 && let fidl_sme::ScanRequest::Passive(_) = scan_request
466 {
467 sme_proxy.log_empty_scan_defect();
468 }
469 }
470 Err(types::ScanError::GeneralError) => sme_proxy.log_failed_scan_defect(),
471 Err(types::ScanError::Cancelled) => sme_proxy.log_aborted_scan_defect(),
472 }
473}
474
475#[cfg(test)]
476mod tests {
477 use super::*;
478 use crate::access_point::state_machine as ap_fsm;
479 use crate::mode_management::iface_manager_api::ConnectAttemptRequest;
480 use crate::mode_management::{Defect, IfaceFailure};
481 use crate::util::testing::fakes::FakeSavedNetworksManager;
482 use crate::util::testing::{
483 generate_channel, generate_random_sme_scan_result, run_until_completion,
484 };
485 use assert_matches::assert_matches;
486 use fidl::endpoints::{ControlHandle, Responder, create_proxy};
487 use futures::future;
488 use futures::task::Poll;
489 use std::pin::pin;
490 use test_case::test_case;
491 use wlan_common::ie::IeType;
492 use wlan_common::scan::{Compatible, Incompatible, write_vmo};
493 use wlan_common::security::SecurityDescriptor;
494 use wlan_common::test_utils::fake_frames::fake_unknown_rsne;
495 use wlan_common::test_utils::fake_stas::IesOverrides;
496 use wlan_common::{fake_bss_description, random_fidl_bss_description};
497 use {fidl_fuchsia_wlan_common_security as fidl_security, fuchsia_async as fasync};
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 {})
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_security::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_security::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 = fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest {});
764 let mut scan_defects = vec![];
765 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
766 let mut scan_fut = pin!(scan_fut);
767
768 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
770
771 let MockScanData { sme_results: input_aps, internal_results: _ } =
773 create_scan_ap_data(types::ScanObservation::Passive);
774 assert_matches!(
776 exec.run_until_stalled(&mut sme_stream.next()),
777 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
778 req, responder,
779 }))) => {
780 assert_eq!(req, scan_request);
781 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
782 responder.send(Ok(vmo)).expect("failed to send scan data");
783 }
784 );
785
786 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
788 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
789 .iter().map(|r| r.clone().into()).collect();
790 assert_eq!(scan_results, input_aps);
791 });
792
793 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
795 }
796
797 #[fuchsia::test]
798 fn sme_scan_with_active_request() {
799 let mut exec = fasync::TestExecutor::new();
800 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
801 let (defect_sender, _) = mpsc::channel(100);
802 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
803
804 let scan_request = fidl_sme::ScanRequest::Active(fidl_sme::ActiveScanRequest {
806 ssids: vec![
807 types::Ssid::try_from("foo_ssid").unwrap().into(),
808 types::Ssid::try_from("bar_ssid").unwrap().into(),
809 ],
810 channels: vec![1, 20],
811 });
812 let mut scan_defects = vec![];
813 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
814 let mut scan_fut = pin!(scan_fut);
815
816 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
818
819 let MockScanData { sme_results: input_aps, internal_results: _ } =
821 create_scan_ap_data(types::ScanObservation::Active);
822 assert_matches!(
824 exec.run_until_stalled(&mut sme_stream.next()),
825 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
826 req, responder,
827 }))) => {
828 assert_eq!(req, scan_request);
829 let vmo = write_vmo(input_aps.clone()).expect("failed to write VMO");
830 responder.send(Ok(vmo)).expect("failed to send scan data");
831 }
832 );
833
834 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
836 let scan_results: Vec<fidl_sme::ScanResult> = result.expect("failed to get scan results")
837 .iter().map(|r| r.clone().into()).collect();
838 assert_eq!(scan_results, input_aps);
839 });
840
841 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
843 }
844
845 #[fuchsia::test]
846 fn sme_channel_closed_while_awaiting_scan_results() {
847 let mut exec = fasync::TestExecutor::new();
848 let (sme_proxy, mut sme_stream) = exec.run_singlethreaded(create_sme_proxy());
849 let (defect_sender, _) = mpsc::channel(100);
850 let sme_proxy = SmeForScan::new(sme_proxy, 0, defect_sender);
851
852 let scan_request = fidl_sme::ScanRequest::Passive(fidl_sme::PassiveScanRequest {});
854 let mut scan_defects = vec![];
855 let scan_fut = sme_scan(&sme_proxy, &scan_request, &mut scan_defects);
856 let mut scan_fut = pin!(scan_fut);
857
858 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
860
861 assert_matches!(
863 exec.run_until_stalled(&mut sme_stream.next()),
864 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
865 req: _, responder,
866 }))) => {
867 responder.control_handle().shutdown();
869 drop(sme_stream);
871 }
872 );
873
874 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(result) => {
876 let error = result.expect_err("did not expect scan results");
877 assert_eq!(error, types::ScanError::GeneralError);
878 });
879 }
880
881 #[fuchsia::test]
882 fn basic_scan() {
883 let mut exec = fasync::TestExecutor::new();
884 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
885 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
886 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
887 let sme_scan = passive_sme_req();
889 let scan_fut =
890 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
891 let mut scan_fut = pin!(scan_fut);
892
893 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
895
896 let MockScanData { sme_results: input_aps, internal_results: internal_aps } =
898 create_scan_ap_data(types::ScanObservation::Passive);
899 assert_matches!(
900 exec.run_until_stalled(&mut sme_stream.next()),
901 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
902 req, responder,
903 }))) => {
904 assert_eq!(req, sme_scan.clone());
905 let vmo = write_vmo(input_aps).expect("failed to write VMO");
906 responder.send(Ok(vmo)).expect("failed to send scan data");
907 }
908 );
909
910 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
912 assert_eq!(request.sme_req, sme_scan);
913 assert_eq!(results.unwrap(), internal_aps);
914 });
915
916 assert_matches!(
919 telemetry_receiver.try_next(),
920 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
921 assert_eq!(inspect_data, ScanEventInspectData::new());
922 assert_eq!(scan_defects, vec![]);
923 });
924 }
925
926 #[fuchsia::test]
927 fn empty_passive_scan_results() {
928 let mut exec = fasync::TestExecutor::new();
929 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
930 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
931 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
932
933 let sme_scan = passive_sme_req();
935 let scan_fut = perform_scan(
936 sme_scan.clone().into(),
937 client.clone(),
938 saved_networks_manager,
939 telemetry_sender,
940 );
941 let mut scan_fut = pin!(scan_fut);
942
943 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
945
946 assert_matches!(
948 exec.run_until_stalled(&mut sme_stream.next()),
949 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
950 req, responder,
951 }))) => {
952 assert_eq!(req, sme_scan.clone());
953 let vmo = write_vmo(vec![]).expect("failed to write VMO");
954 responder.send(Ok(vmo)).expect("failed to send scan data");
955 }
956 );
957
958 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
960 assert_eq!(request.sme_req, sme_scan);
961 assert!(results.unwrap().is_empty());
962 });
963
964 assert_matches!(
966 telemetry_receiver.try_next(),
967 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
968 assert_eq!(inspect_data, ScanEventInspectData::new());
969 assert_eq!(scan_defects, vec![ScanIssue::EmptyScanResults]);
970 });
971
972 let logged_defects = get_fake_defects(&mut exec, client);
974 let expected_defects = vec![Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })];
975 assert_eq!(logged_defects, expected_defects);
976 }
977
978 #[fuchsia::test]
979 fn empty_active_scan_results() {
980 let mut exec = fasync::TestExecutor::new();
981 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
982 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
983 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
984
985 let sme_scan = active_sme_req(vec!["foo"], vec![]);
987 let scan_fut = perform_scan(
988 sme_scan.clone().into(),
989 client.clone(),
990 saved_networks_manager,
991 telemetry_sender,
992 );
993 let mut scan_fut = pin!(scan_fut);
994
995 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
997
998 assert_matches!(
1000 exec.run_until_stalled(&mut sme_stream.next()),
1001 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1002 req, responder,
1003 }))) => {
1004 assert_eq!(req, sme_scan.clone());
1005 let vmo = write_vmo(vec![]).expect("failed to write VMO");
1006 responder.send(Ok(vmo)).expect("failed to send scan data");
1007 }
1008 );
1009
1010 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1012 assert_eq!(request.sme_req, sme_scan);
1013 assert!(results.unwrap().is_empty());
1014 });
1015
1016 assert_matches!(telemetry_receiver.try_next(), Ok(Some(TelemetryEvent::ScanEvent { scan_defects, .. })) => {
1019 assert!(scan_defects.is_empty());
1020 });
1021
1022 let logged_defects = get_fake_defects(&mut exec, client);
1024 let expected_defects = vec![];
1025 assert_eq!(logged_defects, expected_defects);
1026 }
1027
1028 #[test_case(active_sme_req(vec![], vec![]) ; "active_sme_req, no ssid")]
1030 #[test_case(active_sme_req(vec![""], vec![]) ; "active_sme_req, wildcard ssid")]
1031 #[test_case(active_sme_req(vec!["", "foo"], vec![]) ; "active_sme_req, wildcard and foo ssid")]
1032 #[test_case(active_sme_req(vec!["foo"], vec![]) ; "active_sme_req, foo ssid")]
1033 #[test_case(passive_sme_req())]
1034 #[fuchsia::test(add_test_attr = false)]
1035 fn scan_updates_hidden_network_probabilities(sme_scan_request: fidl_sme::ScanRequest) {
1036 let mut exec = fasync::TestExecutor::new();
1037 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1038 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1039 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1040
1041 let MockScanData { sme_results: input_aps, internal_results: scan_results } =
1043 create_scan_ap_data(types::ScanObservation::Unknown);
1044
1045 let scan_fut = perform_scan(
1047 sme_scan_request.clone().into(),
1048 client,
1049 saved_networks_manager.clone(),
1050 telemetry_sender,
1051 );
1052 let mut scan_fut = pin!(scan_fut);
1053
1054 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1056
1057 assert_matches!(
1059 exec.run_until_stalled(&mut sme_stream.next()),
1060 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1061 req, responder,
1062 }))) => {
1063 assert_eq!(req, sme_scan_request);
1064 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1065 responder.send(Ok(vmo)).expect("failed to send scan data");
1066 }
1067 );
1068
1069 let _ = exec.run_until_stalled(&mut scan_fut);
1072
1073 let target_ssids = match sme_scan_request {
1075 fidl_sme::ScanRequest::Passive(_) => vec![],
1076 fidl_sme::ScanRequest::Active(ref req) => {
1077 req.ssids.iter().map(|s| types::Ssid::from_bytes_unchecked(s.to_vec())).collect()
1078 }
1079 };
1080 let mut scan_results_ids: Vec<types::NetworkIdentifierDetailed> = scan_results
1081 .iter()
1082 .map(|scan_result| types::NetworkIdentifierDetailed {
1083 ssid: scan_result.ssid.clone(),
1084 security_type: scan_result.security_type_detailed,
1085 })
1086 .collect();
1087
1088 let scan_result_record_guard =
1089 exec.run_singlethreaded(saved_networks_manager.scan_result_records.lock());
1090 assert_eq!(scan_result_record_guard.len(), 1);
1091 assert_eq!(scan_result_record_guard[0].0, target_ssids);
1092
1093 let mut recorded_ids = scan_result_record_guard[0]
1095 .1
1096 .keys()
1097 .cloned()
1098 .collect::<Vec<types::NetworkIdentifierDetailed>>();
1099
1100 recorded_ids.sort();
1101 scan_results_ids.sort();
1102 assert_eq!(scan_results_ids, recorded_ids);
1103
1104 }
1107
1108 #[fuchsia::test]
1109 fn bss_to_network_map_duplicated_bss() {
1110 let first_result = fidl_sme::ScanResult {
1112 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1113 mutual_security_protocols: vec![fidl_security::Protocol::Wpa3Personal],
1114 }),
1115 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1116 bss_description: random_fidl_bss_description!(
1117 Wpa3,
1118 bssid: [0, 0, 0, 0, 0, 0],
1119 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1120 rssi_dbm: 0,
1121 snr_db: 1,
1122 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
1123 ),
1124 };
1125 let second_result = fidl_sme::ScanResult {
1126 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1127 mutual_security_protocols: vec![fidl_security::Protocol::Wpa3Personal],
1128 }),
1129 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1130 bss_description: random_fidl_bss_description!(
1131 Wpa3,
1132 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1133 bssid: [1, 2, 3, 4, 5, 6],
1134 rssi_dbm: 101,
1135 snr_db: 101,
1136 channel: types::WlanChan::new(101, types::Cbw::Cbw40),
1137 ),
1138 };
1139
1140 let sme_results = [
1141 first_result.clone(),
1142 second_result.clone(),
1143 fidl_sme::ScanResult {
1145 compatibility: fidl_sme::Compatibility::Compatible(fidl_sme::Compatible {
1146 mutual_security_protocols: vec![fidl_security::Protocol::Wpa3Personal],
1147 }),
1148 timestamp_nanos: zx::MonotonicInstant::get().into_nanos(),
1149 bss_description: random_fidl_bss_description!(
1150 Wpa3,
1151 bssid: [0, 0, 0, 0, 0, 0],
1152 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1153 rssi_dbm: 13,
1154 snr_db: 3,
1155 channel: types::WlanChan::new(14, types::Cbw::Cbw20),
1156 ),
1157 },
1158 ];
1159
1160 let expected_id = types::NetworkIdentifierDetailed {
1161 ssid: types::Ssid::try_from("duplicated ssid").unwrap(),
1162 security_type: types::SecurityTypeDetailed::Wpa3Personal,
1163 };
1164
1165 let expected_bss = vec![
1168 types::Bss {
1169 bssid: types::Bssid::from([0, 0, 0, 0, 0, 0]),
1170 signal: types::Signal { rssi_dbm: 0, snr_db: 1 },
1171 timestamp: zx::MonotonicInstant::from_nanos(first_result.timestamp_nanos),
1172 channel: types::WlanChan::new(1, types::Cbw::Cbw20),
1173 observation: types::ScanObservation::Passive,
1174 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1175 bss_description: first_result.bss_description.clone().into(),
1176 },
1177 types::Bss {
1178 bssid: types::Bssid::from([1, 2, 3, 4, 5, 6]),
1179 signal: types::Signal { rssi_dbm: 101, snr_db: 101 },
1180 timestamp: zx::MonotonicInstant::from_nanos(second_result.timestamp_nanos),
1181 channel: types::WlanChan::new(101, types::Cbw::Cbw40),
1182 observation: types::ScanObservation::Passive,
1183 compatibility: Compatible::expect_ok([SecurityDescriptor::WPA3_PERSONAL]),
1184 bss_description: second_result.bss_description.clone().into(),
1185 },
1186 ];
1187
1188 let bss_by_network = bss_to_network_map(
1189 sme_results
1190 .iter()
1191 .map(|scan_result| {
1192 scan_result.clone().try_into().expect("Failed to convert ScanResult")
1193 })
1194 .collect::<Vec<wlan_common::scan::ScanResult>>(),
1195 &[],
1196 &mut ScanEventInspectData::new(),
1197 );
1198 assert_eq!(bss_by_network.len(), 1);
1199 assert_eq!(bss_by_network[&expected_id], expected_bss);
1200 }
1201
1202 #[test_case(
1203 fidl_sme::ScanErrorCode::InternalError,
1204 types::ScanError::GeneralError,
1205 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1206 )]
1207 #[test_case(
1208 fidl_sme::ScanErrorCode::InternalMlmeError,
1209 types::ScanError::GeneralError,
1210 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1211 )]
1212 #[test_case(
1213 fidl_sme::ScanErrorCode::NotSupported,
1214 types::ScanError::GeneralError,
1215 Defect::Iface(IfaceFailure::FailedScan {iface_id: 0})
1216 )]
1217 #[fuchsia::test(add_test_attr = false)]
1218 fn scan_error_no_retries(
1219 sme_failure_mode: fidl_sme::ScanErrorCode,
1220 policy_failure_mode: types::ScanError,
1221 expected_defect: Defect,
1222 ) {
1223 let mut exec = fasync::TestExecutor::new();
1224 let (client, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1225 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1226 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1227
1228 let sme_scan = active_sme_req(vec![], vec![1]);
1230 let scan_fut = perform_scan(
1231 sme_scan.clone().into(),
1232 client.clone(),
1233 saved_networks_manager,
1234 telemetry_sender,
1235 );
1236 let mut scan_fut = pin!(scan_fut);
1237 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1238
1239 assert_matches!(
1241 exec.run_until_stalled(&mut sme_stream.next()),
1242 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1243 responder.send(Err(sme_failure_mode)).expect("failed to send scan error");
1245 }
1246 );
1247
1248 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1250 assert_eq!(request.sme_req, sme_scan);
1251 assert_eq!(results, Err(policy_failure_mode));
1252 });
1253
1254 let logged_defects = get_fake_defects(&mut exec, client);
1256 let expected_defects = vec![expected_defect];
1257 assert_eq!(logged_defects, expected_defects);
1258 }
1259
1260 #[fuchsia::test]
1261 fn scan_returns_error_on_timeout() {
1262 let mut exec = fasync::TestExecutor::new_with_fake_time();
1263 let (client, _sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1264 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1265 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1266
1267 let sme_scan = passive_sme_req();
1269 let scan_fut =
1270 perform_scan(sme_scan.clone().into(), client, saved_networks_manager, telemetry_sender);
1271 let mut scan_fut = pin!(scan_fut);
1272
1273 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Pending);
1275
1276 assert!(exec.wake_next_timer().is_some());
1278
1279 assert_matches!(exec.run_until_stalled(&mut scan_fut), Poll::Ready((request, results)) => {
1281 assert_eq!(request.sme_req, sme_scan);
1282 assert_eq!(results, Err(types::ScanError::GeneralError));
1283 });
1284 }
1285
1286 #[test_case(fidl_sme::ScanErrorCode::NotSupported, ScanIssue::ScanFailure)]
1287 #[test_case(fidl_sme::ScanErrorCode::InternalError, ScanIssue::ScanFailure)]
1288 #[test_case(fidl_sme::ScanErrorCode::InternalMlmeError, ScanIssue::ScanFailure)]
1289 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, ScanIssue::AbortedScan)]
1290 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, ScanIssue::AbortedScan)]
1291 #[fuchsia::test(add_test_attr = false)]
1292 fn test_scan_error_metric_conversion(
1293 scan_error: fidl_sme::ScanErrorCode,
1294 expected_issue: ScanIssue,
1295 ) {
1296 let mut scan_defects = vec![];
1297 log_metric_for_scan_error(&scan_error, &mut scan_defects);
1298 assert_eq!(scan_defects, vec![expected_issue]);
1299 }
1300
1301 #[test_case(Err(types::ScanError::GeneralError), Some(Defect::Iface(IfaceFailure::FailedScan { iface_id: 0 })))]
1302 #[test_case(Err(types::ScanError::Cancelled), Some(Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })))]
1303 #[test_case(Ok(vec![]), Some(Defect::Iface(IfaceFailure::EmptyScanResults { iface_id: 0 })))]
1304 #[test_case(Ok(vec![wlan_common::scan::ScanResult::try_from(
1305 fidl_sme::ScanResult {
1306 bss_description: random_fidl_bss_description!(Wpa2, ssid: types::Ssid::try_from("other ssid").unwrap()),
1307 ..generate_random_sme_scan_result()
1308 },
1309 ).expect("failed scan result conversion")]),
1310 None
1311 )]
1312 #[fuchsia::test(add_test_attr = false)]
1313 fn test_scan_defect_reporting(
1314 scan_result: Result<Vec<wlan_common::scan::ScanResult>, types::ScanError>,
1315 expected_defect: Option<Defect>,
1316 ) {
1317 let mut exec = fasync::TestExecutor::new();
1318 let (iface_manager, _) = exec.run_singlethreaded(create_iface_manager());
1319 let scan_request = passive_sme_req();
1320
1321 let sme = {
1323 let cloned_iface_manager = iface_manager.clone();
1324 let fut = async move {
1325 let mut iface_manager = cloned_iface_manager.lock().await;
1326 iface_manager.get_sme_proxy_for_scan().await
1327 };
1328 let mut fut = pin!(fut);
1329 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(sme)) => sme)
1330 };
1331
1332 let fut = report_scan_defects_to_sme(&sme, &scan_result, &scan_request);
1334 let mut fut = pin!(fut);
1335 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
1336
1337 let logged_defects = get_fake_defects(&mut exec, iface_manager);
1341 match expected_defect {
1342 Some(defect) => {
1343 assert_eq!(logged_defects, vec![defect])
1344 }
1345 None => assert!(logged_defects.is_empty()),
1346 }
1347 }
1348
1349 #[fuchsia::test]
1350 fn scanning_loop_handles_sequential_requests() {
1351 let mut exec = fasync::TestExecutor::new();
1352 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1353 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1354 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1355 let (location_sensor, _, _) = MockScanResultConsumer::new();
1356 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1357 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1358 let scanning_loop = serve_scanning_loop(
1359 iface_mgr.clone(),
1360 saved_networks_manager.clone(),
1361 telemetry_sender,
1362 location_sensor,
1363 scan_request_receiver,
1364 );
1365 let mut scanning_loop = pin!(scanning_loop);
1366
1367 let first_req_channels = vec![13];
1369 let scan_req_fut1 = scan_requester.perform_scan(
1370 ScanReason::BssSelection,
1371 vec!["foo".try_into().unwrap()],
1372 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1373 );
1374 let mut scan_req_fut1 = pin!(scan_req_fut1);
1375 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1376 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1377
1378 assert_matches!(
1380 exec.run_until_stalled(&mut sme_stream.next()),
1381 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1382 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1384 assert_eq!(req.channels, first_req_channels)
1385 });
1386 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1388 }
1389 );
1390 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1391
1392 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1394 assert_eq!(results, Err(types::ScanError::GeneralError));
1395 });
1396
1397 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1399
1400 let second_req_channels = vec![55];
1402 let scan_req_fut2 = scan_requester.perform_scan(
1403 ScanReason::BssSelection,
1404 vec!["foo".try_into().unwrap()],
1405 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1406 );
1407 let mut scan_req_fut2 = pin!(scan_req_fut2);
1408 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1409 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1410
1411 assert_matches!(
1413 exec.run_until_stalled(&mut sme_stream.next()),
1414 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1415 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1417 assert_eq!(req.channels, second_req_channels)
1418 });
1419 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1421 }
1422 );
1423 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1424
1425 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1427 assert_eq!(results, Err(types::ScanError::GeneralError));
1428 });
1429
1430 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1432 }
1433
1434 #[fuchsia::test]
1435 fn scanning_loop_handles_overlapping_requests() {
1436 let mut exec = fasync::TestExecutor::new();
1437 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1438 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1439 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1440 let (location_sensor, _, _) = MockScanResultConsumer::new();
1441 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1442 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1443 let scanning_loop = serve_scanning_loop(
1444 iface_mgr.clone(),
1445 saved_networks_manager.clone(),
1446 telemetry_sender,
1447 location_sensor,
1448 scan_request_receiver,
1449 );
1450 let mut scanning_loop = pin!(scanning_loop);
1451
1452 let first_req_channels = vec![13];
1454 let scan_req_fut1 = scan_requester.perform_scan(
1455 ScanReason::BssSelection,
1456 vec!["foo".try_into().unwrap()],
1457 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1458 );
1459 let mut scan_req_fut1 = pin!(scan_req_fut1);
1460 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1461 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1462
1463 let responder1 = assert_matches!(
1465 exec.run_until_stalled(&mut sme_stream.next()),
1466 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1467 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1469 assert_eq!(req.channels, first_req_channels)
1470 });
1471 responder
1472 }
1473 );
1474 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1475
1476 let second_req_channels = vec![55];
1478 let scan_req_fut2 = scan_requester.perform_scan(
1479 ScanReason::BssSelection,
1480 vec!["foo".try_into().unwrap()],
1481 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1482 );
1483 let mut scan_req_fut2 = pin!(scan_req_fut2);
1484 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1485 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1486
1487 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1489 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1490 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1492
1493 responder1
1495 .send(Err(fidl_sme::ScanErrorCode::InternalError))
1496 .expect("failed to send scan error");
1497 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1498
1499 assert_matches!(
1501 exec.run_until_stalled(&mut sme_stream.next()),
1502 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1503 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1505 assert_eq!(req.channels, second_req_channels)
1506 });
1507 responder.send(Err(fidl_sme::ScanErrorCode::InternalError)).expect("failed to send scan error");
1509 }
1510 );
1511 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1512
1513 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1515 assert_eq!(results, Err(types::ScanError::GeneralError));
1516 });
1517 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Ready(results) => {
1518 assert_eq!(results, Err(types::ScanError::GeneralError));
1519 });
1520
1521 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1523 }
1524
1525 #[fuchsia::test]
1526 fn scanning_loop_sends_results_to_requester_and_location_sensor() {
1527 let mut exec = fasync::TestExecutor::new();
1528 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1529 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1530 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1531 let (location_sensor, location_sensor_results, _) = MockScanResultConsumer::new();
1532 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1533 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1534 let scanning_loop = serve_scanning_loop(
1535 iface_mgr.clone(),
1536 saved_networks_manager.clone(),
1537 telemetry_sender,
1538 location_sensor,
1539 scan_request_receiver,
1540 );
1541 let mut scanning_loop = pin!(scanning_loop);
1542
1543 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1545 let mut scan_req_fut = pin!(scan_req_fut);
1546 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1547 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1548
1549 assert_matches!(
1551 exec.run_until_stalled(&mut sme_stream.next()),
1552 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1553 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1554 let vmo = write_vmo(results).expect("failed to write VMO");
1555 responder.send(Ok(vmo)).expect("failed to send scan error");
1556 }
1557 );
1558 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1559
1560 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1562 assert_eq!(results.len(), 2);
1563 });
1564
1565 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1567 assert_matches!(
1568 &*exec.run_singlethreaded(location_sensor_results.lock()),
1569 Some(results) => {
1570 assert_eq!(results.len(), 2);
1571 }
1572 );
1573 }
1574
1575 #[fuchsia::test]
1576 fn scanning_loop_location_sensor_timeout_works() {
1577 let mut exec = fasync::TestExecutor::new();
1578 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1579 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1580 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1581 let (location_sensor, location_sensor_results, location_sensor_stalled) =
1582 MockScanResultConsumer::new();
1583 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1584 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1585 let scanning_loop = serve_scanning_loop(
1586 iface_mgr.clone(),
1587 saved_networks_manager.clone(),
1588 telemetry_sender,
1589 location_sensor,
1590 scan_request_receiver,
1591 );
1592 let mut scanning_loop = pin!(scanning_loop);
1593
1594 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = true;
1596
1597 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1599 let mut scan_req_fut = pin!(scan_req_fut);
1600 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1601 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1602
1603 assert_matches!(
1605 exec.run_until_stalled(&mut sme_stream.next()),
1606 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1607 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1608 let vmo = write_vmo(results).expect("failed to write VMO");
1609 responder.send(Ok(vmo)).expect("failed to send scan error");
1610 }
1611 );
1612 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1613
1614 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1616 assert_matches!(&*exec.run_singlethreaded(location_sensor_results.lock()), None);
1617
1618 *(exec.run_singlethreaded(location_sensor_stalled.lock())) = false;
1620
1621 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1623 let mut scan_req_fut = pin!(scan_req_fut);
1624 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1625 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1626
1627 assert_matches!(
1629 exec.run_until_stalled(&mut sme_stream.next()),
1630 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req: _, responder }))) => {
1631 let results = vec![generate_random_sme_scan_result(), generate_random_sme_scan_result()];
1632 let vmo = write_vmo(results).expect("failed to write VMO");
1633 responder.send(Ok(vmo)).expect("failed to send scan error");
1634 }
1635 );
1636 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1637
1638 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1640 assert_matches!(
1641 &*exec.run_singlethreaded(location_sensor_results.lock()),
1642 Some(results) => {
1643 assert_eq!(results.len(), 2);
1644 }
1645 );
1646 }
1647
1648 #[fuchsia::test]
1649 fn scanning_loops_sends_inspect_data_to_telemetry() {
1650 let mut exec = fasync::TestExecutor::new();
1651 let (iface_mgr, mut sme_stream) = exec.run_singlethreaded(create_iface_manager());
1652 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1653 let (telemetry_sender, mut telemetry_receiver) = create_telemetry_sender_and_receiver();
1654 let (location_sensor, _, _) = MockScanResultConsumer::new();
1655 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1656 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1657 let scanning_loop = serve_scanning_loop(
1658 iface_mgr.clone(),
1659 saved_networks_manager.clone(),
1660 telemetry_sender,
1661 location_sensor,
1662 scan_request_receiver,
1663 );
1664 let mut scanning_loop = pin!(scanning_loop);
1665
1666 let scan_req_fut = scan_requester.perform_scan(ScanReason::BssSelection, vec![], vec![]);
1668 let mut scan_req_fut = pin!(scan_req_fut);
1669 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1670 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1671
1672 let bss_description = fake_bss_description!(Wpa2, ies_overrides: IesOverrides::new().set(IeType::RSNE, fake_unknown_rsne()[2..].to_vec()));
1674 let scan_result = fidl_sme::ScanResult {
1675 bss_description: bss_description.into(),
1676 ..generate_random_sme_scan_result()
1677 };
1678
1679 assert_matches!(
1681 exec.run_until_stalled(&mut sme_stream.next()),
1682 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan {
1683 req, responder,
1684 }))) => {
1685 assert_eq!(req, passive_sme_req());
1686 let vmo = write_vmo(vec![scan_result.clone()]).expect("failed to write VMO");
1687 responder.send(Ok(vmo)).expect("failed to send scan data");
1688 }
1689 );
1690
1691 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1693
1694 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(Ok(results)) => {
1696 assert_eq!(results.len(), 1);
1697 });
1698
1699 let readable_ie: String =
1701 scan_result.bss_description.ies.iter().map(|n| n.to_string()).join(",");
1702 assert_matches!(
1703 telemetry_receiver.try_next(),
1704 Ok(Some(TelemetryEvent::ScanEvent {inspect_data, scan_defects})) => {
1705 assert_eq!(scan_defects, vec![]);
1706 assert_eq!(inspect_data.unknown_protection_ies, vec![readable_ie]);
1707 });
1708 }
1709
1710 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, false; "Scan error ShouldWait with failed retry")]
1711 #[test_case(fidl_sme::ScanErrorCode::ShouldWait, true; "Scan error ShouldWait with successful retry")]
1712 #[test_case(fidl_sme::ScanErrorCode::CanceledByDriverOrFirmware, true; "Scan error CanceledByDriverOrFirmware with successful retry")]
1713 #[fuchsia::test]
1714 fn scanning_loop_retries_cancelled_request_once(
1715 error_code: fidl_sme::ScanErrorCode,
1716 retry_succeeds: bool,
1717 ) {
1718 let mut exec = fasync::TestExecutor::new_with_fake_time();
1719 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1720 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1721 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1722 let (location_sensor, _, _) = MockScanResultConsumer::new();
1723 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1724 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1725 let scanning_loop = serve_scanning_loop(
1726 iface_mgr.clone(),
1727 saved_networks_manager.clone(),
1728 telemetry_sender,
1729 location_sensor,
1730 scan_request_receiver,
1731 );
1732 let mut scanning_loop = pin!(scanning_loop);
1733
1734 let req_channels = vec![13];
1736 let scan_req_fut = scan_requester.perform_scan(
1737 ScanReason::BssSelection,
1738 vec!["foo".try_into().unwrap()],
1739 req_channels.iter().map(|c| generate_channel(*c)).collect(),
1740 );
1741 let mut scan_req_fut = pin!(scan_req_fut);
1742 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1743 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1744
1745 let responder = assert_matches!(
1747 exec.run_until_stalled(&mut sme_stream.next()),
1748 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1749 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1751 assert_eq!(req.channels, req_channels)
1752 });
1753 responder
1754 }
1755 );
1756 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1757
1758 responder.send(Err(error_code)).expect("failed to send scan error");
1760 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1761
1762 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Pending);
1764
1765 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1767
1768 assert!(exec.wake_next_timer().is_some());
1770 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1771
1772 let responder = assert_matches!(
1774 exec.run_until_stalled(&mut sme_stream.next()),
1775 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1776 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1777 assert_eq!(req.channels, req_channels)
1778 });
1779 responder
1780 }
1781 );
1782
1783 if retry_succeeds {
1784 let MockScanData { sme_results: input_aps, internal_results: _internal_aps } =
1787 create_scan_ap_data(types::ScanObservation::Passive);
1788 let vmo = write_vmo(input_aps).expect("failed to write VMO");
1789 responder.send(Ok(vmo)).expect("failed to send scan data");
1790 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1791
1792 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1794 let expected_defects = vec![Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 })];
1795 assert_eq!(logged_defects, expected_defects);
1796 } else {
1797 responder.send(Err(error_code)).expect("failed to send scan error");
1799 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1800
1801 let logged_defects = get_fake_defects(&mut exec, iface_mgr);
1803 let expected_defects = vec![
1804 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1805 Defect::Iface(IfaceFailure::CanceledScan { iface_id: 0 }),
1806 ];
1807 assert_eq!(logged_defects, expected_defects);
1808 }
1809 assert_matches!(exec.run_until_stalled(&mut scan_req_fut), Poll::Ready(_));
1811
1812 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1814 }
1815
1816 #[fuchsia::test]
1817 fn scanning_loop_backs_off_after_cancelled_request() {
1818 let mut exec = fasync::TestExecutor::new_with_fake_time();
1819 let (iface_mgr, mut sme_stream) = run_until_completion(&mut exec, create_iface_manager());
1820 let saved_networks_manager = Arc::new(FakeSavedNetworksManager::new());
1821 let (telemetry_sender, _telemetry_receiver) = create_telemetry_sender_and_receiver();
1822 let (location_sensor, _, _) = MockScanResultConsumer::new();
1823 let (scan_request_sender, scan_request_receiver) = mpsc::channel(100);
1824 let scan_requester = Arc::new(ScanRequester { sender: scan_request_sender });
1825 let scanning_loop = serve_scanning_loop(
1826 iface_mgr.clone(),
1827 saved_networks_manager.clone(),
1828 telemetry_sender,
1829 location_sensor,
1830 scan_request_receiver,
1831 );
1832 let mut scanning_loop = pin!(scanning_loop);
1833
1834 let first_req_channels = vec![13];
1836 let scan_req_fut1 = scan_requester.perform_scan(
1837 ScanReason::BssSelection,
1838 vec!["foo".try_into().unwrap()],
1839 first_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1840 );
1841 let mut scan_req_fut1 = pin!(scan_req_fut1);
1842 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1843 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1844
1845 let responder = assert_matches!(
1847 exec.run_until_stalled(&mut sme_stream.next()),
1848 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1849 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1851 assert_eq!(req.channels, first_req_channels)
1852 });
1853 responder
1854 }
1855 );
1856
1857 let second_req_channels = vec![55];
1859 let scan_req_fut2 = scan_requester.perform_scan(
1860 ScanReason::BssSelection,
1861 vec!["foo".try_into().unwrap()],
1862 second_req_channels.iter().map(|c| generate_channel(*c)).collect(),
1863 );
1864 let mut scan_req_fut2 = pin!(scan_req_fut2);
1865 assert_matches!(exec.run_until_stalled(&mut scan_req_fut2), Poll::Pending);
1866 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1867
1868 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1870
1871 responder
1873 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1874 .expect("failed to send scan error");
1875 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1876
1877 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Pending);
1879
1880 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1883
1884 assert!(exec.wake_next_timer().is_some());
1886 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1887
1888 let responder = assert_matches!(
1890 exec.run_until_stalled(&mut sme_stream.next()),
1891 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, responder }))) => {
1892 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1894 assert_eq!(req.channels, first_req_channels)
1895 });
1896 responder
1897 }
1898 );
1899
1900 responder
1902 .send(Err(fidl_sme::ScanErrorCode::ShouldWait))
1903 .expect("failed to send scan error");
1904 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1905
1906 assert_matches!(exec.run_until_stalled(&mut scan_req_fut1), Poll::Ready(results) => {
1908 assert_eq!(results, Err(types::ScanError::Cancelled));
1909 });
1910
1911 assert_matches!(exec.run_until_stalled(&mut sme_stream.next()), Poll::Pending);
1914
1915 assert!(exec.wake_next_timer().is_some());
1917 assert_matches!(exec.run_until_stalled(&mut scanning_loop), Poll::Pending);
1918
1919 assert_matches!(
1921 exec.run_until_stalled(&mut sme_stream.next()),
1922 Poll::Ready(Some(Ok(fidl_sme::ClientSmeRequest::Scan { req, .. }))) => {
1923 assert_matches!(req, fidl_sme::ScanRequest::Active(req) => {
1925 assert_eq!(req.channels, second_req_channels)
1926 });
1927 }
1928 );
1929 }
1930}