1use ::fidl as _;
6use anyhow::{Error, format_err};
7use eui48::MacAddress;
8use flex_client::ProxyHasDomain;
9use flex_fuchsia_net as net;
10use flex_fuchsia_wlan_policy as wlan_policy;
11use flex_fuchsia_wlan_product_deprecatedconfiguration as wlan_deprecated;
12use futures::TryStreamExt;
13use futures::future::LocalBoxFuture;
14
15pub mod opts;
16pub mod serialize;
17
18fn extract_network_id(
22 network_id: Option<wlan_policy::NetworkIdentifier>,
23) -> Result<(String, String), Error> {
24 match network_id {
25 Some(id) => {
26 let ssid = std::string::String::from_utf8(id.ssid).unwrap();
27 let security_type = match id.type_ {
28 wlan_policy::SecurityType::None => "",
29 wlan_policy::SecurityType::Wep => "wep",
30 wlan_policy::SecurityType::Wpa => "wpa",
31 wlan_policy::SecurityType::Wpa2 => "wpa2",
32 wlan_policy::SecurityType::Wpa3 => "wpa3",
33 };
34 return Ok((ssid, security_type.to_string()));
35 }
36 None => return Ok(("".to_string(), "".to_string())),
37 };
38}
39
40fn extract_bss_details(bss: wlan_policy::Bss) -> (String, i8, u32) {
42 let bssid = match bss.bssid {
43 Some(bssid) => hex::encode(bssid),
44 None => "".to_string(),
45 };
46 let rssi = match bss.rssi {
47 Some(rssi) => rssi,
48 None => 0,
49 };
50 let frequency = match bss.frequency {
51 Some(frequency) => frequency,
52 None => 0,
53 };
54
55 (bssid, rssi, frequency)
56}
57
58fn extract_compatibility(compatibility: Option<wlan_policy::Compatibility>) -> String {
60 if compatibility.is_some() {
61 match compatibility.unwrap() {
62 wlan_policy::Compatibility::Supported => return "supported".to_string(),
63 wlan_policy::Compatibility::DisallowedInsecure => {
64 return "disallowed, insecure".to_string();
65 }
66 wlan_policy::Compatibility::DisallowedNotSupported => {
67 return "disallowed, not supported".to_string();
68 }
69 }
70 }
71
72 return "compatilibity unknown".to_string();
73}
74
75pub fn print_saved_networks(saved_networks: Vec<wlan_policy::NetworkConfig>) -> Result<(), Error> {
77 for config in saved_networks {
78 let (ssid, security_type) = extract_network_id(config.id)?;
79 let password = match config.credential {
80 Some(credential) => match credential {
81 wlan_policy::Credential::None(wlan_policy::Empty) => String::from(""),
82 wlan_policy::Credential::Password(bytes) => {
83 let password = std::string::String::from_utf8(bytes);
84 password.unwrap()
85 }
86 wlan_policy::Credential::Psk(bytes) => {
87 hex::encode(bytes)
89 }
90 _ => return Err(format_err!("unknown credential variant detected")),
91 },
92 None => String::from(""),
93 };
94 println!("{:32} | {:4} | {}", ssid, security_type, password);
95 }
96 Ok(())
97}
98
99pub fn print_serialized_saved_networks(
101 saved_networks: Vec<wlan_policy::NetworkConfig>,
102) -> Result<(), Error> {
103 let serialized = serialize::serialize_saved_networks(saved_networks)?;
104 println!("{}", serialized);
105 Ok(())
106}
107
108pub async fn restore_serialized_config(
110 client_controller: wlan_policy::ClientControllerProxy,
111 serialized_config: String,
112) -> Result<(), Error> {
113 let network_configs = serialize::deserialize_saved_networks(serialized_config)?;
114 for network in network_configs {
115 save_network(client_controller.clone(), network).await?;
116 }
117 Ok(())
118}
119
120pub fn print_scan_results(scan_results: Vec<wlan_policy::ScanResult>) -> Result<(), Error> {
122 for network in scan_results {
123 let (ssid, security_type) = extract_network_id(network.id)?;
124 let compatibility = extract_compatibility(network.compatibility);
125 println!("{:32} | {:3} ({})", ssid, security_type, compatibility);
126
127 if network.entries.is_some() {
128 for entry in network.entries.unwrap() {
129 let (bssid, rssi, frequency) = extract_bss_details(entry);
130 println!("\t0x{:12} | {:3} | {:5}", bssid, rssi, frequency);
131 }
132 }
133 }
134 Ok(())
135}
136
137fn handle_request_status(status: wlan_policy::RequestStatus) -> Result<(), Error> {
140 match status {
141 wlan_policy::RequestStatus::Acknowledged => Ok(()),
142 wlan_policy::RequestStatus::RejectedNotSupported => {
143 Err(format_err!("request failed: not supported"))
144 }
145 wlan_policy::RequestStatus::RejectedIncompatibleMode => {
146 Err(format_err!("request failed: incompatible mode"))
147 }
148 wlan_policy::RequestStatus::RejectedAlreadyInUse => {
149 Err(format_err!("request failed: already in use"))
150 }
151 wlan_policy::RequestStatus::RejectedDuplicateRequest => {
152 Err(format_err!("request failed: duplicate request."))
153 }
154 }
155}
156
157async fn run_proxy_command<'a, T>(
161 fut: LocalBoxFuture<'a, Result<T, ::fidl::Error>>,
162) -> Result<T, Error> {
163 fut.await.map_err(|e| {
164 match e {
165 ::fidl::Error::ClientChannelClosed { .. } => format_err!(
166 "Failed to obtain a WLAN policy controller. Your command was not executed.\n\n\
167 Help: Only one component may hold a policy controller at once. You can try killing\n\
168 other holders with:\n\
169 * ffx component destroy /core/session-manager/session:session\n"
170 ),
171 e => format_err!("{}", e),
172 }
173 })
174}
175
176pub async fn handle_connect(
181 client_controller: wlan_policy::ClientControllerProxy,
182 mut server_stream: wlan_policy::ClientStateUpdatesRequestStream,
183 ssid: String,
184 security_type: Option<wlan_policy::SecurityType>,
185) -> Result<(), Error> {
186 let network_id = if let Some(type_) = security_type {
188 wlan_policy::NetworkIdentifier { ssid: ssid.into_bytes(), type_ }
189 } else {
190 let mut saved_networks = handle_get_saved_networks(&client_controller)
191 .await
192 .map_err(|e| format_err!("failed to look up matching saved networks: {:?}", e))?;
193 saved_networks.retain(|config| config.id.as_ref().unwrap().ssid == ssid.as_bytes());
194 if saved_networks.len() == 1 {
196 saved_networks.pop().unwrap().id.unwrap()
197 } else if saved_networks.is_empty() {
198 return Err(format_err!(
199 "Failed to find a saved network with the provided name. Please check that the name is correct or make sure the network with the provided name is saved."
200 ));
201 } else {
204 return Err(format_err!(
205 "Multiple saved networks were found matching the provided name, please specify the security type of the network to connect to."
206 ));
207 }
208 };
209
210 let result = run_proxy_command(Box::pin(client_controller.connect(&network_id))).await?;
211 handle_request_status(result)?;
212
213 while let Some(update_request) = server_stream.try_next().await? {
214 let update = update_request.into_on_client_state_update();
215 let (update, responder) = match update {
216 Some((update, responder)) => (update, responder),
217 None => return Err(format_err!("Client provider produced invalid update.")),
218 };
219 let _ = responder.send();
220
221 match update.state {
222 Some(state) => {
223 if state == wlan_policy::WlanClientState::ConnectionsDisabled {
224 return Err(format_err!("Connections disabled while trying to conncet."));
225 }
226 }
227 None => continue,
228 }
229
230 let networks = match update.networks {
231 Some(networks) => networks,
232 None => continue,
233 };
234
235 for net_state in networks {
236 if net_state.id.is_none() || net_state.state.is_none() {
237 continue;
238 }
239 if net_state.id.unwrap().ssid == network_id.ssid {
240 match net_state.state.unwrap() {
241 wlan_policy::ConnectionState::Failed => {
242 return Err(format_err!(
243 "Failed to connect with reason {:?}",
244 net_state.status
245 ));
246 }
247 wlan_policy::ConnectionState::Disconnected => {
248 return Err(format_err!("Disconnect with reason {:?}", net_state.status));
249 }
250 wlan_policy::ConnectionState::Connecting => continue,
251 wlan_policy::ConnectionState::Connected => {
252 println!("Successfully connected");
253 return Ok(());
254 }
255 }
256 }
257 }
258 }
259 Err(format_err!("Status stream terminated before connection could be verified."))
260}
261
262pub async fn handle_get_saved_networks(
265 client_controller: &wlan_policy::ClientControllerProxy,
266) -> Result<Vec<wlan_policy::NetworkConfig>, Error> {
267 let (client_proxy, server_end) =
268 client_controller.domain().create_proxy::<wlan_policy::NetworkConfigIteratorMarker>();
269 let fut = async { client_controller.get_saved_networks(server_end) };
270 run_proxy_command(Box::pin(fut)).await?;
271
272 let mut saved_networks = Vec::new();
273 loop {
274 let mut new_configs = run_proxy_command(Box::pin(client_proxy.get_next())).await?;
275 if new_configs.is_empty() {
276 break;
277 }
278 saved_networks.append(&mut new_configs);
279 }
280 Ok(saved_networks)
281}
282
283pub async fn handle_listen(
290 mut server_stream: wlan_policy::ClientStateUpdatesRequestStream,
291 single_sample: bool,
292) -> Result<(), Error> {
293 let mut last_known_connection_state = None;
294 while let Some(update_request) = server_stream.try_next().await? {
295 let update = update_request.into_on_client_state_update();
296 let (update, responder) = match update {
297 Some((update, responder)) => (update, responder),
298 None => return Err(format_err!("Client provider produced invalid update.")),
299 };
300 let _ = responder.send();
301
302 match update.state {
303 Some(state) => {
304 if last_known_connection_state != Some(state) {
305 last_known_connection_state = Some(state);
306 match state {
307 wlan_policy::WlanClientState::ConnectionsEnabled => {
308 println!("Client connections are enabled");
309 }
310 wlan_policy::WlanClientState::ConnectionsDisabled => {
311 println!("Client connections are disabled");
312 }
313 }
314 };
315 }
316 None => {
317 println!("Unexpected client connection state 'None'");
318 }
319 }
320
321 let networks = match update.networks {
322 Some(networks) => networks,
323 None => continue,
324 };
325
326 let mut updates = vec![];
327 for net_state in networks {
329 if net_state.id.is_none() || net_state.state.is_none() {
330 continue;
331 }
332 let id = net_state.id.unwrap();
333 let ssid = std::str::from_utf8(&id.ssid).unwrap();
334 match net_state.state.unwrap() {
335 wlan_policy::ConnectionState::Failed => {
336 updates.push(format!(
337 "\t{:32} connection failed - {:?}",
338 format!("{}:", ssid),
339 net_state.status
340 ));
341 }
342 wlan_policy::ConnectionState::Disconnected => {
343 updates.push(format!(
344 "\t{:32} connection disconnected - {:?}",
345 format!("{}:", ssid),
346 net_state.status
347 ));
348 }
349 wlan_policy::ConnectionState::Connecting => {
350 updates.push(format!("\t{:32} connecting", format!("{}:", ssid)));
351 }
352 wlan_policy::ConnectionState::Connected => {
353 updates.push(format!("\t{:32} connected", format!("{}:", ssid)))
354 }
355 }
356 }
357
358 updates.sort_by_key(|s| s.to_lowercase());
360 println!("Update:");
361 for update in updates {
362 println!("{}", update);
363 }
364
365 if single_sample {
367 break;
368 }
369 }
370 Ok(())
371}
372
373pub async fn handle_remove_network(
377 client_controller: wlan_policy::ClientControllerProxy,
378 ssid: Vec<u8>,
379 security_type: Option<wlan_policy::SecurityType>,
380 credential: Option<wlan_policy::Credential>,
381) -> Result<(), Error> {
382 let networks_before = handle_get_saved_networks(&client_controller).await.map_err(|e| {
383 format_err!(
384 "The network was not removed because an error occurred getting the list of networks \
385 before removing the requested network: {}",
386 e,
387 )
388 })?;
389
390 let config = if security_type.is_some() && credential.is_some() {
393 wlan_policy::NetworkConfig {
394 id: Some(wlan_policy::NetworkIdentifier {
395 ssid: ssid.clone(),
396 type_: security_type.unwrap(),
397 }),
398 credential: credential.clone(),
399 ..Default::default()
400 }
401 } else {
402 let mut matching_networks = networks_before
406 .iter()
407 .filter(|c| config_matches(c, &ssid, &security_type, &credential))
408 .cloned()
409 .collect::<Vec<_>>();
410
411 if matching_networks.len() == 1 {
413 matching_networks.pop().unwrap()
414 } else if matching_networks.is_empty() {
415 return Err(format_err!(
416 "Failed to find a saved network with the provided arguments. Please check that the arguments are correct if there should be one saved."
417 ));
418 } else {
421 return Err(format_err!(
422 "Multiple saved networks were found matching the provided \
423 arguments, please specify SSID, security, and credential that matches only one \
424 saved network."
425 ));
426 }
427 };
428
429 run_proxy_command(Box::pin(client_controller.remove_network(&config)))
430 .await?
431 .map_err(|e| format_err!("failed to remove network with {:?}", e))?;
432
433 let networks_after = match handle_get_saved_networks(&client_controller).await {
434 Ok(networks) => networks,
435 Err(e) => {
436 println!(
437 "The network provided may or may not have been removed. An error occurred \
438 getting the list of networks after removing: {}",
439 e
440 );
441 return Ok(());
442 }
443 };
444
445 if networks_after.iter().any(|c| config_matches(c, &ssid, &security_type, &credential)) {
448 return Err(format_err!(
449 "The network may not have been removed. A network matching the \
450 provided arguments was found after attempting to remove the network."
451 ));
452 }
453
454 if networks_before.len() == networks_after.len() {
456 println!(
457 "The number of saved networks is the same after removing the specified network. \
458 Please check that the arguments provided are correct and whether the intended \
459 network is saved."
460 );
461 } else {
462 println!("Successfully removed network '{}'", std::str::from_utf8(&ssid).unwrap());
463 }
464 Ok(())
465}
466
467fn config_matches(
470 config: &wlan_policy::NetworkConfig,
471 ssid: &Vec<u8>,
472 security_type: &Option<wlan_policy::SecurityType>,
473 credential: &Option<wlan_policy::Credential>,
474) -> bool {
475 let config_id = match &config.id {
476 Some(id) => id,
477 None => {
478 return false;
479 }
480 };
481
482 if config_id.ssid != *ssid {
483 return false;
484 }
485
486 if let Some(security) = *security_type {
488 if config_id.type_ != security {
489 return false;
490 }
491 }
492 if credential.is_some() {
493 if config.credential != *credential {
494 return false;
495 }
496 }
497
498 return true;
499}
500
501pub async fn handle_save_network(
503 client_controller: wlan_policy::ClientControllerProxy,
504 config: wlan_policy::NetworkConfig,
505) -> Result<(), Error> {
506 save_network(client_controller, config).await
507}
508
509async fn save_network(
510 client_controller: wlan_policy::ClientControllerProxy,
511 network_config: wlan_policy::NetworkConfig,
512) -> Result<(), Error> {
513 run_proxy_command(Box::pin(client_controller.save_network(&network_config)))
514 .await?
515 .map_err(|e| format_err!("failed to save network with {:?}", e))?;
516 println!(
517 "Successfully saved network '{}'",
518 std::str::from_utf8(&network_config.id.unwrap().ssid).unwrap()
519 );
520 Ok(())
521}
522
523pub async fn handle_scan(
525 client_controller: wlan_policy::ClientControllerProxy,
526) -> Result<Vec<wlan_policy::ScanResult>, Error> {
527 let (client_proxy, server_end) =
528 client_controller.domain().create_proxy::<wlan_policy::ScanResultIteratorMarker>();
529 let fut = async { client_controller.scan_for_networks(server_end) };
530 run_proxy_command(Box::pin(fut)).await?;
531
532 let mut scanned_networks = Vec::<wlan_policy::ScanResult>::new();
533 loop {
534 match run_proxy_command(Box::pin(client_proxy.get_next())).await? {
535 Ok(mut new_networks) => {
536 if new_networks.is_empty() {
537 break;
538 }
539 scanned_networks.append(&mut new_networks);
540 }
541 Err(e) => return Err(format_err!("Scan failure error: {:?}", e)),
542 }
543 }
544
545 Ok(scanned_networks)
546}
547
548pub async fn handle_start_client_connections(
550 client_controller: wlan_policy::ClientControllerProxy,
551) -> Result<(), Error> {
552 let status = run_proxy_command(Box::pin(client_controller.start_client_connections())).await?;
553 return handle_request_status(status);
554}
555
556pub async fn handle_stop_client_connections(
558 client_controller: wlan_policy::ClientControllerProxy,
559) -> Result<(), Error> {
560 let status = run_proxy_command(Box::pin(client_controller.stop_client_connections())).await?;
561 return handle_request_status(status);
562}
563
564pub async fn handle_start_ap(
566 ap_controller: wlan_policy::AccessPointControllerProxy,
567 mut server_stream: wlan_policy::AccessPointStateUpdatesRequestStream,
568 config: wlan_policy::NetworkConfig,
569) -> Result<(), Error> {
570 let connectivity_mode = wlan_policy::ConnectivityMode::Unrestricted;
571 let operating_band = wlan_policy::OperatingBand::Any;
572 let result = run_proxy_command(Box::pin(ap_controller.start_access_point(
573 &config,
574 connectivity_mode,
575 operating_band,
576 )))
577 .await?;
578 handle_request_status(result)?;
579
580 while let Some(update_request) = server_stream.try_next().await? {
582 let update = update_request.into_on_access_point_state_update();
583 let (updates, responder) = match update {
584 Some((update, responder)) => (update, responder),
585 None => return Err(format_err!("AP provider produced invalid update.")),
586 };
587 let _ = responder.send();
588
589 for update in updates {
590 match update.state {
591 Some(state) => match state {
592 wlan_policy::OperatingState::Failed => {
593 return Err(format_err!("Failed to start AP."));
594 }
595 wlan_policy::OperatingState::Starting => {
596 println!("AP is starting.");
597 continue;
598 }
599 wlan_policy::OperatingState::Active => return Ok(()),
600 },
601 None => continue,
602 }
603 }
604 }
605 Err(format_err!("Status stream terminated before AP start could be verified."))
606}
607
608pub async fn handle_stop_ap(
610 ap_controller: wlan_policy::AccessPointControllerProxy,
611 config: wlan_policy::NetworkConfig,
612) -> Result<(), Error> {
613 let result = run_proxy_command(Box::pin(ap_controller.stop_access_point(&config))).await?;
614 handle_request_status(result)
615}
616
617pub async fn handle_stop_all_aps(
619 ap_controller: wlan_policy::AccessPointControllerProxy,
620) -> Result<(), Error> {
621 let fut = async { ap_controller.stop_all_access_points() };
622 run_proxy_command(Box::pin(fut)).await?;
623 Ok(())
624}
625
626pub async fn handle_ap_listen(
628 mut server_stream: wlan_policy::AccessPointStateUpdatesRequestStream,
629 single_sample: bool,
630) -> Result<(), Error> {
631 println!(
632 "{:32} | {:4} | {:8} | {:12} | {:6} | {:4} | {:7}",
633 "SSID", "Type", "State", "Mode", "Band", "Freq", "#Clients"
634 );
635
636 while let Some(update_request) = server_stream.try_next().await? {
637 let updates = update_request.into_on_access_point_state_update();
638 let (updates, responder) = match updates {
639 Some((update, responder)) => (update, responder),
640 None => return Err(format_err!("AP provider produced invalid update.")),
641 };
642 let _ = responder.send();
643
644 for update in updates {
645 let (ssid, security_type) = match update.id {
646 Some(network_id) => {
647 let ssid = network_id.ssid.clone();
648 let ssid = String::from_utf8(ssid)?;
649 let security_type = match network_id.type_ {
650 wlan_policy::SecurityType::None => "none",
651 wlan_policy::SecurityType::Wep => "wep",
652 wlan_policy::SecurityType::Wpa => "wpa",
653 wlan_policy::SecurityType::Wpa2 => "wpa2",
654 wlan_policy::SecurityType::Wpa3 => "wpa3",
655 };
656 (ssid, security_type.to_string())
657 }
658 None => ("".to_string(), "".to_string()),
659 };
660 let state = match update.state {
661 Some(state) => match state {
662 wlan_policy::OperatingState::Failed => "failed",
663 wlan_policy::OperatingState::Starting => "starting",
664 wlan_policy::OperatingState::Active => "active",
665 },
666 None => "",
667 };
668 let mode = match update.mode {
669 Some(mode) => match mode {
670 wlan_policy::ConnectivityMode::LocalOnly => "local only",
671 wlan_policy::ConnectivityMode::Unrestricted => "unrestricted",
672 },
673 None => "",
674 };
675 let band = match update.band {
676 Some(band) => match band {
677 wlan_policy::OperatingBand::Any => "any",
678 wlan_policy::OperatingBand::Only24Ghz => "2.4Ghz",
679 wlan_policy::OperatingBand::Only5Ghz => "5Ghz",
680 },
681 None => "",
682 };
683 let frequency = match update.frequency {
684 Some(frequency) => frequency.to_string(),
685 None => "".to_string(),
686 };
687 let client_count = match update.clients {
688 Some(connected_clients) => match connected_clients.count {
689 Some(count) => count.to_string(),
690 None => "".to_string(),
691 },
692 None => "".to_string(),
693 };
694
695 println!(
696 "{:32} | {:4} | {:8} | {:12} | {:6} | {:4} | {:7}",
697 ssid, security_type, state, mode, band, frequency, client_count
698 );
699 }
700
701 if single_sample {
703 break;
704 }
705 }
706 Ok(())
707}
708
709pub async fn handle_suggest_ap_mac(
710 configurator: wlan_deprecated::DeprecatedConfiguratorProxy,
711 mac: MacAddress,
712) -> Result<(), Error> {
713 let mac = net::MacAddress { octets: mac.to_array() };
714 let result = configurator.suggest_access_point_mac_address(&mac).await?;
715 result.map_err(|e| format_err!("suggesting MAC failed: {:?}", e))
716}
717
718#[cfg(test)]
719mod tests {
720 use super::*;
721 use assert_matches::assert_matches;
722 use fidl::endpoints;
723 use fuchsia_async::TestExecutor;
724 use futures::stream::StreamExt;
725 use futures::task::Poll;
726 use std::pin::pin;
727 use test_case::test_case;
728 use zx_status;
729
730 static TEST_SSID: &str = "test_ssid";
731 static TEST_PASSWORD: &str = "test_password";
732
733 struct ClientTestValues {
734 client_proxy: wlan_policy::ClientControllerProxy,
735 client_stream: wlan_policy::ClientControllerRequestStream,
736 update_proxy: wlan_policy::ClientStateUpdatesProxy,
737 update_stream: wlan_policy::ClientStateUpdatesRequestStream,
738 }
739
740 fn client_test_setup() -> ClientTestValues {
741 let (client_proxy, client_stream) =
742 endpoints::create_proxy_and_stream::<wlan_policy::ClientControllerMarker>();
743
744 let (listener_proxy, listener_stream) =
745 endpoints::create_proxy_and_stream::<wlan_policy::ClientStateUpdatesMarker>();
746
747 ClientTestValues {
748 client_proxy: client_proxy,
749 client_stream: client_stream,
750 update_proxy: listener_proxy,
751 update_stream: listener_stream,
752 }
753 }
754
755 fn send_client_request_status(
758 exec: &mut TestExecutor,
759 server: &mut wlan_policy::ClientControllerRequestStream,
760 response: wlan_policy::RequestStatus,
761 ) {
762 let poll = exec.run_until_stalled(&mut server.next());
763 let request = match poll {
764 Poll::Ready(poll_ready) => poll_ready
765 .expect("poll ready result is None")
766 .expect("poll ready result is an Error"),
767 Poll::Pending => panic!("no ClientController request available"),
768 };
769
770 let result = match request {
771 wlan_policy::ClientControllerRequest::StartClientConnections { responder } => {
772 responder.send(response)
773 }
774 wlan_policy::ClientControllerRequest::StopClientConnections { responder } => {
775 responder.send(response)
776 }
777 wlan_policy::ClientControllerRequest::Connect { responder, .. } => {
778 responder.send(response)
779 }
780 _ => panic!("expecting a request that expects a RequestStatus"),
781 };
782
783 if result.is_err() {
784 panic!("could not send request status");
785 }
786 }
787
788 fn create_client_state_summary(
790 ssid: &str,
791 state: wlan_policy::ConnectionState,
792 ) -> wlan_policy::ClientStateSummary {
793 let network_state = wlan_policy::NetworkState {
794 id: Some(create_network_id(ssid)),
795 state: Some(state),
796 status: None,
797 ..Default::default()
798 };
799 wlan_policy::ClientStateSummary {
800 state: Some(wlan_policy::WlanClientState::ConnectionsEnabled),
801 networks: Some(vec![network_state]),
802 ..Default::default()
803 }
804 }
805
806 fn create_ap_state_summary(
808 state: wlan_policy::OperatingState,
809 ) -> wlan_policy::AccessPointState {
810 wlan_policy::AccessPointState {
811 id: None,
812 state: Some(state),
813 mode: None,
814 band: None,
815 frequency: None,
816 clients: None,
817 ..Default::default()
818 }
819 }
820
821 #[track_caller]
823 fn send_network_config_response(
824 exec: &mut TestExecutor,
825 server: &mut wlan_policy::ClientControllerRequestStream,
826 success: bool,
827 ) {
828 let poll = exec.run_until_stalled(&mut server.next());
829 let request = match poll {
830 Poll::Ready(poll_ready) => poll_ready
831 .expect("poll ready result is None")
832 .expect("poll ready result is an Error"),
833 Poll::Pending => panic!("no ClientController request available"),
834 };
835
836 let result = match request {
837 wlan_policy::ClientControllerRequest::SaveNetwork { config: _, responder } => {
838 if success {
839 responder.send(Ok(()))
840 } else {
841 responder.send(Err(wlan_policy::NetworkConfigChangeError::GeneralError))
842 }
843 }
844 wlan_policy::ClientControllerRequest::RemoveNetwork { config: _, responder } => {
845 if success {
846 responder.send(Ok(()))
847 } else {
848 responder.send(Err(wlan_policy::NetworkConfigChangeError::GeneralError))
849 }
850 }
851 _ => panic!("expecting a request that optionally receives a NetworkConfigChangeError"),
852 };
853
854 if result.is_err() {
855 panic!("could not send network config response");
856 }
857 }
858
859 struct ApTestValues {
860 ap_proxy: wlan_policy::AccessPointControllerProxy,
861 ap_stream: wlan_policy::AccessPointControllerRequestStream,
862 update_proxy: wlan_policy::AccessPointStateUpdatesProxy,
863 update_stream: wlan_policy::AccessPointStateUpdatesRequestStream,
864 }
865
866 fn ap_test_setup() -> ApTestValues {
867 let (ap_proxy, ap_stream) =
868 endpoints::create_proxy_and_stream::<wlan_policy::AccessPointControllerMarker>();
869
870 let (listener_proxy, listener_stream) =
871 endpoints::create_proxy_and_stream::<wlan_policy::AccessPointStateUpdatesMarker>();
872
873 ApTestValues {
874 ap_proxy,
875 ap_stream,
876 update_proxy: listener_proxy,
877 update_stream: listener_stream,
878 }
879 }
880
881 fn send_ap_request_status(
884 exec: &mut TestExecutor,
885 server: &mut wlan_policy::AccessPointControllerRequestStream,
886 response: wlan_policy::RequestStatus,
887 ) {
888 let poll = exec.run_until_stalled(&mut server.next());
889 let request = match poll {
890 Poll::Ready(poll_ready) => poll_ready
891 .expect("poll ready result is None")
892 .expect("poll ready result is an Error"),
893 Poll::Pending => panic!("no AccessPointController request available"),
894 };
895
896 let result = match request {
897 wlan_policy::AccessPointControllerRequest::StartAccessPoint { responder, .. } => {
898 responder.send(response)
899 }
900 wlan_policy::AccessPointControllerRequest::StopAccessPoint { config: _, responder } => {
901 responder.send(response)
902 }
903 _ => panic!("expecting a request that expects a RequestStatus"),
904 };
905
906 if result.is_err() {
907 panic!("could not send request status");
908 }
909 }
910
911 fn create_network_id(ssid: &str) -> wlan_policy::NetworkIdentifier {
913 wlan_policy::NetworkIdentifier {
914 ssid: ssid.as_bytes().to_vec(),
915 type_: wlan_policy::SecurityType::Wpa2,
916 }
917 }
918
919 fn create_network_config(ssid: &str) -> wlan_policy::NetworkConfig {
921 wlan_policy::NetworkConfig {
922 id: Some(create_network_id(ssid)),
923 credential: Some(create_password(TEST_PASSWORD)),
924 ..Default::default()
925 }
926 }
927
928 fn create_password(val: &str) -> wlan_policy::Credential {
929 wlan_policy::Credential::Password(val.as_bytes().to_vec())
930 }
931
932 fn create_network_config_with_security(
934 ssid: &str,
935 security: wlan_policy::SecurityType,
936 ) -> wlan_policy::NetworkConfig {
937 let id = wlan_policy::NetworkIdentifier { ssid: ssid.as_bytes().to_vec(), type_: security };
938 wlan_policy::NetworkConfig { id: Some(id), credential: None, ..Default::default() }
939 }
940
941 fn create_scan_result(ssid: &str) -> wlan_policy::ScanResult {
943 wlan_policy::ScanResult {
944 id: Some(create_network_id(ssid)),
945 entries: None,
946 compatibility: None,
947 ..Default::default()
948 }
949 }
950
951 fn get_scan_result_iterator(
954 exec: &mut TestExecutor,
955 mut server: wlan_policy::ClientControllerRequestStream,
956 ) -> wlan_policy::ScanResultIteratorRequestStream {
957 let poll = exec.run_until_stalled(&mut server.next());
958 let request = match poll {
959 Poll::Ready(poll_ready) => poll_ready
960 .expect("poll ready result is None")
961 .expect("poll ready result is an Error"),
962 Poll::Pending => panic!("no ClientController request available"),
963 };
964
965 match request {
966 wlan_policy::ClientControllerRequest::ScanForNetworks {
967 iterator,
968 control_handle: _,
969 } => iterator.into_stream(),
970 _ => panic!("expecting a ScanForNetworks"),
971 }
972 }
973
974 fn send_scan_result(
976 exec: &mut TestExecutor,
977 server: &mut wlan_policy::ScanResultIteratorRequestStream,
978 scan_result: Result<&[wlan_policy::ScanResult], wlan_policy::ScanErrorCode>,
979 ) {
980 assert_matches!(
981 exec.run_until_stalled(&mut server.next()),
982 Poll::Ready(Some(Ok(wlan_policy::ScanResultIteratorRequest::GetNext {
983 responder
984 }))) => {
985 match responder.send(scan_result) {
986 Ok(()) => {}
987 Err(e) => panic!("failed to send scan result: {}", e),
988 }
989 }
990 );
991 }
992
993 #[track_caller]
996 fn get_saved_networks_iterator(
997 exec: &mut TestExecutor,
998 server: &mut wlan_policy::ClientControllerRequestStream,
999 ) -> wlan_policy::NetworkConfigIteratorRequestStream {
1000 let poll = exec.run_until_stalled(&mut server.next());
1001 let request = match poll {
1002 Poll::Ready(poll_ready) => poll_ready
1003 .expect("poll ready result is None")
1004 .expect("poll ready result is an Error"),
1005 Poll::Pending => panic!("no ClientController request available"),
1006 };
1007
1008 match request {
1009 wlan_policy::ClientControllerRequest::GetSavedNetworks {
1010 iterator,
1011 control_handle: _,
1012 } => iterator.into_stream(),
1013 _ => panic!("expecting a ScanForNetworks"),
1014 }
1015 }
1016
1017 fn send_saved_networks(
1019 exec: &mut TestExecutor,
1020 server: &mut wlan_policy::NetworkConfigIteratorRequestStream,
1021 saved_networks_response: Vec<wlan_policy::NetworkConfig>,
1022 ) {
1023 assert_matches!(
1024 exec.run_until_stalled(&mut server.next()),
1025 Poll::Ready(Some(Ok(wlan_policy::NetworkConfigIteratorRequest::GetNext {
1026 responder
1027 }))) => {
1028 match responder.send(&saved_networks_response) {
1029 Ok(()) => {}
1030 Err(e) => panic!("failed to send saved networks: {}", e),
1031 }
1032 }
1033 );
1034 }
1035
1036 #[fuchsia::test]
1038 fn test_start_client_connections_success() {
1039 let mut exec = TestExecutor::new();
1040 let mut test_values = client_test_setup();
1041 let fut = handle_start_client_connections(test_values.client_proxy);
1042 let mut fut = pin!(fut);
1043
1044 assert!(exec.run_until_stalled(&mut fut).is_pending());
1046
1047 send_client_request_status(
1049 &mut exec,
1050 &mut test_values.client_stream,
1051 wlan_policy::RequestStatus::Acknowledged,
1052 );
1053
1054 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1055 }
1056
1057 #[fuchsia::test]
1059 fn test_start_client_connections_fail() {
1060 let mut exec = TestExecutor::new();
1061 let mut test_values = client_test_setup();
1062 let fut = handle_start_client_connections(test_values.client_proxy);
1063 let mut fut = pin!(fut);
1064
1065 assert!(exec.run_until_stalled(&mut fut).is_pending());
1067
1068 send_client_request_status(
1070 &mut exec,
1071 &mut test_values.client_stream,
1072 wlan_policy::RequestStatus::RejectedNotSupported,
1073 );
1074
1075 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1076 }
1077
1078 #[fuchsia::test]
1080 fn test_stop_client_connections_success() {
1081 let mut exec = TestExecutor::new();
1082 let mut test_values = client_test_setup();
1083 let fut = handle_stop_client_connections(test_values.client_proxy);
1084 let mut fut = pin!(fut);
1085
1086 assert!(exec.run_until_stalled(&mut fut).is_pending());
1088
1089 send_client_request_status(
1091 &mut exec,
1092 &mut test_values.client_stream,
1093 wlan_policy::RequestStatus::Acknowledged,
1094 );
1095
1096 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1097 }
1098
1099 #[fuchsia::test]
1101 fn test_stop_client_connections_fail() {
1102 let mut exec = TestExecutor::new();
1103 let mut test_values = client_test_setup();
1104 let fut = handle_stop_client_connections(test_values.client_proxy);
1105 let mut fut = pin!(fut);
1106
1107 assert!(exec.run_until_stalled(&mut fut).is_pending());
1109
1110 send_client_request_status(
1112 &mut exec,
1113 &mut test_values.client_stream,
1114 wlan_policy::RequestStatus::RejectedNotSupported,
1115 );
1116
1117 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1118 }
1119
1120 #[fuchsia::test]
1122 fn test_save_network_pass() {
1123 let mut exec = TestExecutor::new();
1124 let mut test_values = client_test_setup();
1125 let config = create_network_config(TEST_SSID);
1126 let fut = handle_save_network(test_values.client_proxy, config);
1127 let mut fut = pin!(fut);
1128
1129 assert!(exec.run_until_stalled(&mut fut).is_pending());
1131
1132 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1134
1135 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1136 }
1137
1138 #[fuchsia::test]
1140 fn test_save_network_fail() {
1141 let mut exec = TestExecutor::new();
1142 let mut test_values = client_test_setup();
1143 let config = create_network_config(TEST_SSID);
1144 let fut = handle_save_network(test_values.client_proxy, config);
1145 let mut fut = pin!(fut);
1146
1147 assert!(exec.run_until_stalled(&mut fut).is_pending());
1149
1150 send_network_config_response(&mut exec, &mut test_values.client_stream, false);
1152
1153 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1154 }
1155
1156 #[fuchsia::test]
1158 fn test_remove_network_pass() {
1159 let mut exec = TestExecutor::new();
1160 let mut test_values = client_test_setup();
1161 let security = Some(wlan_policy::SecurityType::Wpa2);
1162 let credential = Some(create_password(TEST_PASSWORD));
1163 let fut =
1164 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1165 let mut fut = pin!(fut);
1166 assert!(exec.run_until_stalled(&mut fut).is_pending());
1167
1168 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1170 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1171 assert!(exec.run_until_stalled(&mut fut).is_pending());
1172 send_saved_networks(&mut exec, &mut iterator, vec![]);
1173
1174 assert!(exec.run_until_stalled(&mut fut).is_pending());
1176
1177 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1179 assert!(exec.run_until_stalled(&mut fut).is_pending());
1180
1181 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1183 send_saved_networks(&mut exec, &mut iterator, vec![]);
1184
1185 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1186 }
1187
1188 #[fuchsia::test]
1192 fn test_remove_network_ssid_only_pass() {
1193 let mut exec = TestExecutor::new();
1194 let mut test_values = client_test_setup();
1195
1196 let security = None;
1198 let credential = None;
1199 let fut =
1200 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1201 let mut fut = pin!(fut);
1202
1203 assert!(exec.run_until_stalled(&mut fut).is_pending());
1205
1206 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1208 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1209 assert!(exec.run_until_stalled(&mut fut).is_pending());
1210 send_saved_networks(&mut exec, &mut iterator, vec![]);
1211
1212 assert!(exec.run_until_stalled(&mut fut).is_pending());
1214
1215 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1217 assert!(exec.run_until_stalled(&mut fut).is_pending());
1218
1219 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1221 send_saved_networks(&mut exec, &mut iterator, vec![]);
1222
1223 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1224 }
1225
1226 #[fuchsia::test]
1230 fn test_remove_network_unspecified_security_pass() {
1231 let mut exec = TestExecutor::new();
1232 let mut test_values = client_test_setup();
1233
1234 let security = None;
1236 let credential = Some(create_password(TEST_PASSWORD));
1237 let fut =
1238 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1239 let mut fut = pin!(fut);
1240
1241 assert!(exec.run_until_stalled(&mut fut).is_pending());
1243
1244 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1246 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1247 assert!(exec.run_until_stalled(&mut fut).is_pending());
1248 send_saved_networks(&mut exec, &mut iterator, vec![]);
1249
1250 assert!(exec.run_until_stalled(&mut fut).is_pending());
1252
1253 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1255 assert!(exec.run_until_stalled(&mut fut).is_pending());
1256
1257 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1259 send_saved_networks(&mut exec, &mut iterator, vec![]);
1260
1261 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1262 }
1263
1264 #[fuchsia::test]
1268 fn test_remove_network_no_credential_pass() {
1269 let mut exec = TestExecutor::new();
1270 let mut test_values = client_test_setup();
1271
1272 let security = Some(wlan_policy::SecurityType::Wpa2);
1274 let credential = None;
1275 let fut =
1276 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1277 let mut fut = pin!(fut);
1278
1279 assert!(exec.run_until_stalled(&mut fut).is_pending());
1281
1282 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1284 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1285 assert!(exec.run_until_stalled(&mut fut).is_pending());
1286 send_saved_networks(&mut exec, &mut iterator, vec![]);
1287
1288 assert!(exec.run_until_stalled(&mut fut).is_pending());
1290
1291 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1293 assert!(exec.run_until_stalled(&mut fut).is_pending());
1294
1295 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1297 send_saved_networks(&mut exec, &mut iterator, vec![]);
1298
1299 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1300 }
1301
1302 #[fuchsia::test]
1305 fn test_remove_network_ssid_only_no_match_fails() {
1306 let mut exec = TestExecutor::new();
1307 let mut test_values = client_test_setup();
1308
1309 let security = None;
1311 let credential = None;
1312 let fut =
1313 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1314 let mut fut = pin!(fut);
1315
1316 assert!(exec.run_until_stalled(&mut fut).is_pending());
1318
1319 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1321 send_saved_networks(
1322 &mut exec,
1323 &mut iterator,
1324 vec![create_network_config("some-other-ssid")],
1325 );
1326 assert!(exec.run_until_stalled(&mut fut).is_pending());
1327 send_saved_networks(&mut exec, &mut iterator, vec![]);
1328
1329 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1331 }
1332
1333 #[fuchsia::test]
1335 fn test_remove_network_fail() {
1336 let mut exec = TestExecutor::new();
1337 let mut test_values = client_test_setup();
1338 let security = Some(wlan_policy::SecurityType::Wpa2);
1339 let credential = Some(create_password(TEST_PASSWORD));
1340 let fut =
1341 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1342 let mut fut = pin!(fut);
1343 assert!(exec.run_until_stalled(&mut fut).is_pending());
1344
1345 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1347 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1348 assert!(exec.run_until_stalled(&mut fut).is_pending());
1349 send_saved_networks(&mut exec, &mut iterator, vec![]);
1350
1351 assert!(exec.run_until_stalled(&mut fut).is_pending());
1353
1354 send_network_config_response(&mut exec, &mut test_values.client_stream, false);
1356
1357 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1358 }
1359
1360 #[fuchsia::test]
1362 fn test_remove_network_not_removed_fails() {
1363 let mut exec = TestExecutor::new();
1364 let mut test_values = client_test_setup();
1365 let security = Some(wlan_policy::SecurityType::Wpa2);
1366 let credential = Some(create_password(TEST_PASSWORD));
1367 let fut =
1368 handle_remove_network(test_values.client_proxy, TEST_SSID.into(), security, credential);
1369 let mut fut = pin!(fut);
1370 assert!(exec.run_until_stalled(&mut fut).is_pending());
1371
1372 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1374 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1375 assert!(exec.run_until_stalled(&mut fut).is_pending());
1376 send_saved_networks(&mut exec, &mut iterator, vec![]);
1377
1378 assert!(exec.run_until_stalled(&mut fut).is_pending());
1380
1381 send_network_config_response(&mut exec, &mut test_values.client_stream, true);
1383 assert!(exec.run_until_stalled(&mut fut).is_pending());
1384
1385 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1388 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1389 assert!(exec.run_until_stalled(&mut fut).is_pending());
1390 send_saved_networks(&mut exec, &mut iterator, vec![]);
1391
1392 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1393 }
1394
1395 #[test_case(
1399 TEST_SSID,
1400 Some(wlan_policy::SecurityType::Wpa2),
1401 Some(create_password(TEST_PASSWORD)),
1402 true
1403 )]
1404 #[test_case(TEST_SSID, Some(wlan_policy::SecurityType::Wpa2), None, true)]
1405 #[test_case(TEST_SSID, None, Some(create_password(TEST_PASSWORD)), true)]
1406 #[test_case(TEST_SSID, None, None, true)]
1407 #[test_case(
1408 TEST_SSID,
1409 Some(wlan_policy::SecurityType::Wpa2),
1410 Some(create_password("otherpassword")),
1411 false
1412 )]
1413 #[test_case(TEST_SSID, None, Some(create_password("otherpassword")), false)]
1414 #[test_case(
1415 TEST_SSID,
1416 Some(wlan_policy::SecurityType::Wpa3),
1417 Some(create_password(TEST_PASSWORD)),
1418 false
1419 )]
1420 #[test_case(TEST_SSID, Some(wlan_policy::SecurityType::Wpa3), None, false)]
1421 #[test_case(
1422 "otherssid",
1423 Some(wlan_policy::SecurityType::Wpa3),
1424 Some(create_password(TEST_PASSWORD)),
1425 false
1426 )]
1427 #[test_case("otherssid", None, None, false)]
1428 #[fuchsia::test(add_test_attr = false)]
1429 fn test_config_matches_config(
1430 ssid: &str,
1431 security: Option<wlan_policy::SecurityType>,
1432 credential: Option<wlan_policy::Credential>,
1433 expected_result: bool,
1434 ) {
1435 let ssid = ssid.as_bytes().to_vec();
1436 let config = create_network_config(TEST_SSID);
1437 let result = config_matches(&config, &ssid, &security, &credential);
1438 assert_eq!(result, expected_result);
1439 }
1440
1441 #[fuchsia::test]
1443 fn test_connect_pass() {
1444 let mut exec = TestExecutor::new();
1445 let mut test_values = client_test_setup();
1446
1447 let ssid = TEST_SSID.to_string();
1449 let security = Some(wlan_policy::SecurityType::Wpa2);
1450 let fut =
1451 handle_connect(test_values.client_proxy, test_values.update_stream, ssid, security);
1452 let mut fut = pin!(fut);
1453
1454 assert!(exec.run_until_stalled(&mut fut).is_pending());
1456
1457 send_client_request_status(
1459 &mut exec,
1460 &mut test_values.client_stream,
1461 wlan_policy::RequestStatus::Acknowledged,
1462 );
1463
1464 assert!(exec.run_until_stalled(&mut fut).is_pending());
1466 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1467 TEST_SSID,
1468 wlan_policy::ConnectionState::Connecting,
1469 ));
1470
1471 assert!(exec.run_until_stalled(&mut fut).is_pending());
1473 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1474 TEST_SSID,
1475 wlan_policy::ConnectionState::Connected,
1476 ));
1477
1478 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1480 }
1481
1482 #[fuchsia::test]
1485 fn test_connect_unspecified_security_pass() {
1486 let mut exec = TestExecutor::new();
1487 let mut test_values = client_test_setup();
1488
1489 let ssid = TEST_SSID.to_string();
1491 let fut = handle_connect(test_values.client_proxy, test_values.update_stream, ssid, None);
1492 let mut fut = pin!(fut);
1493
1494 assert!(exec.run_until_stalled(&mut fut).is_pending());
1496
1497 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1499 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1500 assert!(exec.run_until_stalled(&mut fut).is_pending());
1501
1502 send_saved_networks(&mut exec, &mut iterator, vec![]);
1504
1505 assert!(exec.run_until_stalled(&mut fut).is_pending());
1507
1508 send_client_request_status(
1510 &mut exec,
1511 &mut test_values.client_stream,
1512 wlan_policy::RequestStatus::Acknowledged,
1513 );
1514
1515 assert!(exec.run_until_stalled(&mut fut).is_pending());
1517 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1518 TEST_SSID,
1519 wlan_policy::ConnectionState::Connecting,
1520 ));
1521
1522 assert!(exec.run_until_stalled(&mut fut).is_pending());
1524 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1525 TEST_SSID,
1526 wlan_policy::ConnectionState::Connected,
1527 ));
1528
1529 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1531 }
1532
1533 #[fuchsia::test]
1536 fn test_connect_no_security_given_nothing_saved_fails() {
1537 let mut exec = TestExecutor::new();
1538 let mut test_values = client_test_setup();
1539
1540 let ssid = TEST_SSID.to_string();
1542 let fut = handle_connect(test_values.client_proxy, test_values.update_stream, ssid, None);
1543 let mut fut = pin!(fut);
1544
1545 assert!(exec.run_until_stalled(&mut fut).is_pending());
1547
1548 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1550 send_saved_networks(&mut exec, &mut iterator, vec![]);
1551
1552 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1554
1555 assert_matches!(
1557 exec.run_until_stalled(&mut test_values.client_stream.next()),
1558 Poll::Ready(None)
1559 );
1560 }
1561
1562 #[fuchsia::test]
1565 fn test_connect_no_security_given_multiple_saved_fails() {
1566 let mut exec = TestExecutor::new();
1567 let mut test_values = client_test_setup();
1568
1569 let ssid = TEST_SSID.to_string();
1571 let fut = handle_connect(test_values.client_proxy, test_values.update_stream, ssid, None);
1572 let mut fut = pin!(fut);
1573
1574 assert!(exec.run_until_stalled(&mut fut).is_pending());
1576
1577 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1579 let wpa_config =
1580 create_network_config_with_security(TEST_SSID, wlan_policy::SecurityType::Wpa);
1581 let networks = vec![create_network_config(TEST_SSID), wpa_config];
1582
1583 send_saved_networks(&mut exec, &mut iterator, networks);
1584 assert!(exec.run_until_stalled(&mut fut).is_pending());
1585
1586 send_saved_networks(&mut exec, &mut iterator, vec![]);
1588
1589 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1591
1592 assert_matches!(
1594 exec.run_until_stalled(&mut test_values.client_stream.next()),
1595 Poll::Ready(None)
1596 );
1597 }
1598
1599 #[fuchsia::test]
1601 fn test_connect_fail() {
1602 let mut exec = TestExecutor::new();
1603 let mut test_values = client_test_setup();
1604
1605 let ssid = TEST_SSID.to_string();
1607 let security = Some(wlan_policy::SecurityType::Wpa2);
1608 let fut =
1609 handle_connect(test_values.client_proxy, test_values.update_stream, ssid, security);
1610 let mut fut = pin!(fut);
1611
1612 assert!(exec.run_until_stalled(&mut fut).is_pending());
1614
1615 send_client_request_status(
1617 &mut exec,
1618 &mut test_values.client_stream,
1619 wlan_policy::RequestStatus::Acknowledged,
1620 );
1621
1622 assert!(exec.run_until_stalled(&mut fut).is_pending());
1624 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1625 TEST_SSID,
1626 wlan_policy::ConnectionState::Failed,
1627 ));
1628
1629 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1631 }
1632
1633 #[fuchsia::test]
1635 fn test_scan_pass() {
1636 let mut exec = TestExecutor::new();
1637 let test_values = client_test_setup();
1638
1639 let fut = handle_scan(test_values.client_proxy);
1640 let mut fut = pin!(fut);
1641
1642 assert!(exec.run_until_stalled(&mut fut).is_pending());
1644
1645 let mut iterator = get_scan_result_iterator(&mut exec, test_values.client_stream);
1647 send_scan_result(&mut exec, &mut iterator, Ok(&[create_scan_result(TEST_SSID)]));
1648
1649 assert!(exec.run_until_stalled(&mut fut).is_pending());
1651
1652 send_scan_result(&mut exec, &mut iterator, Ok(&[]));
1654
1655 assert_matches!(
1657 exec.run_until_stalled(&mut fut),
1658 Poll::Ready(Ok(result)) => {
1659 assert_eq!(result.len(), 1);
1660 assert_eq!(result[0].id.as_ref().unwrap().ssid, TEST_SSID.as_bytes().to_vec());
1661 }
1662 );
1663 }
1664
1665 #[fuchsia::test]
1667 fn test_scan_fail() {
1668 let mut exec = TestExecutor::new();
1669 let test_values = client_test_setup();
1670
1671 let fut = handle_scan(test_values.client_proxy);
1672 let mut fut = pin!(fut);
1673
1674 assert!(exec.run_until_stalled(&mut fut).is_pending());
1676
1677 let mut iterator = get_scan_result_iterator(&mut exec, test_values.client_stream);
1679 send_scan_result(&mut exec, &mut iterator, Err(wlan_policy::ScanErrorCode::GeneralError));
1680
1681 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1683 }
1684
1685 #[fuchsia::test]
1687 fn test_get_saved_networks() {
1688 let mut exec = TestExecutor::new();
1689 let mut test_values = client_test_setup();
1690
1691 let fut = handle_get_saved_networks(&test_values.client_proxy);
1692 let mut fut = pin!(fut);
1693
1694 assert!(exec.run_until_stalled(&mut fut).is_pending());
1696
1697 let mut iterator = get_saved_networks_iterator(&mut exec, &mut test_values.client_stream);
1699 send_saved_networks(&mut exec, &mut iterator, vec![create_network_config(TEST_SSID)]);
1700 assert!(exec.run_until_stalled(&mut fut).is_pending());
1701
1702 send_saved_networks(&mut exec, &mut iterator, vec![]);
1704
1705 assert_matches!(
1707 exec.run_until_stalled(&mut fut),
1708 Poll::Ready(Ok(result)) => {
1709 assert_eq!(result.len(), 1);
1710 assert_eq!(result[0].id.as_ref().unwrap().ssid, TEST_SSID.as_bytes().to_vec());
1711 }
1712 );
1713 }
1714
1715 #[fuchsia::test]
1717 fn test_client_listen() {
1718 let mut exec = TestExecutor::new();
1719 let test_values = client_test_setup();
1720
1721 let fut = handle_listen(test_values.update_stream, false);
1722 let mut fut = pin!(fut);
1723
1724 assert!(exec.run_until_stalled(&mut fut).is_pending());
1726 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1727 TEST_SSID,
1728 wlan_policy::ConnectionState::Connecting,
1729 ));
1730
1731 assert!(exec.run_until_stalled(&mut fut).is_pending());
1733 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1734 TEST_SSID,
1735 wlan_policy::ConnectionState::Connected,
1736 ));
1737
1738 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1740 }
1741
1742 #[fuchsia::test]
1744 fn test_client_status() {
1745 let mut exec = TestExecutor::new();
1746 let test_values = client_test_setup();
1747
1748 let fut = handle_listen(test_values.update_stream, true);
1749 let mut fut = pin!(fut);
1750
1751 assert!(exec.run_until_stalled(&mut fut).is_pending());
1753 let _ = test_values.update_proxy.on_client_state_update(&create_client_state_summary(
1754 TEST_SSID,
1755 wlan_policy::ConnectionState::Connecting,
1756 ));
1757
1758 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1760 }
1761
1762 #[fuchsia::test]
1765 fn test_stop_ap_fail() {
1766 let mut exec = TestExecutor::new();
1767 let mut test_values = ap_test_setup();
1768
1769 let network_config = create_network_config(&TEST_SSID);
1770 let fut = handle_stop_ap(test_values.ap_proxy, network_config);
1771 let mut fut = pin!(fut);
1772
1773 assert!(exec.run_until_stalled(&mut fut).is_pending());
1775
1776 send_ap_request_status(
1778 &mut exec,
1779 &mut test_values.ap_stream,
1780 wlan_policy::RequestStatus::RejectedNotSupported,
1781 );
1782
1783 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1785 }
1786
1787 #[fuchsia::test]
1789 fn test_stop_ap_pass() {
1790 let mut exec = TestExecutor::new();
1791 let mut test_values = ap_test_setup();
1792
1793 let network_config = create_network_config(&TEST_SSID);
1794 let fut = handle_stop_ap(test_values.ap_proxy, network_config);
1795 let mut fut = pin!(fut);
1796
1797 assert!(exec.run_until_stalled(&mut fut).is_pending());
1799
1800 send_ap_request_status(
1802 &mut exec,
1803 &mut test_values.ap_stream,
1804 wlan_policy::RequestStatus::Acknowledged,
1805 );
1806
1807 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1809 }
1810
1811 #[fuchsia::test]
1813 fn test_start_ap_request_fail() {
1814 let mut exec = TestExecutor::new();
1815 let mut test_values = ap_test_setup();
1816
1817 let network_config = create_network_config(&TEST_SSID);
1818 let fut = handle_start_ap(test_values.ap_proxy, test_values.update_stream, network_config);
1819 let mut fut = pin!(fut);
1820
1821 assert!(exec.run_until_stalled(&mut fut).is_pending());
1823
1824 send_ap_request_status(
1826 &mut exec,
1827 &mut test_values.ap_stream,
1828 wlan_policy::RequestStatus::RejectedNotSupported,
1829 );
1830
1831 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1833 }
1834
1835 #[fuchsia::test]
1838 fn test_start_ap_pass() {
1839 let mut exec = TestExecutor::new();
1840 let mut test_values = ap_test_setup();
1841
1842 let network_config = create_network_config(&TEST_SSID);
1843 let fut = handle_start_ap(test_values.ap_proxy, test_values.update_stream, network_config);
1844 let mut fut = pin!(fut);
1845
1846 assert!(exec.run_until_stalled(&mut fut).is_pending());
1848
1849 send_ap_request_status(
1851 &mut exec,
1852 &mut test_values.ap_stream,
1853 wlan_policy::RequestStatus::Acknowledged,
1854 );
1855
1856 assert!(exec.run_until_stalled(&mut fut).is_pending());
1858
1859 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1861 wlan_policy::OperatingState::Starting,
1862 )]);
1863
1864 assert!(exec.run_until_stalled(&mut fut).is_pending());
1866
1867 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1869 wlan_policy::OperatingState::Active,
1870 )]);
1871
1872 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1874 }
1875
1876 #[fuchsia::test]
1879 fn test_ap_failed_to_start() {
1880 let mut exec = TestExecutor::new();
1881 let mut test_values = ap_test_setup();
1882
1883 let network_config = create_network_config(&TEST_SSID);
1884 let fut = handle_start_ap(test_values.ap_proxy, test_values.update_stream, network_config);
1885 let mut fut = pin!(fut);
1886
1887 assert!(exec.run_until_stalled(&mut fut).is_pending());
1889
1890 send_ap_request_status(
1892 &mut exec,
1893 &mut test_values.ap_stream,
1894 wlan_policy::RequestStatus::Acknowledged,
1895 );
1896
1897 assert!(exec.run_until_stalled(&mut fut).is_pending());
1899
1900 let state_updates = &[create_ap_state_summary(wlan_policy::OperatingState::Failed)];
1902 let _ = test_values.update_proxy.on_access_point_state_update(state_updates);
1903
1904 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
1906 }
1907
1908 #[fuchsia::test]
1910 fn test_stop_all_aps() {
1911 let mut exec = TestExecutor::new();
1912 let mut test_values = ap_test_setup();
1913
1914 let fut = handle_stop_all_aps(test_values.ap_proxy);
1915 let mut fut = pin!(fut);
1916
1917 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1919
1920 assert_matches!(
1922 exec.run_until_stalled(&mut test_values.ap_stream.next()),
1923 Poll::Ready(Some(Ok(
1924 wlan_policy::AccessPointControllerRequest::StopAllAccessPoints { .. }
1925 )))
1926 );
1927 }
1928
1929 #[fuchsia::test]
1931 fn test_ap_listen() {
1932 let mut exec = TestExecutor::new();
1933 let test_values = ap_test_setup();
1934
1935 let fut = handle_ap_listen(test_values.update_stream, false);
1936 let mut fut = pin!(fut);
1937
1938 assert!(exec.run_until_stalled(&mut fut).is_pending());
1940 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1941 wlan_policy::OperatingState::Starting,
1942 )]);
1943
1944 assert!(exec.run_until_stalled(&mut fut).is_pending());
1946 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1947 wlan_policy::OperatingState::Active,
1948 )]);
1949
1950 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1952 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1953 wlan_policy::OperatingState::Failed,
1954 )]);
1955
1956 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Pending);
1957 }
1958
1959 #[fuchsia::test]
1961 fn test_ap_status() {
1962 let mut exec = TestExecutor::new();
1963 let test_values = ap_test_setup();
1964
1965 let fut = handle_ap_listen(test_values.update_stream, true);
1966 let mut fut = pin!(fut);
1967
1968 assert!(exec.run_until_stalled(&mut fut).is_pending());
1970 let _ = test_values.update_proxy.on_access_point_state_update(&[create_ap_state_summary(
1971 wlan_policy::OperatingState::Starting,
1972 )]);
1973
1974 assert_matches!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
1976 }
1977
1978 #[fuchsia::test]
1979 fn test_suggest_ap_mac_succeeds() {
1980 let mut exec = TestExecutor::new();
1981
1982 let (configurator_proxy, mut configurator_stream) =
1983 endpoints::create_proxy_and_stream::<wlan_deprecated::DeprecatedConfiguratorMarker>();
1984 let mac = MacAddress::from_bytes(&[0, 1, 2, 3, 4, 5]).unwrap();
1985 let suggest_fut = handle_suggest_ap_mac(configurator_proxy, mac);
1986 let mut suggest_fut = pin!(suggest_fut);
1987
1988 assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Pending);
1989
1990 assert_matches!(
1991 exec.run_until_stalled(&mut configurator_stream.next()),
1992 Poll::Ready(Some(Ok(wlan_deprecated::DeprecatedConfiguratorRequest::SuggestAccessPointMacAddress {
1993 mac: net::MacAddress { octets: [0, 1, 2, 3, 4, 5] }, responder
1994 }))) => {
1995 assert!(responder.send(Ok(())).is_ok());
1996 }
1997 );
1998
1999 assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Ready(Ok(())));
2000 }
2001
2002 #[fuchsia::test]
2003 fn test_suggest_ap_mac_fails() {
2004 let mut exec = TestExecutor::new();
2005
2006 let (configurator_proxy, mut configurator_stream) =
2007 endpoints::create_proxy_and_stream::<wlan_deprecated::DeprecatedConfiguratorMarker>();
2008 let mac = MacAddress::from_bytes(&[0, 1, 2, 3, 4, 5]).unwrap();
2009 let suggest_fut = handle_suggest_ap_mac(configurator_proxy, mac);
2010 let mut suggest_fut = pin!(suggest_fut);
2011
2012 assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Pending);
2013
2014 assert_matches!(
2015 exec.run_until_stalled(&mut configurator_stream.next()),
2016 Poll::Ready(Some(Ok(wlan_deprecated::DeprecatedConfiguratorRequest::SuggestAccessPointMacAddress {
2017 mac: net::MacAddress { octets: [0, 1, 2, 3, 4, 5] }, responder
2018 }))) => {
2019 assert!(responder.send(Err(wlan_deprecated::SuggestMacAddressError::InvalidArguments)).is_ok());
2020 }
2021 );
2022
2023 assert_matches!(exec.run_until_stalled(&mut suggest_fut), Poll::Ready(Err(_)));
2024 }
2025
2026 #[fuchsia_async::run_singlethreaded(test)]
2027 async fn test_proxy_command_succeeds() {
2028 match run_proxy_command(Box::pin(async { Ok(zx_status::Status::OK) })).await {
2029 Ok(status) => {
2030 assert_eq!(status, zx_status::Status::OK)
2031 }
2032 Err(e) => panic!("Test unexpectedly failed with {}", e),
2033 }
2034 }
2035
2036 #[fuchsia_async::run_singlethreaded(test)]
2037 async fn test_proxy_command_already_bound() {
2038 let result: Result<(), Error> = run_proxy_command(Box::pin(async {
2039 Err(fidl::Error::ClientChannelClosed {
2040 status: zx_status::Status::ALREADY_BOUND,
2041 protocol_name: "test",
2042 epitaph: Some(zx_status::Status::ALREADY_BOUND.into_raw() as u32),
2043 })
2044 }))
2045 .await;
2046 match result {
2047 Ok(status) => panic!("Test unexpectedly succeeded with {:?}", status),
2048 Err(e) => {
2049 assert!(e.to_string().contains("Failed to obtain a WLAN policy controller"));
2050 }
2051 }
2052 }
2053
2054 #[fuchsia_async::run_singlethreaded(test)]
2055 async fn test_proxy_command_generic_failure() {
2056 let result: Result<(), Error> =
2057 run_proxy_command(Box::pin(async { Err(fidl::Error::Invalid) })).await;
2058 match result {
2059 Ok(status) => panic!("Test unexpectedly succeeded with {:?}", status),
2060 Err(e) => {
2061 assert!(!e.to_string().contains("Failed to obtain a WLAN policy controller"));
2062 }
2063 }
2064 }
2065}