wlancfg_lib/client/
mod.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Serves Client policy services.
6use crate::client::types as client_types;
7use crate::config_management::{
8    self, Credential, NetworkConfigError, NetworkIdentifier, SaveError, SavedNetworksManagerApi,
9};
10use crate::mode_management::iface_manager_api::{ConnectAttemptRequest, IfaceManagerApi};
11use crate::telemetry::{TelemetryEvent, TelemetrySender};
12use crate::util::listener;
13use fidl::epitaph::ChannelEpitaphExt;
14use fidl_fuchsia_wlan_policy as fidl_policy;
15use futures::lock::{Mutex, MutexGuard};
16use futures::prelude::*;
17use futures::select;
18use futures::stream::FuturesUnordered;
19use log::{error, info, warn};
20use std::sync::Arc;
21
22pub mod connection_selection;
23pub mod roaming;
24pub mod scan;
25pub mod state_machine;
26pub mod types;
27
28/// Max number of network configs that we will send at once through the network config iterator
29/// in get_saved_networks. This depends on the maximum size of a FIDL NetworkConfig, so it may
30/// need to change if a FIDL NetworkConfig or FIDL Credential changes.
31const MAX_CONFIGS_PER_RESPONSE: usize = 100;
32
33// This number was chosen arbitrarily.
34const MAX_CONCURRENT_LISTENERS: usize = 1000;
35
36type ClientRequests = fidl::endpoints::ServerEnd<fidl_policy::ClientControllerMarker>;
37type SavedNetworksPtr = Arc<dyn SavedNetworksManagerApi>;
38
39/// Serves the ClientProvider protocol.
40/// Only one ClientController can be active. Additional requests to register ClientControllers
41/// will result in their channel being immediately closed.
42pub async fn serve_provider_requests(
43    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
44    update_sender: listener::ClientListenerMessageSender,
45    saved_networks: SavedNetworksPtr,
46    scan_requester: Arc<dyn scan::ScanRequestApi>,
47    client_provider_lock: Arc<Mutex<()>>,
48    mut requests: fidl_policy::ClientProviderRequestStream,
49    telemetry_sender: TelemetrySender,
50) {
51    let mut controller_reqs = FuturesUnordered::new();
52
53    loop {
54        select! {
55            // Progress controller requests.
56            _ = controller_reqs.select_next_some() => (),
57            // Process provider requests.
58            req = requests.select_next_some() => if let Ok(req) = req {
59                // If another component already has a client provider, rejest the request.
60                if let Some(client_provider_guard) = client_provider_lock.try_lock() {
61                    let fut = handle_provider_request(
62                        Arc::clone(&iface_manager),
63                        update_sender.clone(),
64                        saved_networks.clone(),
65                        scan_requester.clone(),
66                        client_provider_guard,
67                        req,
68                        telemetry_sender.clone(),
69                    );
70                    controller_reqs.push(fut);
71                } else if let Err(e) = reject_provider_request(req) {
72                    error!("error sending rejection epitaph: {:?}", e);
73                }
74            },
75            complete => break,
76        }
77    }
78}
79
80/// Serves the ClientListener protocol.
81pub async fn serve_listener_requests(
82    update_sender: listener::ClientListenerMessageSender,
83    requests: fidl_policy::ClientListenerRequestStream,
84) {
85    let serve_fut = requests
86        .try_for_each_concurrent(MAX_CONCURRENT_LISTENERS, |req| {
87            handle_listener_request(update_sender.clone(), req)
88        })
89        .unwrap_or_else(|e| error!("error serving Client Listener API: {}", e));
90    serve_fut.await;
91}
92
93/// Handle inbound requests to acquire a new ClientController.
94async fn handle_provider_request(
95    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
96    update_sender: listener::ClientListenerMessageSender,
97    saved_networks: SavedNetworksPtr,
98    scan_requester: Arc<dyn scan::ScanRequestApi>,
99    client_provider_guard: MutexGuard<'_, ()>,
100    req: fidl_policy::ClientProviderRequest,
101    telemetry_sender: TelemetrySender,
102) -> Result<(), fidl::Error> {
103    match req {
104        fidl_policy::ClientProviderRequest::GetController { requests, updates, .. } => {
105            register_listener(update_sender, updates.into_proxy());
106            handle_client_requests(
107                iface_manager,
108                scan_requester,
109                saved_networks,
110                client_provider_guard,
111                requests,
112                telemetry_sender,
113            )
114            .await?;
115            Ok(())
116        }
117    }
118}
119
120/// Logs a message for an incoming ClientControllerRequest
121fn log_client_request(request: &fidl_policy::ClientControllerRequest) {
122    info!(
123        "Received policy client request {}",
124        match request {
125            fidl_policy::ClientControllerRequest::Connect { .. } => "Connect",
126            fidl_policy::ClientControllerRequest::StartClientConnections { .. } =>
127                "StartClientConnections",
128            fidl_policy::ClientControllerRequest::StopClientConnections { .. } =>
129                "StopClientConnections",
130            fidl_policy::ClientControllerRequest::ScanForNetworks { .. } => "ScanForNetworks",
131            fidl_policy::ClientControllerRequest::SaveNetwork { .. } => "SaveNetwork",
132            fidl_policy::ClientControllerRequest::RemoveNetwork { .. } => "RemoveNetwork",
133            fidl_policy::ClientControllerRequest::GetSavedNetworks { .. } => "GetSavedNetworks",
134        }
135    );
136}
137
138/// Handles all incoming requests from a ClientController.
139async fn handle_client_requests(
140    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
141    scan_requester: Arc<dyn scan::ScanRequestApi>,
142    saved_networks: SavedNetworksPtr,
143    client_provider_guard: MutexGuard<'_, ()>,
144    requests: ClientRequests,
145    telemetry_sender: TelemetrySender,
146) -> Result<(), fidl::Error> {
147    let mut request_stream = requests.into_stream();
148    while let Some(request) = request_stream.try_next().await? {
149        log_client_request(&request);
150        match request {
151            fidl_policy::ClientControllerRequest::Connect { id, responder, .. } => {
152                let response = handle_client_request_connect(
153                    Arc::clone(&iface_manager),
154                    saved_networks.clone(),
155                    &id,
156                )
157                .await;
158                responder.send(response)?
159            }
160            fidl_policy::ClientControllerRequest::StartClientConnections { responder } => {
161                telemetry_sender.send(TelemetryEvent::StartClientConnectionsRequest);
162                let response =
163                    handle_client_request_start_client_connections(iface_manager.clone()).await;
164                responder.send(response)?
165            }
166            fidl_policy::ClientControllerRequest::StopClientConnections { responder } => {
167                telemetry_sender.send(TelemetryEvent::StopClientConnectionsRequest);
168                let response =
169                    handle_client_request_stop_client_connections(iface_manager.clone()).await;
170                responder.send(response)?
171            }
172            fidl_policy::ClientControllerRequest::ScanForNetworks { iterator, .. } => {
173                let fut = handle_client_request_scan(
174                    scan_requester.clone(),
175                    saved_networks.clone(),
176                    telemetry_sender.clone(),
177                    iterator,
178                );
179                // The scan handler is infallible and should not block handling of further request.
180                // Detach the future here so we continue responding to other requests.
181                fuchsia_async::Task::local(fut).detach();
182            }
183            fidl_policy::ClientControllerRequest::SaveNetwork { config, responder } => {
184                // If there is an error saving the network, log it and convert to a FIDL value.
185                let response = handle_client_request_save_network(
186                    saved_networks.clone(),
187                    config,
188                    Arc::clone(&iface_manager),
189                )
190                .await
191                .map_err(|e| {
192                    error!("Failed to save network: {:?}", e);
193                    fidl_policy::NetworkConfigChangeError::from(e)
194                });
195                responder.send(response)?;
196            }
197            fidl_policy::ClientControllerRequest::RemoveNetwork { config, responder } => {
198                let err = handle_client_request_remove_network(
199                    saved_networks.clone(),
200                    config,
201                    iface_manager.clone(),
202                )
203                .map_err(|_| SaveError::GeneralError)
204                .await;
205
206                responder.send(err)?;
207            }
208            fidl_policy::ClientControllerRequest::GetSavedNetworks { iterator, .. } => {
209                handle_client_request_get_networks(saved_networks.clone(), iterator).await?;
210            }
211        }
212    }
213    drop(client_provider_guard);
214    Ok(())
215}
216
217/// Attempts to issue a new connect request to the currently active Client.
218/// The network's configuration must have been stored before issuing a connect request.
219async fn handle_client_request_connect(
220    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
221    saved_networks: SavedNetworksPtr,
222    network: &fidl_policy::NetworkIdentifier,
223) -> fidl_policy::RequestStatus {
224    let network_config = match saved_networks
225        .lookup(&NetworkIdentifier::new(
226            client_types::Ssid::from_bytes_unchecked(network.ssid.clone()),
227            network.type_.into(),
228        ))
229        .await
230        .pop()
231    {
232        Some(config) => config,
233        None => {
234            error!("Requested network not found in saved networks");
235            return fidl_policy::RequestStatus::RejectedNotSupported;
236        }
237    };
238
239    let network_id = fidl_policy::NetworkIdentifier {
240        ssid: network_config.ssid.into(),
241        type_: fidl_policy::SecurityType::from(network_config.security_type),
242    };
243    let connect_req = ConnectAttemptRequest::new(
244        network_id.into(),
245        network_config.credential,
246        client_types::ConnectReason::FidlConnectRequest,
247    );
248
249    let mut iface_manager = iface_manager.lock().await;
250    match iface_manager.connect(connect_req).await {
251        Ok(_) => fidl_policy::RequestStatus::Acknowledged,
252        Err(e) => {
253            error!("failed to connect: {:?}", e);
254            fidl_policy::RequestStatus::RejectedIncompatibleMode
255        }
256    }
257}
258
259async fn handle_client_request_scan(
260    scan_requester: Arc<dyn scan::ScanRequestApi>,
261    saved_networks: SavedNetworksPtr,
262    telemetry_sender: TelemetrySender,
263    output_iterator: fidl::endpoints::ServerEnd<fidl_fuchsia_wlan_policy::ScanResultIteratorMarker>,
264) {
265    let get_scan_results = async {
266        let passive_scan_results =
267            scan_requester.perform_scan(scan::ScanReason::ClientRequest, vec![], vec![]).await?;
268
269        let requested_active_scan_ssids: Vec<types::Ssid> =
270            config_management::select_high_probability_hidden_networks(
271                saved_networks.get_networks().await,
272            )
273            .drain(..)
274            .map(|id| id.ssid)
275            .collect();
276
277        info!(
278            "Completed passive scan for API request, {} likely-hidden networks to scan for.",
279            requested_active_scan_ssids.len()
280        );
281        telemetry_sender.send(TelemetryEvent::ActiveScanRequestedViaApi {
282            num_ssids_requested: requested_active_scan_ssids.len(),
283        });
284
285        if requested_active_scan_ssids.is_empty() {
286            Ok(passive_scan_results)
287        } else {
288            scan_requester
289                .perform_scan(scan::ScanReason::ClientRequest, requested_active_scan_ssids, vec![])
290                .await
291                .map(|mut scan_results| {
292                    scan_results.extend(passive_scan_results);
293                    scan_results
294                })
295        }
296    };
297
298    match get_scan_results.await {
299        Ok(results) => {
300            // Note: for now, we must always present WPA2/3 networks as WPA2 over our external
301            // interfaces (i.e. to FIDL consumers of scan results). See b/182209070 for more
302            // information.
303            // TODO(b/182569380): use actual wpa3 support in this conversion rather than 'false'
304            let fidl_results = scan::scan_result_to_policy_scan_result(&results, false);
305            if let Err(e) = scan::send_scan_results_over_fidl(output_iterator, &fidl_results).await
306            {
307                warn!("Failed to send scan results to requester: {:?}", e);
308            }
309        }
310        Err(e) => {
311            if let Err(e) = scan::send_scan_error_over_fidl(output_iterator, e).await {
312                warn!("Failed to send scan error to requester: {:?}", e);
313            }
314        }
315    }
316}
317
318/// This function handles requests to save a network by saving the network and sending back to the
319/// controller whether or not we successfully saved the network. There could be a FIDL error in
320/// sending the response.
321async fn handle_client_request_save_network(
322    saved_networks: SavedNetworksPtr,
323    network_config: fidl_policy::NetworkConfig,
324    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
325) -> Result<(), NetworkConfigError> {
326    // The FIDL network config fields are defined as Options, and we consider it an error if either
327    // field is missing (ie None) here.
328    let net_id: client_types::NetworkIdentifier =
329        network_config.id.ok_or(NetworkConfigError::ConfigMissingId)?.into();
330    let credential = Credential::try_from(
331        network_config.credential.ok_or(NetworkConfigError::ConfigMissingCredential)?,
332    )?;
333    let evicted_config = saved_networks.store(net_id.clone(), credential.clone()).await?;
334
335    // If a config was removed, disconnect from that network.
336    let mut iface_manager = iface_manager.lock().await;
337    if let Some(config) = evicted_config {
338        let net_id = client_types::NetworkIdentifier {
339            ssid: config.ssid,
340            security_type: config.security_type,
341        };
342        match iface_manager
343            .disconnect(net_id, client_types::DisconnectReason::NetworkConfigUpdated)
344            .await
345        {
346            Ok(()) => {}
347            Err(e) => error!("failed to disconnect from network: {}", e),
348        }
349    }
350
351    // Attempt to connect to the new network if there is an idle client interface.
352    let connect_req = ConnectAttemptRequest::new(
353        net_id,
354        credential,
355        client_types::ConnectReason::NewSavedNetworkAutoconnect,
356    );
357    match iface_manager.has_idle_client().await {
358        Ok(true) => {
359            info!("Idle interface available, will attempt connection to new saved network");
360            let _ = iface_manager.connect(connect_req).await;
361        }
362        Ok(false) => {}
363        Err(e) => {
364            error!("Unable to query idle client state while saving network: {:?}", e);
365        }
366    }
367
368    Ok(())
369}
370
371/// Will remove the specified network and respond to the remove network request with a network
372/// config change error if an error occurs while trying to remove the network.
373async fn handle_client_request_remove_network(
374    saved_networks: SavedNetworksPtr,
375    network_config: fidl_policy::NetworkConfig,
376    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
377) -> Result<(), NetworkConfigError> {
378    // The FIDL network config fields are defined as Options, and we consider it an error if either
379    // field is missing (ie None) here.
380    let net_id =
381        NetworkIdentifier::from(network_config.id.ok_or(NetworkConfigError::ConfigMissingId)?);
382    let credential = Credential::try_from(
383        network_config.credential.ok_or(NetworkConfigError::ConfigMissingCredential)?,
384    )?;
385    if saved_networks.remove(net_id.clone(), credential.clone()).await? {
386        match iface_manager
387            .lock()
388            .await
389            .disconnect(net_id, client_types::DisconnectReason::NetworkUnsaved)
390            .await
391        {
392            Ok(()) => {}
393            Err(e) => error!("failed to disconnect from network: {}", e),
394        }
395    }
396    Ok(())
397}
398
399async fn handle_client_request_get_networks(
400    saved_networks: SavedNetworksPtr,
401    iterator: fidl::endpoints::ServerEnd<fidl_policy::NetworkConfigIteratorMarker>,
402) -> Result<(), fidl::Error> {
403    // make sufficiently small batches of networks to send and convert configs to FIDL values
404    let network_configs = saved_networks.get_networks().await;
405    let chunks = network_configs.chunks(MAX_CONFIGS_PER_RESPONSE);
406    let fidl_chunks = chunks.into_iter().map(|chunk| {
407        chunk
408            .iter()
409            .map(fidl_policy::NetworkConfig::from)
410            .collect::<Vec<fidl_policy::NetworkConfig>>()
411    });
412    let mut stream = iterator.into_stream();
413    for chunk in fidl_chunks {
414        send_next_chunk(&mut stream, chunk).await?;
415    }
416    send_next_chunk(&mut stream, vec![]).await
417}
418
419/// Send a chunk of saved networks to the specified FIDL iterator
420async fn send_next_chunk(
421    stream: &mut fidl_policy::NetworkConfigIteratorRequestStream,
422    chunk: Vec<fidl_policy::NetworkConfig>,
423) -> Result<(), fidl::Error> {
424    if let Some(req) = stream.try_next().await? {
425        let fidl_policy::NetworkConfigIteratorRequest::GetNext { responder } = req;
426        responder.send(&chunk)
427    } else {
428        // This will happen if the iterator request stream was closed and we expected to send
429        // another response.
430        // TODO(https://fxbug.dev/42121602) Test this error path
431        info!("Info: peer closed channel for network config results unexpectedly");
432        Ok(())
433    }
434}
435
436/// Handle inbound requests to register an additional ClientStateUpdates listener.
437async fn handle_listener_request(
438    update_sender: listener::ClientListenerMessageSender,
439    req: fidl_policy::ClientListenerRequest,
440) -> Result<(), fidl::Error> {
441    match req {
442        fidl_policy::ClientListenerRequest::GetListener { updates, .. } => {
443            register_listener(update_sender, updates.into_proxy());
444            Ok(())
445        }
446    }
447}
448
449/// Registers a new update listener.
450/// The client's current state will be send to the newly added listener immediately.
451fn register_listener(
452    update_sender: listener::ClientListenerMessageSender,
453    listener: fidl_policy::ClientStateUpdatesProxy,
454) {
455    let _ignored = update_sender.unbounded_send(listener::Message::NewListener(listener));
456}
457
458/// Rejects a ClientProvider request by sending a corresponding Epitaph via the |requests| and
459/// |updates| channels.
460fn reject_provider_request(req: fidl_policy::ClientProviderRequest) -> Result<(), fidl::Error> {
461    match req {
462        fidl_policy::ClientProviderRequest::GetController { requests, updates, .. } => {
463            info!("Rejecting new client controller request because a controller is in use");
464            requests.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
465            updates.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
466            Ok(())
467        }
468    }
469}
470
471/// Allows client operations to be performed.
472async fn handle_client_request_start_client_connections(
473    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
474) -> fidl_policy::RequestStatus {
475    let mut iface_manager = iface_manager.lock().await;
476    if let Err(e) = iface_manager.start_client_connections().await {
477        warn!("encountered an error while starting client connections: {:?}", e);
478    }
479    fidl_policy::RequestStatus::Acknowledged
480}
481
482/// Stops all active client connections and disallows future client operations.
483async fn handle_client_request_stop_client_connections(
484    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
485) -> fidl_policy::RequestStatus {
486    let mut iface_manager = iface_manager.lock().await;
487    if let Err(e) = iface_manager
488        .stop_client_connections(client_types::DisconnectReason::FidlStopClientConnectionsRequest)
489        .await
490    {
491        warn!("encountered an error while stopping client connections: {:?}", e);
492    }
493    fidl_policy::RequestStatus::Acknowledged
494}
495
496#[cfg(test)]
497mod tests {
498    use super::*;
499    use crate::access_point::state_machine as ap_fsm;
500    use crate::config_management::{NetworkConfig, SecurityType, WPA_PSK_BYTE_LEN};
501    use crate::mode_management::iface_manager_api::SmeForScan;
502    use crate::util::testing::fakes::{FakeSavedNetworksManager, FakeScanRequester};
503    use crate::util::testing::{
504        generate_random_fidl_network_config, generate_random_fidl_network_config_with_ssid,
505    };
506    use anyhow::{Error, format_err};
507    use assert_matches::assert_matches;
508    use async_trait::async_trait;
509    use fidl::endpoints::{Proxy, create_proxy, create_request_stream};
510    use fuchsia_async as fasync;
511    use futures::channel::{mpsc, oneshot};
512    use futures::task::Poll;
513    use std::pin::pin;
514    use test_case::test_case;
515
516    /// Only used to tell us what disconnect request was given to the IfaceManager so that we
517    /// don't need to worry about the implementation logic in the FakeIfaceManager.
518    #[derive(Debug)]
519    enum IfaceManagerRequest {
520        Disconnect(client_types::NetworkIdentifier, client_types::DisconnectReason),
521    }
522
523    struct FakeIfaceManager {
524        pub sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
525        pub disconnected_ifaces: Vec<u16>,
526        command_sender: mpsc::Sender<IfaceManagerRequest>,
527        start_client_connections_succeeds: bool,
528        stop_client_connections_succeeds: bool,
529    }
530
531    impl FakeIfaceManager {
532        pub fn new(
533            proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
534            command_sender: mpsc::Sender<IfaceManagerRequest>,
535        ) -> Self {
536            FakeIfaceManager {
537                sme_proxy: proxy,
538                disconnected_ifaces: Vec::new(),
539                command_sender,
540                start_client_connections_succeeds: true,
541                stop_client_connections_succeeds: true,
542            }
543        }
544    }
545
546    #[async_trait(?Send)]
547    impl IfaceManagerApi for FakeIfaceManager {
548        async fn disconnect(
549            &mut self,
550            network_id: client_types::NetworkIdentifier,
551            reason: client_types::DisconnectReason,
552        ) -> Result<(), Error> {
553            self.command_sender
554                .try_send(IfaceManagerRequest::Disconnect(network_id, reason))
555                .map_err(|e| {
556                    error!(
557                        "Failed to send disconnect: commands_sender's receiver may have
558                        been dropped. FakeIfaceManager should be created manually with a sender
559                        assigned: {:?}",
560                        e
561                    );
562                    format_err!("failed to send disconnect: {:?}", e)
563                })
564        }
565
566        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
567            let _ = self.disconnected_ifaces.pop();
568            Ok(())
569        }
570
571        async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error> {
572            self.disconnected_ifaces.push(iface_id);
573            Ok(())
574        }
575
576        async fn has_idle_client(&mut self) -> Result<bool, Error> {
577            Ok(!self.disconnected_ifaces.is_empty())
578        }
579
580        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
581            unimplemented!()
582        }
583
584        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
585            unimplemented!()
586        }
587
588        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
589            let (defect_sender, _) = mpsc::channel(100);
590            Ok(SmeForScan::new(self.sme_proxy.clone(), 0, defect_sender))
591        }
592
593        async fn stop_client_connections(
594            &mut self,
595            _reason: client_types::DisconnectReason,
596        ) -> Result<(), Error> {
597            if self.stop_client_connections_succeeds {
598                Ok(())
599            } else {
600                Err(format_err!("stop client connections failed"))
601            }
602        }
603
604        async fn start_client_connections(&mut self) -> Result<(), Error> {
605            if self.start_client_connections_succeeds {
606                Ok(())
607            } else {
608                Err(format_err!("start client connections failed"))
609            }
610        }
611
612        async fn start_ap(
613            &mut self,
614            _config: ap_fsm::ApConfig,
615        ) -> Result<oneshot::Receiver<()>, Error> {
616            unimplemented!()
617        }
618
619        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
620            unimplemented!()
621        }
622
623        async fn stop_all_aps(&mut self) -> Result<(), Error> {
624            unimplemented!()
625        }
626
627        async fn set_country(
628            &mut self,
629            _country_code: Option<types::CountryCode>,
630        ) -> Result<(), Error> {
631            unimplemented!()
632        }
633    }
634
635    /// Requests a new ClientController from the given ClientProvider.
636    fn request_controller(
637        provider: &fidl_policy::ClientProviderProxy,
638    ) -> (fidl_policy::ClientControllerProxy, fidl_policy::ClientStateUpdatesRequestStream) {
639        let (controller, requests) = create_proxy::<fidl_policy::ClientControllerMarker>();
640        let (update_sink, update_stream) =
641            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
642        provider.get_controller(requests, update_sink).expect("error getting controller");
643        (controller, update_stream)
644    }
645
646    struct TestValues {
647        saved_networks: SavedNetworksPtr,
648        net_id_open: fidl_policy::NetworkIdentifier,
649        net_id_wpa2_w_password: fidl_policy::NetworkIdentifier,
650        net_id_wpa2_w_psk: fidl_policy::NetworkIdentifier,
651        provider: fidl_policy::ClientProviderProxy,
652        requests: fidl_policy::ClientProviderRequestStream,
653        iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
654        iface_mgr_req_recvr: mpsc::Receiver<IfaceManagerRequest>,
655        scan_requester: Arc<FakeScanRequester>,
656        update_sender: mpsc::UnboundedSender<listener::ClientListenerMessage>,
657        listener_updates: mpsc::UnboundedReceiver<listener::ClientListenerMessage>,
658        client_provider_lock: Arc<Mutex<()>>,
659        telemetry_sender: TelemetrySender,
660        telemetry_receiver: mpsc::Receiver<TelemetryEvent>,
661    }
662
663    // setup channels and proxies needed for the tests to use use the Client Provider and
664    // Client Controller APIs in tests. The stash id should be the test name so that each
665    // test will have a unique persistent store behind it.
666    fn test_setup() -> TestValues {
667        let net_id_open = fidl_policy::NetworkIdentifier {
668            ssid: "foobar".to_string().into_bytes(),
669            type_: fidl_policy::SecurityType::None,
670        };
671        let net_id_wpa2_w_password = fidl_policy::NetworkIdentifier {
672            ssid: b"foobar-wpa2".to_vec(),
673            type_: fidl_policy::SecurityType::Wpa2,
674        };
675        let net_id_wpa2_w_psk = fidl_policy::NetworkIdentifier {
676            ssid: b"foobar-psk".to_vec(),
677            type_: fidl_policy::SecurityType::Wpa2,
678        };
679
680        let presaved_default_configs = vec![
681            fidl_policy::NetworkConfig {
682                id: Some(net_id_open.clone()),
683                credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
684                ..Default::default()
685            },
686            fidl_policy::NetworkConfig {
687                id: Some(net_id_wpa2_w_password.clone()),
688                credential: Some(fidl_policy::Credential::Password(b"foobar-password".to_vec())),
689                ..Default::default()
690            },
691            fidl_policy::NetworkConfig {
692                id: Some(net_id_wpa2_w_psk.clone()),
693                credential: Some(fidl_policy::Credential::Psk([64; WPA_PSK_BYTE_LEN].to_vec())),
694                ..Default::default()
695            },
696        ];
697        let saved_networks =
698            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(presaved_default_configs));
699        let (telemetry_sender, telemetry_receiver) = mpsc::channel::<TelemetryEvent>(100);
700        let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>();
701        let requests = requests.into_stream();
702
703        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
704        let (req_sender, iface_mgr_req_recvr) = mpsc::channel(1);
705        let iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
706        let iface_manager = Arc::new(Mutex::new(iface_manager));
707        let scan_requester = Arc::new(FakeScanRequester::new());
708
709        let (update_sender, listener_updates) = mpsc::unbounded();
710
711        TestValues {
712            saved_networks,
713            net_id_open,
714            net_id_wpa2_w_password,
715            net_id_wpa2_w_psk,
716            provider,
717            requests,
718            iface_manager,
719            iface_mgr_req_recvr,
720            scan_requester,
721            update_sender,
722            listener_updates,
723            client_provider_lock: Arc::new(Mutex::new(())),
724            telemetry_sender: TelemetrySender::new(telemetry_sender),
725            telemetry_receiver,
726        }
727    }
728
729    #[fuchsia::test]
730    fn connect_request_unknown_network() {
731        let ssid = client_types::Ssid::try_from("foobar-unknown").unwrap();
732        let mut exec = fasync::TestExecutor::new();
733        let test_values = test_setup();
734        let serve_fut = serve_provider_requests(
735            test_values.iface_manager,
736            test_values.update_sender,
737            Arc::clone(&test_values.saved_networks),
738            test_values.scan_requester,
739            test_values.client_provider_lock,
740            test_values.requests,
741            test_values.telemetry_sender,
742        );
743        let mut serve_fut = pin!(serve_fut);
744
745        // No request has been sent yet. Future should be idle.
746        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
747
748        // Request a new controller.
749        let (controller, _) = request_controller(&test_values.provider);
750        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
751
752        // Issue connect request.
753        let connect_fut = controller.connect(&fidl_policy::NetworkIdentifier {
754            ssid: ssid.to_vec(),
755            type_: fidl_policy::SecurityType::None,
756        });
757        let mut connect_fut = pin!(connect_fut);
758
759        // Process connect request and verify connect response.
760        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
761
762        assert_matches!(
763            exec.run_until_stalled(&mut connect_fut),
764            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedNotSupported))
765        );
766
767        // Unknown network should not have been saved by saved networks manager
768        // since we did not successfully connect.
769        let id = NetworkIdentifier::new(ssid, SecurityType::None);
770        let lookup_fut = test_values.saved_networks.lookup(&id);
771        assert!(exec.run_singlethreaded(lookup_fut).is_empty());
772    }
773
774    #[fuchsia::test]
775    fn connect_request_open_network() {
776        let mut exec = fasync::TestExecutor::new();
777
778        let test_values = test_setup();
779        let serve_fut = serve_provider_requests(
780            test_values.iface_manager,
781            test_values.update_sender,
782            Arc::clone(&test_values.saved_networks),
783            test_values.scan_requester,
784            test_values.client_provider_lock,
785            test_values.requests,
786            test_values.telemetry_sender,
787        );
788        let mut serve_fut = pin!(serve_fut);
789
790        // No request has been sent yet. Future should be idle.
791        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
792
793        // Request a new controller.
794        let (controller, _update_stream) = request_controller(&test_values.provider);
795        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
796
797        // Issue connect request.
798        let connect_fut = controller.connect(&test_values.net_id_open);
799        let mut connect_fut = pin!(connect_fut);
800
801        // Process connect request and verify connect response.
802        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
803
804        // Verify that the connect call is acknowledged.
805        assert_matches!(
806            exec.run_until_stalled(&mut connect_fut),
807            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
808        );
809    }
810
811    #[fuchsia::test]
812    fn connect_request_protected_network() {
813        let mut exec = fasync::TestExecutor::new();
814
815        let test_values = test_setup();
816        let serve_fut = serve_provider_requests(
817            test_values.iface_manager,
818            test_values.update_sender,
819            Arc::clone(&test_values.saved_networks),
820            test_values.scan_requester,
821            test_values.client_provider_lock,
822            test_values.requests,
823            test_values.telemetry_sender,
824        );
825        let mut serve_fut = pin!(serve_fut);
826
827        // No request has been sent yet. Future should be idle.
828        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
829
830        // Request a new controller.
831        let (controller, _update_stream) = request_controller(&test_values.provider);
832        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
833
834        // Issue connect request.
835        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
836        let mut connect_fut = pin!(connect_fut);
837
838        // Process connect request and verify connect response.
839        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
840
841        // Verify that the connect call is acknowledged.
842        assert_matches!(
843            exec.run_until_stalled(&mut connect_fut),
844            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
845        );
846    }
847
848    #[fuchsia::test]
849    fn connect_request_protected_psk_network() {
850        let mut exec = fasync::TestExecutor::new();
851
852        let test_values = test_setup();
853        let serve_fut = serve_provider_requests(
854            test_values.iface_manager,
855            test_values.update_sender,
856            Arc::clone(&test_values.saved_networks),
857            test_values.scan_requester,
858            test_values.client_provider_lock,
859            test_values.requests,
860            test_values.telemetry_sender,
861        );
862        let mut serve_fut = pin!(serve_fut);
863
864        // No request has been sent yet. Future should be idle.
865        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
866
867        // Request a new controller.
868        let (controller, _update_stream) = request_controller(&test_values.provider);
869        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
870
871        // Issue connect request.
872        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_psk);
873        let mut connect_fut = pin!(connect_fut);
874
875        // Process connect request and verify connect response.
876        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
877
878        // Verify that the connect call is acknowledged.
879        assert_matches!(
880            exec.run_until_stalled(&mut connect_fut),
881            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
882        );
883    }
884
885    #[fuchsia::test]
886    fn start_and_stop_client_connections() {
887        let mut exec = fasync::TestExecutor::new();
888        let mut test_values = test_setup();
889        let serve_fut = serve_provider_requests(
890            test_values.iface_manager,
891            test_values.update_sender,
892            test_values.saved_networks,
893            test_values.scan_requester,
894            test_values.client_provider_lock,
895            test_values.requests,
896            test_values.telemetry_sender,
897        );
898        let mut serve_fut = pin!(serve_fut);
899
900        // No request has been sent yet. Future should now be waiting for request.
901        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
902
903        // Request a new controller.
904        let (controller, _update_stream) = request_controller(&test_values.provider);
905        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
906
907        // Issue request to start client connections.
908        let start_fut = controller.start_client_connections();
909        let mut start_fut = pin!(start_fut);
910
911        // Request should be acknowledged.
912        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
913        assert_matches!(
914            exec.run_until_stalled(&mut start_fut),
915            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
916        );
917
918        // A message should be sent to telemetry.
919        assert_matches!(test_values.telemetry_receiver.try_next(), Ok(Some(event)) => {
920            assert_matches!(event, TelemetryEvent::StartClientConnectionsRequest);
921        });
922
923        // Perform a connect operation.
924        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
925        let mut connect_fut = pin!(connect_fut);
926
927        // Process connect request and verify connect response.
928        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
929
930        // Verify that the connect call is acknowledged.
931        assert_matches!(
932            exec.run_until_stalled(&mut connect_fut),
933            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
934        );
935
936        // The client state machine will immediately query for status.
937        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
938
939        // Issue request to stop client connections.
940        let stop_fut = controller.stop_client_connections();
941        let mut stop_fut = pin!(stop_fut);
942
943        // Run the serve future until it stalls and expect the client to disconnect
944        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
945
946        // A message should be sent to telemetry.
947        assert_matches!(test_values.telemetry_receiver.try_next(), Ok(Some(event)) => {
948            assert_matches!(event, TelemetryEvent::StopClientConnectionsRequest);
949        });
950
951        // Request should be acknowledged.
952        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
953        assert_matches!(
954            exec.run_until_stalled(&mut stop_fut),
955            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
956        );
957    }
958
959    /// End-to-end test of the scan function, verifying that an incoming
960    /// FIDL scan request results in a scan in the SME, and that the results
961    /// make it back to the requester.
962    #[fuchsia::test]
963    fn scan_end_to_end() {
964        let mut exec = fasync::TestExecutor::new();
965        let test_values = test_setup();
966        let serve_fut = serve_provider_requests(
967            test_values.iface_manager,
968            test_values.update_sender,
969            test_values.saved_networks,
970            test_values.scan_requester.clone(),
971            test_values.client_provider_lock,
972            test_values.requests,
973            test_values.telemetry_sender,
974        );
975        let mut serve_fut = pin!(serve_fut);
976
977        // No request has been sent yet. Future should be idle.
978        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
979
980        // Request a new controller.
981        let (controller, _update_stream) = request_controller(&test_values.provider);
982        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
983
984        // Issue a scan request.
985        let (_iter, server) = fidl::endpoints::create_proxy();
986        controller.scan_for_networks(server).expect("Failed to call scan for networks");
987
988        // Currently the FakeScanRequester will panic if a scan is requested and no results
989        // are queued, so add something.
990        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
991        // A second scan request for all the likely-hidden networks
992        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
993
994        // Process scan request and verify scan response.
995        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
996
997        // Check that a scan request was sent to the scan module, including an active scan for the
998        // potentially-hidden networks.
999        let expected_active_ssids = [
1000            test_values.net_id_wpa2_w_password,
1001            test_values.net_id_wpa2_w_psk,
1002            test_values.net_id_open,
1003        ]
1004        .iter()
1005        .map(|id| types::Ssid::from_bytes_unchecked(id.ssid.clone()))
1006        .collect();
1007        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1008            scan::ScanReason::ClientRequest,
1009            vec![],
1010            vec![],
1011        )));
1012        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1013            scan::ScanReason::ClientRequest,
1014            expected_active_ssids,
1015            vec![],
1016        )));
1017    }
1018
1019    #[fuchsia::test]
1020    fn save_network() {
1021        let mut exec = fasync::TestExecutor::new();
1022        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1023
1024        let mut test_values = test_setup();
1025        let serve_fut = serve_provider_requests(
1026            test_values.iface_manager,
1027            test_values.update_sender,
1028            saved_networks.clone(),
1029            test_values.scan_requester,
1030            test_values.client_provider_lock,
1031            test_values.requests,
1032            test_values.telemetry_sender,
1033        );
1034        let mut serve_fut = pin!(serve_fut);
1035
1036        // No request has been sent yet. Future should be idle.
1037        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1038
1039        // Request a new controller.
1040        let (controller, _update_stream) = request_controller(&test_values.provider);
1041        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1042        assert_matches!(
1043            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1044            Poll::Ready(_)
1045        );
1046
1047        // Save some network
1048        let network_id = fidl_policy::NetworkIdentifier {
1049            ssid: b"foo".to_vec(),
1050            type_: fidl_policy::SecurityType::None,
1051        };
1052        let network_config = fidl_policy::NetworkConfig {
1053            id: Some(network_id.clone()),
1054            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1055            ..Default::default()
1056        };
1057        let mut save_fut = controller.save_network(&network_config);
1058
1059        // Run server_provider forward so that it will process the save network request
1060        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1061        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1062
1063        // Check that the the response says we succeeded.
1064        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1065
1066        // Check that the value was actually saved in the saved networks manager.
1067        let target_id = NetworkIdentifier::from(network_id);
1068        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false)
1069            .expect("Failed to create network config");
1070        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![target_config]);
1071    }
1072
1073    #[fuchsia::test]
1074    fn save_network_with_disconnected_iface() {
1075        let mut exec = fasync::TestExecutor::new();
1076        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1077
1078        let mut test_values = test_setup();
1079        let serve_fut = serve_provider_requests(
1080            test_values.iface_manager.clone(),
1081            test_values.update_sender,
1082            saved_networks.clone(),
1083            test_values.scan_requester,
1084            test_values.client_provider_lock,
1085            test_values.requests,
1086            test_values.telemetry_sender,
1087        );
1088        let mut serve_fut = pin!(serve_fut);
1089
1090        // Setup the IfaceManager so that it has a disconnected iface.
1091        {
1092            let iface_manager = test_values.iface_manager.clone();
1093            let iface_manager_fut = iface_manager.lock();
1094            let mut iface_manager_fut = pin!(iface_manager_fut);
1095            let mut iface_manager = match exec.run_until_stalled(&mut iface_manager_fut) {
1096                Poll::Ready(iface_manager) => iface_manager,
1097                Poll::Pending => panic!("expected to acquire iface_manager lock"),
1098            };
1099            let record_idle_fut = iface_manager.record_idle_client(0);
1100            let mut record_idle_fut = pin!(record_idle_fut);
1101            assert_matches!(exec.run_until_stalled(&mut record_idle_fut), Poll::Ready(Ok(())));
1102        }
1103
1104        // No request has been sent yet. Future should be idle.
1105        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1106
1107        // Request a new controller.
1108        let (controller, _update_stream) = request_controller(&test_values.provider);
1109        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1110        assert_matches!(
1111            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1112            Poll::Ready(_)
1113        );
1114
1115        // Save some network
1116        let network_id = fidl_policy::NetworkIdentifier {
1117            ssid: b"foo".to_vec(),
1118            type_: fidl_policy::SecurityType::None,
1119        };
1120        let network_config = fidl_policy::NetworkConfig {
1121            id: Some(network_id.clone()),
1122            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1123            ..Default::default()
1124        };
1125        let mut save_fut = controller.save_network(&network_config);
1126
1127        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1128        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1129
1130        // Check that the the response says we succeeded.
1131        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1132            let save_result = result.expect("Failed to get save network response");
1133            assert_eq!(save_result, Ok(()));
1134        });
1135
1136        // Check that the value was actually saved in the saved networks manager.
1137        let target_id = NetworkIdentifier::from(network_id);
1138        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false)
1139            .expect("Failed to create network config");
1140        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![target_config]);
1141    }
1142
1143    #[fuchsia::test]
1144    fn save_network_overwrite_disconnects() {
1145        let mut exec = fasync::TestExecutor::new();
1146        let mut test_values = test_setup();
1147        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1148
1149        let serve_fut = serve_provider_requests(
1150            test_values.iface_manager,
1151            test_values.update_sender,
1152            saved_networks.clone(),
1153            test_values.scan_requester,
1154            test_values.client_provider_lock,
1155            test_values.requests,
1156            test_values.telemetry_sender,
1157        );
1158        let mut serve_fut = pin!(serve_fut);
1159
1160        // No request has been sent yet. Future should be idle.
1161        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1162
1163        // Request a new controller.
1164        let (controller, _update_stream) = request_controller(&test_values.provider);
1165        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1166        assert_matches!(
1167            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1168            Poll::Ready(_)
1169        );
1170
1171        // Save the network directly.
1172        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1173        let credential = Credential::Password(b"password".to_vec());
1174        let save_fut = saved_networks.store(network_id.clone(), credential.clone());
1175        let mut save_fut = pin!(save_fut);
1176        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(None)));
1177
1178        // Save a network with the same identifier but a different password
1179        let network_config = fidl_policy::NetworkConfig {
1180            id: Some(fidl_policy::NetworkIdentifier::from(network_id.clone())),
1181            credential: Some(fidl_policy::Credential::Password(b"other-password".to_vec())),
1182            ..Default::default()
1183        };
1184        let mut save_fut = controller.save_network(&network_config);
1185
1186        // Process the remove request on the server side and handle requests to stash on the way.
1187        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1188        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1189
1190        // Check that the iface manager was asked to disconnect from some network
1191        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1192            assert_eq!(net_id, network_id.clone());
1193            assert_eq!(reason, client_types::DisconnectReason::NetworkConfigUpdated);
1194        });
1195        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1196        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1197    }
1198
1199    #[fuchsia::test]
1200    fn save_bad_network_should_fail() {
1201        let mut exec = fasync::TestExecutor::new();
1202        let mut saved_networks = FakeSavedNetworksManager::new();
1203        saved_networks.fail_all_stores = true;
1204        let saved_networks = Arc::new(saved_networks);
1205
1206        let mut test_values = test_setup();
1207        let serve_fut = serve_provider_requests(
1208            test_values.iface_manager,
1209            test_values.update_sender,
1210            saved_networks.clone(),
1211            test_values.scan_requester,
1212            test_values.client_provider_lock,
1213            test_values.requests,
1214            test_values.telemetry_sender,
1215        );
1216        let mut serve_fut = pin!(serve_fut);
1217
1218        // No request has been sent yet. Future should be idle.
1219        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1220
1221        // Request a new controller.
1222        let (controller, _update_stream) = request_controller(&test_values.provider);
1223        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1224        assert_matches!(
1225            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1226            Poll::Ready(_)
1227        );
1228
1229        // Create a network config whose password is too short. FIDL network config does not
1230        // require valid fields unlike our crate define config. We should not be able to
1231        // successfully save this network through the API.
1232        let bad_network_id = fidl_policy::NetworkIdentifier {
1233            ssid: b"foo".to_vec(),
1234            type_: fidl_policy::SecurityType::Wpa2,
1235        };
1236        let network_config = fidl_policy::NetworkConfig {
1237            id: Some(bad_network_id.clone()),
1238            credential: Some(fidl_policy::Credential::Password(b"bar".to_vec())),
1239            ..Default::default()
1240        };
1241        // Attempt to save the config
1242        let mut save_fut = controller.save_network(&network_config);
1243
1244        // Run server_provider forward so that it will process the save network request
1245        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1246
1247        // Check that the the response says we failed to save the network.
1248        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1249            let error = result.expect("Failed to get save network response");
1250            assert_eq!(error, Err(fidl_policy::NetworkConfigChangeError::NetworkConfigWriteError));
1251        });
1252
1253        // Check that the value was was not saved in saved networks manager.
1254        let target_id = NetworkIdentifier::from(bad_network_id);
1255        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![]);
1256    }
1257
1258    #[fuchsia::test]
1259    fn test_remove_a_network() {
1260        let mut exec = fasync::TestExecutor::new();
1261        let mut test_values = test_setup();
1262
1263        let serve_fut = serve_provider_requests(
1264            test_values.iface_manager,
1265            test_values.update_sender,
1266            test_values.saved_networks.clone(),
1267            test_values.scan_requester,
1268            test_values.client_provider_lock,
1269            test_values.requests,
1270            test_values.telemetry_sender,
1271        );
1272        let mut serve_fut = pin!(serve_fut);
1273
1274        // No request has been sent yet. Future should be idle.
1275        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1276
1277        // Request a new controller.
1278        let (controller, _update_stream) = request_controller(&test_values.provider);
1279        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1280        assert_matches!(
1281            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1282            Poll::Ready(_)
1283        );
1284
1285        // Request to a network that is saved
1286        let network_config = fidl_policy::NetworkConfig {
1287            id: Some(test_values.net_id_open.clone()),
1288            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1289            ..Default::default()
1290        };
1291        let mut remove_fut = controller.remove_network(&network_config);
1292
1293        // Process the remove request on the server side and handle requests to stash on the way.
1294        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1295        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1296
1297        // Successfully removing a network should always request a disconnect from IfaceManager,
1298        // which will know whether we are connected to the network to disconnect from. This checks
1299        // that the IfaceManager is told to disconnect (if connected).
1300        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1301            assert_eq!(net_id, test_values.net_id_open.clone().into());
1302            assert_eq!(reason, client_types::DisconnectReason::NetworkUnsaved);
1303        });
1304        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1305        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1306        assert!(
1307            exec.run_singlethreaded(
1308                test_values.saved_networks.lookup(&test_values.net_id_open.clone().into())
1309            )
1310            .is_empty()
1311        );
1312
1313        // Removing a network that is not saved should not trigger a disconnect.
1314        let mut remove_fut = controller.remove_network(&network_config);
1315        // Process the remove request on the server side and handle requests to stash on the way.
1316        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1317        assert_matches!(
1318            exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()),
1319            Poll::Pending
1320        );
1321        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1322    }
1323
1324    #[fuchsia::test]
1325    fn test_get_saved_network() {
1326        let expected_configs = vec![generate_random_fidl_network_config()];
1327        let expected_num_sends = 1;
1328        run_get_saved_networks_test(expected_configs, expected_num_sends);
1329    }
1330
1331    #[fuchsia::test]
1332    fn test_get_saved_networks_multiple_chunks() {
1333        // Save MAX_CONFIGS_PER_RESPONSE + 1 configs so that get_saved_networks should respond with
1334        // 2 chunks of responses plus one response with an empty vector.
1335        let mut configs = vec![];
1336        for index in 0..MAX_CONFIGS_PER_RESPONSE + 1 {
1337            // Create unique network config to be saved.
1338            let ssid = format!("some_config{index}");
1339            let network_config = generate_random_fidl_network_config_with_ssid(&ssid);
1340            configs.push(network_config);
1341        }
1342
1343        let expected_num_sends = 2;
1344        run_get_saved_networks_test(configs, expected_num_sends);
1345    }
1346
1347    /// Test that get saved networks with the given saved networks
1348    /// test_id: the name of the test to create a unique persistent store for each test
1349    /// configs: list of FIDL NetworkConfigs that we expect to get from get_saved_networks and
1350    ///          and which are returned by SavedNetworksManager
1351    /// expected_num_sends: number of chunks of results we expect to get from get_saved_networks.
1352    ///     This is not counting the empty vector that signifies no more results.
1353    fn run_get_saved_networks_test(
1354        configs: Vec<fidl_policy::NetworkConfig>,
1355        expected_num_sends: usize,
1356    ) {
1357        let mut exec = fasync::TestExecutor::new();
1358        let saved_networks =
1359            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(configs.clone()));
1360
1361        let test_values = test_setup();
1362        let serve_fut = serve_provider_requests(
1363            test_values.iface_manager,
1364            test_values.update_sender,
1365            saved_networks.clone(),
1366            test_values.scan_requester,
1367            test_values.client_provider_lock,
1368            test_values.requests,
1369            test_values.telemetry_sender,
1370        );
1371        let mut serve_fut = pin!(serve_fut);
1372
1373        // No request has been sent yet. Future should be idle.
1374        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1375
1376        // Request a new controller.
1377        let (controller, _update_stream) = request_controller(&test_values.provider);
1378        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1379
1380        // Issue request to get the list of saved networks.
1381        let (iter, server) =
1382            fidl::endpoints::create_proxy::<fidl_policy::NetworkConfigIteratorMarker>();
1383        controller.get_saved_networks(server).expect("Failed to call get saved networks");
1384
1385        // Get responses from iterator. Expect to see the specified number of responses with
1386        // results plus one response of an empty vector indicating the end of results.
1387        let mut saved_networks_results = vec![];
1388        for i in 0..expected_num_sends {
1389            let get_saved_fut = iter.get_next();
1390            assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1391            let results = exec
1392                .run_singlethreaded(get_saved_fut)
1393                .expect("Failed to get next chunk of saved networks results");
1394            // the size of received chunk should either be max chunk size or whatever is left
1395            // to receive in the last chunk
1396            if i < expected_num_sends - 1 {
1397                assert_eq!(results.len(), MAX_CONFIGS_PER_RESPONSE);
1398            } else {
1399                assert_eq!(results.len(), configs.len() % MAX_CONFIGS_PER_RESPONSE);
1400            }
1401            saved_networks_results.extend(results);
1402        }
1403        let get_saved_end_fut = iter.get_next();
1404        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1405        let results = exec
1406            .run_singlethreaded(get_saved_end_fut)
1407            .expect("Failed to get next chunk of saved networks results");
1408        assert!(results.is_empty());
1409
1410        // check whether each network we saved is in the results and that nothing else is there.
1411        for network_config in &configs {
1412            assert!(saved_networks_results.contains(network_config));
1413        }
1414        assert_eq!(configs.len(), saved_networks_results.len());
1415    }
1416
1417    #[fuchsia::test]
1418    fn register_update_listener() {
1419        let mut exec = fasync::TestExecutor::new();
1420        let mut test_values = test_setup();
1421        let serve_fut = serve_provider_requests(
1422            test_values.iface_manager,
1423            test_values.update_sender,
1424            test_values.saved_networks,
1425            test_values.scan_requester,
1426            test_values.client_provider_lock,
1427            test_values.requests,
1428            test_values.telemetry_sender,
1429        );
1430        let mut serve_fut = pin!(serve_fut);
1431
1432        // No request has been sent yet. Future should be idle.
1433        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1434
1435        // Request a new controller.
1436        let (_controller, _update_stream) = request_controller(&test_values.provider);
1437        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1438        assert_matches!(
1439            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1440            Poll::Ready(Some(listener::Message::NewListener(_)))
1441        );
1442    }
1443
1444    #[fuchsia::test]
1445    fn get_listener() {
1446        let mut exec = fasync::TestExecutor::new();
1447        let (listener, requests) = create_proxy::<fidl_policy::ClientListenerMarker>();
1448        let requests = requests.into_stream();
1449
1450        let (update_sender, mut listener_updates) = mpsc::unbounded();
1451        let serve_fut = serve_listener_requests(update_sender, requests);
1452        let mut serve_fut = pin!(serve_fut);
1453
1454        // No request has been sent yet. Future should be idle.
1455        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1456
1457        // Register listener.
1458        let (update_sink, _update_stream) =
1459            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
1460        listener.get_listener(update_sink).expect("error getting listener");
1461
1462        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1463        assert_matches!(
1464            exec.run_until_stalled(&mut listener_updates.next()),
1465            Poll::Ready(Some(listener::Message::NewListener(_)))
1466        );
1467    }
1468
1469    #[fuchsia::test]
1470    fn multiple_controllers_write_attempt() {
1471        let mut exec = fasync::TestExecutor::new();
1472        let test_values = test_setup();
1473        let serve_fut = serve_provider_requests(
1474            test_values.iface_manager,
1475            test_values.update_sender,
1476            test_values.saved_networks,
1477            test_values.scan_requester,
1478            test_values.client_provider_lock,
1479            test_values.requests,
1480            test_values.telemetry_sender,
1481        );
1482        let mut serve_fut = pin!(serve_fut);
1483
1484        // No request has been sent yet. Future should be idle.
1485        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1486
1487        // Request a controller.
1488        let (controller1, _) = request_controller(&test_values.provider);
1489        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1490
1491        // Request another controller.
1492        let (controller2, _) = request_controller(&test_values.provider);
1493        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1494
1495        // Ensure first controller is operable. Issue connect request.
1496        let connect_fut = controller1.connect(&test_values.net_id_open);
1497        let mut connect_fut = pin!(connect_fut);
1498
1499        // Process connect request from first controller. Verify success.
1500        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1501
1502        assert_matches!(
1503            exec.run_until_stalled(&mut connect_fut),
1504            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1505        );
1506
1507        // Ensure second controller is not operable. Issue connect request.
1508        let connect_fut = controller2.connect(&test_values.net_id_open);
1509        let mut connect_fut = pin!(connect_fut);
1510
1511        // Process connect request from second controller. Verify failure.
1512        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1513        assert_matches!(
1514            exec.run_until_stalled(&mut connect_fut),
1515            Poll::Ready(Err(fidl::Error::ClientChannelClosed {
1516                status: zx::Status::ALREADY_BOUND,
1517                ..
1518            }))
1519        );
1520
1521        // Drop first controller. A new controller can now take control.
1522        drop(controller1);
1523        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1524
1525        // Request another controller.
1526        let (controller3, _) = request_controller(&test_values.provider);
1527        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1528
1529        // Ensure third controller is operable. Issue connect request.
1530        let connect_fut = controller3.connect(&test_values.net_id_open);
1531        let mut connect_fut = pin!(connect_fut);
1532
1533        // Process connect request from third controller. Verify success.
1534        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1535
1536        assert_matches!(
1537            exec.run_until_stalled(&mut connect_fut),
1538            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1539        );
1540    }
1541
1542    #[fuchsia::test]
1543    fn multiple_controllers_epitaph() {
1544        let mut exec = fasync::TestExecutor::new();
1545        let test_values = test_setup();
1546        let serve_fut = serve_provider_requests(
1547            test_values.iface_manager,
1548            test_values.update_sender,
1549            test_values.saved_networks.clone(),
1550            test_values.scan_requester,
1551            test_values.client_provider_lock,
1552            test_values.requests,
1553            test_values.telemetry_sender,
1554        );
1555        let mut serve_fut = pin!(serve_fut);
1556
1557        // No request has been sent yet. Future should be idle.
1558        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1559
1560        // Request a controller.
1561        let (_controller1, _) = request_controller(&test_values.provider);
1562        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1563
1564        // Request another controller.
1565        let (controller2, _) = request_controller(&test_values.provider);
1566        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1567
1568        // Verify Epitaph was received.
1569        let mut controller2_event_stream = controller2.take_event_stream();
1570        let controller2_event_fut = controller2_event_stream.next();
1571        let mut controller2_event_fut = pin!(controller2_event_fut);
1572        assert_matches!(
1573            exec.run_until_stalled(&mut controller2_event_fut),
1574            Poll::Ready(Some(Err(fidl::Error::ClientChannelClosed {
1575                status: zx::Status::ALREADY_BOUND,
1576                ..
1577            })))
1578        );
1579        assert!(controller2.is_closed());
1580    }
1581
1582    struct FakeIfaceManagerNoIfaces {}
1583
1584    #[async_trait(?Send)]
1585    impl IfaceManagerApi for FakeIfaceManagerNoIfaces {
1586        async fn disconnect(
1587            &mut self,
1588            _network_id: client_types::NetworkIdentifier,
1589            _reason: client_types::DisconnectReason,
1590        ) -> Result<(), Error> {
1591            Err(format_err!("No ifaces"))
1592        }
1593
1594        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
1595            Err(format_err!("No ifaces"))
1596        }
1597
1598        async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
1599            unimplemented!()
1600        }
1601
1602        async fn has_idle_client(&mut self) -> Result<bool, Error> {
1603            unimplemented!()
1604        }
1605
1606        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1607            unimplemented!()
1608        }
1609
1610        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1611            unimplemented!()
1612        }
1613
1614        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
1615            Err(format_err!("No ifaces"))
1616        }
1617
1618        async fn stop_client_connections(
1619            &mut self,
1620            _reason: client_types::DisconnectReason,
1621        ) -> Result<(), Error> {
1622            unimplemented!()
1623        }
1624
1625        async fn start_client_connections(&mut self) -> Result<(), Error> {
1626            unimplemented!()
1627        }
1628
1629        async fn start_ap(
1630            &mut self,
1631            _config: ap_fsm::ApConfig,
1632        ) -> Result<oneshot::Receiver<()>, Error> {
1633            unimplemented!()
1634        }
1635
1636        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
1637            unimplemented!()
1638        }
1639
1640        async fn stop_all_aps(&mut self) -> Result<(), Error> {
1641            unimplemented!()
1642        }
1643
1644        async fn set_country(
1645            &mut self,
1646            _country_code: Option<types::CountryCode>,
1647        ) -> Result<(), Error> {
1648            unimplemented!()
1649        }
1650    }
1651
1652    #[fuchsia::test]
1653    fn no_client_interface() {
1654        let mut exec = fasync::TestExecutor::new();
1655        let test_values = test_setup();
1656
1657        let iface_manager = Arc::new(Mutex::new(FakeIfaceManagerNoIfaces {}));
1658
1659        let serve_fut = serve_provider_requests(
1660            iface_manager,
1661            test_values.update_sender,
1662            test_values.saved_networks,
1663            test_values.scan_requester,
1664            test_values.client_provider_lock,
1665            test_values.requests,
1666            test_values.telemetry_sender,
1667        );
1668        let mut serve_fut = pin!(serve_fut);
1669
1670        // No request has been sent yet. Future should be idle.
1671        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1672
1673        // Request a controller.
1674        let (controller, _) = request_controller(&test_values.provider);
1675        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1676
1677        // Issue connect request.
1678        let connect_fut = controller.connect(&test_values.net_id_open);
1679        let mut connect_fut = pin!(connect_fut);
1680
1681        // Process connect request from first controller. Verify success.
1682        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1683        assert_matches!(
1684            exec.run_until_stalled(&mut connect_fut),
1685            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedIncompatibleMode))
1686        );
1687    }
1688
1689    // Gets a saved network config with a particular SSID, security type, and credential.
1690    // If there are more than one configs saved for the same SSID, security type, and credential,
1691    // the function will panic.
1692    async fn get_config(
1693        saved_networks: Arc<dyn SavedNetworksManagerApi>,
1694        id: NetworkIdentifier,
1695        cred: Credential,
1696    ) -> Option<NetworkConfig> {
1697        let mut cfgs = saved_networks
1698            .lookup(&id)
1699            .await
1700            .into_iter()
1701            .filter(|cfg| cfg.credential == cred)
1702            .collect::<Vec<_>>();
1703        // there should not be multiple configs with the same SSID, security type, and credential.
1704        assert!(cfgs.len() <= 1);
1705        cfgs.pop()
1706    }
1707
1708    #[fuchsia::test]
1709    async fn get_correct_config() {
1710        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1711        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1712        let cfg = NetworkConfig::new(
1713            network_id.clone(),
1714            Credential::Password(b"password".to_vec()),
1715            false,
1716        )
1717        .expect("Failed to create network config");
1718
1719        assert!(
1720            saved_networks
1721                .store(network_id.clone(), Credential::Password(b"password".to_vec()))
1722                .await
1723                .expect("Failed to store network config")
1724                .is_none()
1725        );
1726
1727        assert_eq!(
1728            Some(cfg),
1729            get_config(
1730                saved_networks.clone(),
1731                network_id,
1732                Credential::Password(b"password".to_vec())
1733            )
1734            .await
1735        );
1736        assert_eq!(
1737            None,
1738            get_config(
1739                saved_networks.clone(),
1740                NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap(),
1741                Credential::Password(b"not-saved".to_vec())
1742            )
1743            .await
1744        );
1745    }
1746
1747    #[fuchsia::test]
1748    fn multiple_api_clients() {
1749        let mut exec = fasync::TestExecutor::new();
1750        let test_values = test_setup();
1751        let serve_fut = serve_provider_requests(
1752            test_values.iface_manager.clone(),
1753            test_values.update_sender.clone(),
1754            test_values.saved_networks.clone(),
1755            test_values.scan_requester.clone(),
1756            test_values.client_provider_lock.clone(),
1757            test_values.requests,
1758            test_values.telemetry_sender.clone(),
1759        );
1760        let mut serve_fut = pin!(serve_fut);
1761
1762        // No request has been sent yet. Future should be idle.
1763        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1764
1765        // Request a controller.
1766        let (controller1, _) = request_controller(&test_values.provider);
1767        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1768
1769        // Create another client provider request stream and start serving it.  This is equivalent
1770        // to the behavior that occurs when a second client connects to the ClientProvider service.
1771        let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>();
1772        let requests = requests.into_stream();
1773
1774        let second_serve_fut = serve_provider_requests(
1775            test_values.iface_manager.clone(),
1776            test_values.update_sender.clone(),
1777            test_values.saved_networks.clone(),
1778            test_values.scan_requester,
1779            test_values.client_provider_lock.clone(),
1780            requests,
1781            test_values.telemetry_sender,
1782        );
1783        let mut second_serve_fut = pin!(second_serve_fut);
1784
1785        // Request a client controller from the second instance of the service.
1786        let (controller2, _) = request_controller(&provider);
1787        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1788
1789        // Verify Epitaph was received.
1790        let mut controller2_event_stream = controller2.take_event_stream();
1791        let controller2_event_fut = controller2_event_stream.next();
1792        let mut controller2_event_fut = pin!(controller2_event_fut);
1793        assert_matches!(
1794            exec.run_until_stalled(&mut controller2_event_fut),
1795            Poll::Ready(Some(Err(fidl::Error::ClientChannelClosed {
1796                status: zx::Status::ALREADY_BOUND,
1797                ..
1798            })))
1799        );
1800        assert!(controller2.is_closed());
1801
1802        // Drop the first controller and verify that the second provider client can get a
1803        // functional client controller.
1804        drop(controller1);
1805        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1806
1807        let (controller2, _) = request_controller(&provider);
1808        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1809
1810        // Ensure the new controller works by issuing a connect request.
1811        let connect_fut = controller2.connect(&test_values.net_id_open);
1812        let mut connect_fut = pin!(connect_fut);
1813
1814        // Process connect request from first controller. Verify success.
1815        assert_matches!(exec.run_until_stalled(&mut second_serve_fut), Poll::Pending);
1816
1817        assert_matches!(
1818            exec.run_until_stalled(&mut connect_fut),
1819            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1820        );
1821    }
1822
1823    #[test_case(true)]
1824    #[test_case(false)]
1825    #[fuchsia::test(add_test_attr = false)]
1826    fn test_start_client_connections(start_client_connections_succeeds: bool) {
1827        let mut exec = fasync::TestExecutor::new();
1828        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
1829        let (req_sender, _req_recvr) = mpsc::channel(1);
1830        let mut iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
1831
1832        // Setup the IfaceManager to succeed or fail depending on the test configuration.
1833        iface_manager.start_client_connections_succeeds = start_client_connections_succeeds;
1834
1835        let iface_manager: Arc<Mutex<dyn IfaceManagerApi>> = Arc::new(Mutex::new(iface_manager));
1836
1837        // Regardless of what the IfaceManager is actually able to do, we expect the response to
1838        // simply ack the caller.
1839        let fut = handle_client_request_start_client_connections(iface_manager);
1840        let mut fut = pin!(fut);
1841        assert_matches!(
1842            exec.run_until_stalled(&mut fut),
1843            Poll::Ready(fidl_policy::RequestStatus::Acknowledged)
1844        );
1845    }
1846
1847    #[test_case(true)]
1848    #[test_case(false)]
1849    #[fuchsia::test(add_test_attr = false)]
1850    fn test_stop_client_connections(stop_client_connections_succeeds: bool) {
1851        let mut exec = fasync::TestExecutor::new();
1852        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
1853        let (req_sender, _req_recvr) = mpsc::channel(1);
1854        let mut iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
1855
1856        // Setup the IfaceManager to succeed or fail depending on the test configuration.
1857        iface_manager.stop_client_connections_succeeds = stop_client_connections_succeeds;
1858
1859        let iface_manager: Arc<Mutex<dyn IfaceManagerApi>> = Arc::new(Mutex::new(iface_manager));
1860
1861        // Regardless of what the IfaceManager is actually able to do, we expect the response to
1862        // simply ack the caller.
1863        let fut = handle_client_request_stop_client_connections(iface_manager);
1864        let mut fut = pin!(fut);
1865        assert_matches!(
1866            exec.run_until_stalled(&mut fut),
1867            Poll::Ready(fidl_policy::RequestStatus::Acknowledged)
1868        );
1869    }
1870}