Skip to main content

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            let fidl_results = scan::scan_result_to_policy_scan_result(&results);
304            if let Err(e) = scan::send_scan_results_over_fidl(output_iterator, &fidl_results).await
305            {
306                warn!("Failed to send scan results to requester: {:?}", e);
307            }
308        }
309        Err(e) => {
310            if let Err(e) = scan::send_scan_error_over_fidl(output_iterator, e).await {
311                warn!("Failed to send scan error to requester: {:?}", e);
312            }
313        }
314    }
315}
316
317/// This function handles requests to save a network by saving the network and sending back to the
318/// controller whether or not we successfully saved the network. There could be a FIDL error in
319/// sending the response.
320async fn handle_client_request_save_network(
321    saved_networks: SavedNetworksPtr,
322    network_config: fidl_policy::NetworkConfig,
323    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
324) -> Result<(), NetworkConfigError> {
325    // The FIDL network config fields are defined as Options, and we consider it an error if either
326    // field is missing (ie None) here.
327    let net_id: client_types::NetworkIdentifier =
328        network_config.id.ok_or(NetworkConfigError::ConfigMissingId)?.into();
329    let credential = Credential::try_from(
330        network_config.credential.ok_or(NetworkConfigError::ConfigMissingCredential)?,
331    )?;
332    let evicted_config = saved_networks.store(net_id.clone(), credential.clone()).await?;
333
334    // If a config was removed, disconnect from that network.
335    let mut iface_manager = iface_manager.lock().await;
336    if let Some(config) = evicted_config {
337        let net_id = client_types::NetworkIdentifier {
338            ssid: config.ssid,
339            security_type: config.security_type,
340        };
341        match iface_manager
342            .disconnect(net_id, client_types::DisconnectReason::NetworkConfigUpdated)
343            .await
344        {
345            Ok(()) => {}
346            Err(e) => error!("failed to disconnect from network: {}", e),
347        }
348    }
349
350    // Attempt to connect to the new network if there is an idle client interface.
351    let connect_req = ConnectAttemptRequest::new(
352        net_id,
353        credential,
354        client_types::ConnectReason::NewSavedNetworkAutoconnect,
355    );
356    match iface_manager.has_idle_client().await {
357        Ok(true) => {
358            info!("Idle interface available, will attempt connection to new saved network");
359            let _ = iface_manager.connect(connect_req).await;
360        }
361        Ok(false) => {}
362        Err(e) => {
363            error!("Unable to query idle client state while saving network: {:?}", e);
364        }
365    }
366
367    Ok(())
368}
369
370/// Will remove the specified network and respond to the remove network request with a network
371/// config change error if an error occurs while trying to remove the network.
372async fn handle_client_request_remove_network(
373    saved_networks: SavedNetworksPtr,
374    network_config: fidl_policy::NetworkConfig,
375    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
376) -> Result<(), NetworkConfigError> {
377    // The FIDL network config fields are defined as Options, and we consider it an error if either
378    // field is missing (ie None) here.
379    let net_id =
380        NetworkIdentifier::from(network_config.id.ok_or(NetworkConfigError::ConfigMissingId)?);
381    let credential = Credential::try_from(
382        network_config.credential.ok_or(NetworkConfigError::ConfigMissingCredential)?,
383    )?;
384    if saved_networks.remove(net_id.clone(), credential.clone()).await? {
385        match iface_manager
386            .lock()
387            .await
388            .disconnect(net_id, client_types::DisconnectReason::NetworkUnsaved)
389            .await
390        {
391            Ok(()) => {}
392            Err(e) => error!("failed to disconnect from network: {}", e),
393        }
394    }
395    Ok(())
396}
397
398async fn handle_client_request_get_networks(
399    saved_networks: SavedNetworksPtr,
400    iterator: fidl::endpoints::ServerEnd<fidl_policy::NetworkConfigIteratorMarker>,
401) -> Result<(), fidl::Error> {
402    // make sufficiently small batches of networks to send and convert configs to FIDL values
403    let network_configs = saved_networks.get_networks().await;
404    let chunks = network_configs.chunks(MAX_CONFIGS_PER_RESPONSE);
405    let fidl_chunks = chunks.into_iter().map(|chunk| {
406        chunk
407            .iter()
408            .map(fidl_policy::NetworkConfig::from)
409            .collect::<Vec<fidl_policy::NetworkConfig>>()
410    });
411    let mut stream = iterator.into_stream();
412    for chunk in fidl_chunks {
413        send_next_chunk(&mut stream, chunk).await?;
414    }
415    send_next_chunk(&mut stream, vec![]).await
416}
417
418/// Send a chunk of saved networks to the specified FIDL iterator
419async fn send_next_chunk(
420    stream: &mut fidl_policy::NetworkConfigIteratorRequestStream,
421    chunk: Vec<fidl_policy::NetworkConfig>,
422) -> Result<(), fidl::Error> {
423    if let Some(req) = stream.try_next().await? {
424        let fidl_policy::NetworkConfigIteratorRequest::GetNext { responder } = req;
425        responder.send(&chunk)
426    } else {
427        // This will happen if the iterator request stream was closed and we expected to send
428        // another response.
429        // TODO(https://fxbug.dev/42121602) Test this error path
430        info!("Info: peer closed channel for network config results unexpectedly");
431        Ok(())
432    }
433}
434
435/// Handle inbound requests to register an additional ClientStateUpdates listener.
436async fn handle_listener_request(
437    update_sender: listener::ClientListenerMessageSender,
438    req: fidl_policy::ClientListenerRequest,
439) -> Result<(), fidl::Error> {
440    match req {
441        fidl_policy::ClientListenerRequest::GetListener { updates, .. } => {
442            register_listener(update_sender, updates.into_proxy());
443            Ok(())
444        }
445    }
446}
447
448/// Registers a new update listener.
449/// The client's current state will be send to the newly added listener immediately.
450fn register_listener(
451    update_sender: listener::ClientListenerMessageSender,
452    listener: fidl_policy::ClientStateUpdatesProxy,
453) {
454    let _ignored = update_sender.unbounded_send(listener::Message::NewListener(listener));
455}
456
457/// Rejects a ClientProvider request by sending a corresponding Epitaph via the |requests| and
458/// |updates| channels.
459fn reject_provider_request(req: fidl_policy::ClientProviderRequest) -> Result<(), fidl::Error> {
460    match req {
461        fidl_policy::ClientProviderRequest::GetController { requests, updates, .. } => {
462            info!("Rejecting new client controller request because a controller is in use");
463            requests.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
464            updates.into_channel().close_with_epitaph(zx::Status::ALREADY_BOUND)?;
465            Ok(())
466        }
467    }
468}
469
470/// Allows client operations to be performed.
471async fn handle_client_request_start_client_connections(
472    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
473) -> fidl_policy::RequestStatus {
474    let mut iface_manager = iface_manager.lock().await;
475    if let Err(e) = iface_manager.start_client_connections().await {
476        warn!("encountered an error while starting client connections: {:?}", e);
477    }
478    fidl_policy::RequestStatus::Acknowledged
479}
480
481/// Stops all active client connections and disallows future client operations.
482async fn handle_client_request_stop_client_connections(
483    iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
484) -> fidl_policy::RequestStatus {
485    let mut iface_manager = iface_manager.lock().await;
486    if let Err(e) = iface_manager
487        .stop_client_connections(client_types::DisconnectReason::FidlStopClientConnectionsRequest)
488        .await
489    {
490        warn!("encountered an error while stopping client connections: {:?}", e);
491    }
492    fidl_policy::RequestStatus::Acknowledged
493}
494
495#[cfg(test)]
496mod tests {
497    use super::*;
498    use crate::access_point::state_machine as ap_fsm;
499    use crate::config_management::{NetworkConfig, SecurityType, WPA_PSK_BYTE_LEN};
500    use crate::mode_management::iface_manager_api::SmeForScan;
501    use crate::util::testing::fakes::{FakeSavedNetworksManager, FakeScanRequester};
502    use crate::util::testing::{
503        generate_random_fidl_network_config, generate_random_fidl_network_config_with_ssid,
504    };
505    use anyhow::{Error, format_err};
506    use assert_matches::assert_matches;
507    use async_trait::async_trait;
508    use fidl::endpoints::{Proxy, create_proxy, create_request_stream};
509    use fuchsia_async as fasync;
510    use futures::channel::{mpsc, oneshot};
511    use futures::task::Poll;
512    use std::pin::pin;
513    use test_case::test_case;
514
515    /// Only used to tell us what disconnect request was given to the IfaceManager so that we
516    /// don't need to worry about the implementation logic in the FakeIfaceManager.
517    #[derive(Debug)]
518    enum IfaceManagerRequest {
519        Disconnect(client_types::NetworkIdentifier, client_types::DisconnectReason),
520    }
521
522    struct FakeIfaceManager {
523        pub sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
524        pub disconnected_ifaces: Vec<u16>,
525        command_sender: mpsc::Sender<IfaceManagerRequest>,
526        start_client_connections_succeeds: bool,
527        stop_client_connections_succeeds: bool,
528    }
529
530    impl FakeIfaceManager {
531        pub fn new(
532            proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
533            command_sender: mpsc::Sender<IfaceManagerRequest>,
534        ) -> Self {
535            FakeIfaceManager {
536                sme_proxy: proxy,
537                disconnected_ifaces: Vec::new(),
538                command_sender,
539                start_client_connections_succeeds: true,
540                stop_client_connections_succeeds: true,
541            }
542        }
543    }
544
545    #[async_trait(?Send)]
546    impl IfaceManagerApi for FakeIfaceManager {
547        async fn disconnect(
548            &mut self,
549            network_id: client_types::NetworkIdentifier,
550            reason: client_types::DisconnectReason,
551        ) -> Result<(), Error> {
552            self.command_sender
553                .try_send(IfaceManagerRequest::Disconnect(network_id, reason))
554                .map_err(|e| {
555                    error!(
556                        "Failed to send disconnect: commands_sender's receiver may have
557                        been dropped. FakeIfaceManager should be created manually with a sender
558                        assigned: {:?}",
559                        e
560                    );
561                    format_err!("failed to send disconnect: {:?}", e)
562                })
563        }
564
565        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
566            let _ = self.disconnected_ifaces.pop();
567            Ok(())
568        }
569
570        async fn record_idle_client(&mut self, iface_id: u16) -> Result<(), Error> {
571            self.disconnected_ifaces.push(iface_id);
572            Ok(())
573        }
574
575        async fn has_idle_client(&mut self) -> Result<bool, Error> {
576            Ok(!self.disconnected_ifaces.is_empty())
577        }
578
579        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
580            unimplemented!()
581        }
582
583        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
584            unimplemented!()
585        }
586
587        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
588            let (defect_sender, _) = mpsc::channel(100);
589            Ok(SmeForScan::new(self.sme_proxy.clone(), 0, defect_sender))
590        }
591
592        async fn stop_client_connections(
593            &mut self,
594            _reason: client_types::DisconnectReason,
595        ) -> Result<(), Error> {
596            if self.stop_client_connections_succeeds {
597                Ok(())
598            } else {
599                Err(format_err!("stop client connections failed"))
600            }
601        }
602
603        async fn start_client_connections(&mut self) -> Result<(), Error> {
604            if self.start_client_connections_succeeds {
605                Ok(())
606            } else {
607                Err(format_err!("start client connections failed"))
608            }
609        }
610
611        async fn start_ap(
612            &mut self,
613            _config: ap_fsm::ApConfig,
614        ) -> Result<oneshot::Receiver<()>, Error> {
615            unimplemented!()
616        }
617
618        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
619            unimplemented!()
620        }
621
622        async fn stop_all_aps(&mut self) -> Result<(), Error> {
623            unimplemented!()
624        }
625
626        async fn set_country(
627            &mut self,
628            _country_code: Option<types::CountryCode>,
629        ) -> Result<(), Error> {
630            unimplemented!()
631        }
632    }
633
634    /// Requests a new ClientController from the given ClientProvider.
635    fn request_controller(
636        provider: &fidl_policy::ClientProviderProxy,
637    ) -> (fidl_policy::ClientControllerProxy, fidl_policy::ClientStateUpdatesRequestStream) {
638        let (controller, requests) = create_proxy::<fidl_policy::ClientControllerMarker>();
639        let (update_sink, update_stream) =
640            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
641        provider.get_controller(requests, update_sink).expect("error getting controller");
642        (controller, update_stream)
643    }
644
645    struct TestValues {
646        saved_networks: SavedNetworksPtr,
647        net_id_open: fidl_policy::NetworkIdentifier,
648        net_id_wpa2_w_password: fidl_policy::NetworkIdentifier,
649        net_id_wpa2_w_psk: fidl_policy::NetworkIdentifier,
650        provider: fidl_policy::ClientProviderProxy,
651        requests: fidl_policy::ClientProviderRequestStream,
652        iface_manager: Arc<Mutex<dyn IfaceManagerApi>>,
653        iface_mgr_req_recvr: mpsc::Receiver<IfaceManagerRequest>,
654        scan_requester: Arc<FakeScanRequester>,
655        update_sender: mpsc::UnboundedSender<listener::ClientListenerMessage>,
656        listener_updates: mpsc::UnboundedReceiver<listener::ClientListenerMessage>,
657        client_provider_lock: Arc<Mutex<()>>,
658        telemetry_sender: TelemetrySender,
659        telemetry_receiver: mpsc::Receiver<TelemetryEvent>,
660    }
661
662    // setup channels and proxies needed for the tests to use use the Client Provider and
663    // Client Controller APIs in tests. The stash id should be the test name so that each
664    // test will have a unique persistent store behind it.
665    fn test_setup() -> TestValues {
666        let net_id_open = fidl_policy::NetworkIdentifier {
667            ssid: "foobar".to_string().into_bytes(),
668            type_: fidl_policy::SecurityType::None,
669        };
670        let net_id_wpa2_w_password = fidl_policy::NetworkIdentifier {
671            ssid: b"foobar-wpa2".to_vec(),
672            type_: fidl_policy::SecurityType::Wpa2,
673        };
674        let net_id_wpa2_w_psk = fidl_policy::NetworkIdentifier {
675            ssid: b"foobar-psk".to_vec(),
676            type_: fidl_policy::SecurityType::Wpa2,
677        };
678
679        let presaved_default_configs = vec![
680            fidl_policy::NetworkConfig {
681                id: Some(net_id_open.clone()),
682                credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
683                ..Default::default()
684            },
685            fidl_policy::NetworkConfig {
686                id: Some(net_id_wpa2_w_password.clone()),
687                credential: Some(fidl_policy::Credential::Password(b"foobar-password".to_vec())),
688                ..Default::default()
689            },
690            fidl_policy::NetworkConfig {
691                id: Some(net_id_wpa2_w_psk.clone()),
692                credential: Some(fidl_policy::Credential::Psk([64; WPA_PSK_BYTE_LEN].to_vec())),
693                ..Default::default()
694            },
695        ];
696        let saved_networks =
697            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(presaved_default_configs));
698        let (telemetry_sender, telemetry_receiver) = mpsc::channel::<TelemetryEvent>(100);
699        let (provider, requests) = create_proxy::<fidl_policy::ClientProviderMarker>();
700        let requests = requests.into_stream();
701
702        let (proxy, _server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>();
703        let (req_sender, iface_mgr_req_recvr) = mpsc::channel(1);
704        let iface_manager = FakeIfaceManager::new(proxy.clone(), req_sender);
705        let iface_manager = Arc::new(Mutex::new(iface_manager));
706        let scan_requester = Arc::new(FakeScanRequester::new());
707
708        let (update_sender, listener_updates) = mpsc::unbounded();
709
710        TestValues {
711            saved_networks,
712            net_id_open,
713            net_id_wpa2_w_password,
714            net_id_wpa2_w_psk,
715            provider,
716            requests,
717            iface_manager,
718            iface_mgr_req_recvr,
719            scan_requester,
720            update_sender,
721            listener_updates,
722            client_provider_lock: Arc::new(Mutex::new(())),
723            telemetry_sender: TelemetrySender::new(telemetry_sender),
724            telemetry_receiver,
725        }
726    }
727
728    #[fuchsia::test]
729    fn connect_request_unknown_network() {
730        let ssid = client_types::Ssid::try_from("foobar-unknown").unwrap();
731        let mut exec = fasync::TestExecutor::new();
732        let test_values = test_setup();
733        let serve_fut = serve_provider_requests(
734            test_values.iface_manager,
735            test_values.update_sender,
736            Arc::clone(&test_values.saved_networks),
737            test_values.scan_requester,
738            test_values.client_provider_lock,
739            test_values.requests,
740            test_values.telemetry_sender,
741        );
742        let mut serve_fut = pin!(serve_fut);
743
744        // No request has been sent yet. Future should be idle.
745        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
746
747        // Request a new controller.
748        let (controller, _) = request_controller(&test_values.provider);
749        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
750
751        // Issue connect request.
752        let connect_fut = controller.connect(&fidl_policy::NetworkIdentifier {
753            ssid: ssid.to_vec(),
754            type_: fidl_policy::SecurityType::None,
755        });
756        let mut connect_fut = pin!(connect_fut);
757
758        // Process connect request and verify connect response.
759        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
760
761        assert_matches!(
762            exec.run_until_stalled(&mut connect_fut),
763            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedNotSupported))
764        );
765
766        // Unknown network should not have been saved by saved networks manager
767        // since we did not successfully connect.
768        let id = NetworkIdentifier::new(ssid, SecurityType::None);
769        let lookup_fut = test_values.saved_networks.lookup(&id);
770        assert!(exec.run_singlethreaded(lookup_fut).is_empty());
771    }
772
773    #[fuchsia::test]
774    fn connect_request_open_network() {
775        let mut exec = fasync::TestExecutor::new();
776
777        let test_values = test_setup();
778        let serve_fut = serve_provider_requests(
779            test_values.iface_manager,
780            test_values.update_sender,
781            Arc::clone(&test_values.saved_networks),
782            test_values.scan_requester,
783            test_values.client_provider_lock,
784            test_values.requests,
785            test_values.telemetry_sender,
786        );
787        let mut serve_fut = pin!(serve_fut);
788
789        // No request has been sent yet. Future should be idle.
790        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
791
792        // Request a new controller.
793        let (controller, _update_stream) = request_controller(&test_values.provider);
794        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
795
796        // Issue connect request.
797        let connect_fut = controller.connect(&test_values.net_id_open);
798        let mut connect_fut = pin!(connect_fut);
799
800        // Process connect request and verify connect response.
801        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
802
803        // Verify that the connect call is acknowledged.
804        assert_matches!(
805            exec.run_until_stalled(&mut connect_fut),
806            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
807        );
808    }
809
810    #[fuchsia::test]
811    fn connect_request_protected_network() {
812        let mut exec = fasync::TestExecutor::new();
813
814        let test_values = test_setup();
815        let serve_fut = serve_provider_requests(
816            test_values.iface_manager,
817            test_values.update_sender,
818            Arc::clone(&test_values.saved_networks),
819            test_values.scan_requester,
820            test_values.client_provider_lock,
821            test_values.requests,
822            test_values.telemetry_sender,
823        );
824        let mut serve_fut = pin!(serve_fut);
825
826        // No request has been sent yet. Future should be idle.
827        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
828
829        // Request a new controller.
830        let (controller, _update_stream) = request_controller(&test_values.provider);
831        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
832
833        // Issue connect request.
834        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
835        let mut connect_fut = pin!(connect_fut);
836
837        // Process connect request and verify connect response.
838        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
839
840        // Verify that the connect call is acknowledged.
841        assert_matches!(
842            exec.run_until_stalled(&mut connect_fut),
843            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
844        );
845    }
846
847    #[fuchsia::test]
848    fn connect_request_protected_psk_network() {
849        let mut exec = fasync::TestExecutor::new();
850
851        let test_values = test_setup();
852        let serve_fut = serve_provider_requests(
853            test_values.iface_manager,
854            test_values.update_sender,
855            Arc::clone(&test_values.saved_networks),
856            test_values.scan_requester,
857            test_values.client_provider_lock,
858            test_values.requests,
859            test_values.telemetry_sender,
860        );
861        let mut serve_fut = pin!(serve_fut);
862
863        // No request has been sent yet. Future should be idle.
864        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
865
866        // Request a new controller.
867        let (controller, _update_stream) = request_controller(&test_values.provider);
868        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
869
870        // Issue connect request.
871        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_psk);
872        let mut connect_fut = pin!(connect_fut);
873
874        // Process connect request and verify connect response.
875        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
876
877        // Verify that the connect call is acknowledged.
878        assert_matches!(
879            exec.run_until_stalled(&mut connect_fut),
880            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
881        );
882    }
883
884    #[fuchsia::test]
885    fn start_and_stop_client_connections() {
886        let mut exec = fasync::TestExecutor::new();
887        let mut test_values = test_setup();
888        let serve_fut = serve_provider_requests(
889            test_values.iface_manager,
890            test_values.update_sender,
891            test_values.saved_networks,
892            test_values.scan_requester,
893            test_values.client_provider_lock,
894            test_values.requests,
895            test_values.telemetry_sender,
896        );
897        let mut serve_fut = pin!(serve_fut);
898
899        // No request has been sent yet. Future should now be waiting for request.
900        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
901
902        // Request a new controller.
903        let (controller, _update_stream) = request_controller(&test_values.provider);
904        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
905
906        // Issue request to start client connections.
907        let start_fut = controller.start_client_connections();
908        let mut start_fut = pin!(start_fut);
909
910        // Request should be acknowledged.
911        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
912        assert_matches!(
913            exec.run_until_stalled(&mut start_fut),
914            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
915        );
916
917        // A message should be sent to telemetry.
918        assert_matches!(test_values.telemetry_receiver.try_next(), Ok(Some(event)) => {
919            assert_matches!(event, TelemetryEvent::StartClientConnectionsRequest);
920        });
921
922        // Perform a connect operation.
923        let connect_fut = controller.connect(&test_values.net_id_wpa2_w_password);
924        let mut connect_fut = pin!(connect_fut);
925
926        // Process connect request and verify connect response.
927        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
928
929        // Verify that the connect call is acknowledged.
930        assert_matches!(
931            exec.run_until_stalled(&mut connect_fut),
932            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
933        );
934
935        // The client state machine will immediately query for status.
936        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
937
938        // Issue request to stop client connections.
939        let stop_fut = controller.stop_client_connections();
940        let mut stop_fut = pin!(stop_fut);
941
942        // Run the serve future until it stalls and expect the client to disconnect
943        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
944
945        // A message should be sent to telemetry.
946        assert_matches!(test_values.telemetry_receiver.try_next(), Ok(Some(event)) => {
947            assert_matches!(event, TelemetryEvent::StopClientConnectionsRequest);
948        });
949
950        // Request should be acknowledged.
951        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
952        assert_matches!(
953            exec.run_until_stalled(&mut stop_fut),
954            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
955        );
956    }
957
958    /// End-to-end test of the scan function, verifying that an incoming
959    /// FIDL scan request results in a scan in the SME, and that the results
960    /// make it back to the requester.
961    #[fuchsia::test]
962    fn scan_end_to_end() {
963        let mut exec = fasync::TestExecutor::new();
964        let test_values = test_setup();
965        let serve_fut = serve_provider_requests(
966            test_values.iface_manager,
967            test_values.update_sender,
968            test_values.saved_networks,
969            test_values.scan_requester.clone(),
970            test_values.client_provider_lock,
971            test_values.requests,
972            test_values.telemetry_sender,
973        );
974        let mut serve_fut = pin!(serve_fut);
975
976        // No request has been sent yet. Future should be idle.
977        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
978
979        // Request a new controller.
980        let (controller, _update_stream) = request_controller(&test_values.provider);
981        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
982
983        // Issue a scan request.
984        let (_iter, server) = fidl::endpoints::create_proxy();
985        controller.scan_for_networks(server).expect("Failed to call scan for networks");
986
987        // Currently the FakeScanRequester will panic if a scan is requested and no results
988        // are queued, so add something.
989        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
990        // A second scan request for all the likely-hidden networks
991        exec.run_singlethreaded(test_values.scan_requester.add_scan_result(Ok(vec![])));
992
993        // Process scan request and verify scan response.
994        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
995
996        // Check that a scan request was sent to the scan module, including an active scan for the
997        // potentially-hidden networks.
998        let expected_active_ssids = [
999            test_values.net_id_wpa2_w_password,
1000            test_values.net_id_wpa2_w_psk,
1001            test_values.net_id_open,
1002        ]
1003        .iter()
1004        .map(|id| types::Ssid::from_bytes_unchecked(id.ssid.clone()))
1005        .collect();
1006        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1007            scan::ScanReason::ClientRequest,
1008            vec![],
1009            vec![],
1010        )));
1011        exec.run_singlethreaded(test_values.scan_requester.verify_scan_request((
1012            scan::ScanReason::ClientRequest,
1013            expected_active_ssids,
1014            vec![],
1015        )));
1016    }
1017
1018    #[fuchsia::test]
1019    fn save_network() {
1020        let mut exec = fasync::TestExecutor::new();
1021        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1022
1023        let mut test_values = test_setup();
1024        let serve_fut = serve_provider_requests(
1025            test_values.iface_manager,
1026            test_values.update_sender,
1027            saved_networks.clone(),
1028            test_values.scan_requester,
1029            test_values.client_provider_lock,
1030            test_values.requests,
1031            test_values.telemetry_sender,
1032        );
1033        let mut serve_fut = pin!(serve_fut);
1034
1035        // No request has been sent yet. Future should be idle.
1036        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1037
1038        // Request a new controller.
1039        let (controller, _update_stream) = request_controller(&test_values.provider);
1040        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1041        assert_matches!(
1042            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1043            Poll::Ready(_)
1044        );
1045
1046        // Save some network
1047        let network_id = fidl_policy::NetworkIdentifier {
1048            ssid: b"foo".to_vec(),
1049            type_: fidl_policy::SecurityType::None,
1050        };
1051        let network_config = fidl_policy::NetworkConfig {
1052            id: Some(network_id.clone()),
1053            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1054            ..Default::default()
1055        };
1056        let mut save_fut = controller.save_network(&network_config);
1057
1058        // Run server_provider forward so that it will process the save network request
1059        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1060        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1061
1062        // Check that the the response says we succeeded.
1063        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1064
1065        // Check that the value was actually saved in the saved networks manager.
1066        let target_id = NetworkIdentifier::from(network_id);
1067        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false, None)
1068            .expect("Failed to create network config");
1069        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![target_config]);
1070    }
1071
1072    #[fuchsia::test]
1073    fn save_network_with_disconnected_iface() {
1074        let mut exec = fasync::TestExecutor::new();
1075        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1076
1077        let mut test_values = test_setup();
1078        let serve_fut = serve_provider_requests(
1079            test_values.iface_manager.clone(),
1080            test_values.update_sender,
1081            saved_networks.clone(),
1082            test_values.scan_requester,
1083            test_values.client_provider_lock,
1084            test_values.requests,
1085            test_values.telemetry_sender,
1086        );
1087        let mut serve_fut = pin!(serve_fut);
1088
1089        // Setup the IfaceManager so that it has a disconnected iface.
1090        {
1091            let iface_manager = test_values.iface_manager.clone();
1092            let iface_manager_fut = iface_manager.lock();
1093            let mut iface_manager_fut = pin!(iface_manager_fut);
1094            let mut iface_manager = match exec.run_until_stalled(&mut iface_manager_fut) {
1095                Poll::Ready(iface_manager) => iface_manager,
1096                Poll::Pending => panic!("expected to acquire iface_manager lock"),
1097            };
1098            let record_idle_fut = iface_manager.record_idle_client(0);
1099            let mut record_idle_fut = pin!(record_idle_fut);
1100            assert_matches!(exec.run_until_stalled(&mut record_idle_fut), Poll::Ready(Ok(())));
1101        }
1102
1103        // No request has been sent yet. Future should be idle.
1104        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1105
1106        // Request a new controller.
1107        let (controller, _update_stream) = request_controller(&test_values.provider);
1108        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1109        assert_matches!(
1110            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1111            Poll::Ready(_)
1112        );
1113
1114        // Save some network
1115        let network_id = fidl_policy::NetworkIdentifier {
1116            ssid: b"foo".to_vec(),
1117            type_: fidl_policy::SecurityType::None,
1118        };
1119        let network_config = fidl_policy::NetworkConfig {
1120            id: Some(network_id.clone()),
1121            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1122            ..Default::default()
1123        };
1124        let mut save_fut = controller.save_network(&network_config);
1125
1126        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Pending);
1127        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1128
1129        // Check that the the response says we succeeded.
1130        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1131            let save_result = result.expect("Failed to get save network response");
1132            assert_eq!(save_result, Ok(()));
1133        });
1134
1135        // Check that the value was actually saved in the saved networks manager.
1136        let target_id = NetworkIdentifier::from(network_id);
1137        let target_config = NetworkConfig::new(target_id.clone(), Credential::None, false, None)
1138            .expect("Failed to create network config");
1139        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![target_config]);
1140    }
1141
1142    #[fuchsia::test]
1143    fn save_network_overwrite_disconnects() {
1144        let mut exec = fasync::TestExecutor::new();
1145        let mut test_values = test_setup();
1146        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1147
1148        let serve_fut = serve_provider_requests(
1149            test_values.iface_manager,
1150            test_values.update_sender,
1151            saved_networks.clone(),
1152            test_values.scan_requester,
1153            test_values.client_provider_lock,
1154            test_values.requests,
1155            test_values.telemetry_sender,
1156        );
1157        let mut serve_fut = pin!(serve_fut);
1158
1159        // No request has been sent yet. Future should be idle.
1160        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1161
1162        // Request a new controller.
1163        let (controller, _update_stream) = request_controller(&test_values.provider);
1164        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1165        assert_matches!(
1166            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1167            Poll::Ready(_)
1168        );
1169
1170        // Save the network directly.
1171        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1172        let credential = Credential::Password(b"password".to_vec());
1173        let save_fut = saved_networks.store(network_id.clone(), credential.clone());
1174        let mut save_fut = pin!(save_fut);
1175        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(None)));
1176
1177        // Save a network with the same identifier but a different password
1178        let network_config = fidl_policy::NetworkConfig {
1179            id: Some(fidl_policy::NetworkIdentifier::from(network_id.clone())),
1180            credential: Some(fidl_policy::Credential::Password(b"other-password".to_vec())),
1181            ..Default::default()
1182        };
1183        let mut save_fut = controller.save_network(&network_config);
1184
1185        // Process the remove request on the server side and handle requests to stash on the way.
1186        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1187        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1188
1189        // Check that the iface manager was asked to disconnect from some network
1190        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1191            assert_eq!(net_id, network_id.clone());
1192            assert_eq!(reason, client_types::DisconnectReason::NetworkConfigUpdated);
1193        });
1194        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1195        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(Ok(Ok(()))));
1196    }
1197
1198    #[fuchsia::test]
1199    fn save_bad_network_should_fail() {
1200        let mut exec = fasync::TestExecutor::new();
1201        let mut saved_networks = FakeSavedNetworksManager::new();
1202        saved_networks.fail_all_stores = true;
1203        let saved_networks = Arc::new(saved_networks);
1204
1205        let mut test_values = test_setup();
1206        let serve_fut = serve_provider_requests(
1207            test_values.iface_manager,
1208            test_values.update_sender,
1209            saved_networks.clone(),
1210            test_values.scan_requester,
1211            test_values.client_provider_lock,
1212            test_values.requests,
1213            test_values.telemetry_sender,
1214        );
1215        let mut serve_fut = pin!(serve_fut);
1216
1217        // No request has been sent yet. Future should be idle.
1218        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1219
1220        // Request a new controller.
1221        let (controller, _update_stream) = request_controller(&test_values.provider);
1222        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1223        assert_matches!(
1224            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1225            Poll::Ready(_)
1226        );
1227
1228        // Create a network config whose password is too short. FIDL network config does not
1229        // require valid fields unlike our crate define config. We should not be able to
1230        // successfully save this network through the API.
1231        let bad_network_id = fidl_policy::NetworkIdentifier {
1232            ssid: b"foo".to_vec(),
1233            type_: fidl_policy::SecurityType::Wpa2,
1234        };
1235        let network_config = fidl_policy::NetworkConfig {
1236            id: Some(bad_network_id.clone()),
1237            credential: Some(fidl_policy::Credential::Password(b"bar".to_vec())),
1238            ..Default::default()
1239        };
1240        // Attempt to save the config
1241        let mut save_fut = controller.save_network(&network_config);
1242
1243        // Run server_provider forward so that it will process the save network request
1244        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1245
1246        // Check that the the response says we failed to save the network.
1247        assert_matches!(exec.run_until_stalled(&mut save_fut), Poll::Ready(result) => {
1248            let error = result.expect("Failed to get save network response");
1249            assert_eq!(error, Err(fidl_policy::NetworkConfigChangeError::NetworkConfigWriteError));
1250        });
1251
1252        // Check that the value was was not saved in saved networks manager.
1253        let target_id = NetworkIdentifier::from(bad_network_id);
1254        assert_eq!(exec.run_singlethreaded(saved_networks.lookup(&target_id)), vec![]);
1255    }
1256
1257    #[fuchsia::test]
1258    fn test_remove_a_network() {
1259        let mut exec = fasync::TestExecutor::new();
1260        let mut test_values = test_setup();
1261
1262        let serve_fut = serve_provider_requests(
1263            test_values.iface_manager,
1264            test_values.update_sender,
1265            test_values.saved_networks.clone(),
1266            test_values.scan_requester,
1267            test_values.client_provider_lock,
1268            test_values.requests,
1269            test_values.telemetry_sender,
1270        );
1271        let mut serve_fut = pin!(serve_fut);
1272
1273        // No request has been sent yet. Future should be idle.
1274        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1275
1276        // Request a new controller.
1277        let (controller, _update_stream) = request_controller(&test_values.provider);
1278        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1279        assert_matches!(
1280            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1281            Poll::Ready(_)
1282        );
1283
1284        // Request to a network that is saved
1285        let network_config = fidl_policy::NetworkConfig {
1286            id: Some(test_values.net_id_open.clone()),
1287            credential: Some(fidl_policy::Credential::None(fidl_policy::Empty)),
1288            ..Default::default()
1289        };
1290        let mut remove_fut = controller.remove_network(&network_config);
1291
1292        // Process the remove request on the server side and handle requests to stash on the way.
1293        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1294        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1295
1296        // Successfully removing a network should always request a disconnect from IfaceManager,
1297        // which will know whether we are connected to the network to disconnect from. This checks
1298        // that the IfaceManager is told to disconnect (if connected).
1299        assert_matches!(exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()), Poll::Ready(Some(IfaceManagerRequest::Disconnect(net_id, reason))) => {
1300            assert_eq!(net_id, test_values.net_id_open.clone().into());
1301            assert_eq!(reason, client_types::DisconnectReason::NetworkUnsaved);
1302        });
1303        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1304        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1305        assert!(
1306            exec.run_singlethreaded(
1307                test_values.saved_networks.lookup(&test_values.net_id_open.clone().into())
1308            )
1309            .is_empty()
1310        );
1311
1312        // Removing a network that is not saved should not trigger a disconnect.
1313        let mut remove_fut = controller.remove_network(&network_config);
1314        // Process the remove request on the server side and handle requests to stash on the way.
1315        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1316        assert_matches!(
1317            exec.run_until_stalled(&mut test_values.iface_mgr_req_recvr.next()),
1318            Poll::Pending
1319        );
1320        assert_matches!(exec.run_until_stalled(&mut remove_fut), Poll::Ready(Ok(Ok(()))));
1321    }
1322
1323    #[fuchsia::test]
1324    fn test_get_saved_network() {
1325        let expected_configs = vec![generate_random_fidl_network_config()];
1326        let expected_num_sends = 1;
1327        run_get_saved_networks_test(expected_configs, expected_num_sends);
1328    }
1329
1330    #[fuchsia::test]
1331    fn test_get_saved_networks_multiple_chunks() {
1332        // Save MAX_CONFIGS_PER_RESPONSE + 1 configs so that get_saved_networks should respond with
1333        // 2 chunks of responses plus one response with an empty vector.
1334        let mut configs = vec![];
1335        for index in 0..MAX_CONFIGS_PER_RESPONSE + 1 {
1336            // Create unique network config to be saved.
1337            let ssid = format!("some_config{index}");
1338            let network_config = generate_random_fidl_network_config_with_ssid(&ssid);
1339            configs.push(network_config);
1340        }
1341
1342        let expected_num_sends = 2;
1343        run_get_saved_networks_test(configs, expected_num_sends);
1344    }
1345
1346    /// Test that get saved networks with the given saved networks
1347    /// test_id: the name of the test to create a unique persistent store for each test
1348    /// configs: list of FIDL NetworkConfigs that we expect to get from get_saved_networks and
1349    ///          and which are returned by SavedNetworksManager
1350    /// expected_num_sends: number of chunks of results we expect to get from get_saved_networks.
1351    ///     This is not counting the empty vector that signifies no more results.
1352    fn run_get_saved_networks_test(
1353        configs: Vec<fidl_policy::NetworkConfig>,
1354        expected_num_sends: usize,
1355    ) {
1356        let mut exec = fasync::TestExecutor::new();
1357        let saved_networks =
1358            Arc::new(FakeSavedNetworksManager::new_with_saved_networks(configs.clone()));
1359
1360        let test_values = test_setup();
1361        let serve_fut = serve_provider_requests(
1362            test_values.iface_manager,
1363            test_values.update_sender,
1364            saved_networks.clone(),
1365            test_values.scan_requester,
1366            test_values.client_provider_lock,
1367            test_values.requests,
1368            test_values.telemetry_sender,
1369        );
1370        let mut serve_fut = pin!(serve_fut);
1371
1372        // No request has been sent yet. Future should be idle.
1373        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1374
1375        // Request a new controller.
1376        let (controller, _update_stream) = request_controller(&test_values.provider);
1377        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1378
1379        // Issue request to get the list of saved networks.
1380        let (iter, server) =
1381            fidl::endpoints::create_proxy::<fidl_policy::NetworkConfigIteratorMarker>();
1382        controller.get_saved_networks(server).expect("Failed to call get saved networks");
1383
1384        // Get responses from iterator. Expect to see the specified number of responses with
1385        // results plus one response of an empty vector indicating the end of results.
1386        let mut saved_networks_results = vec![];
1387        for i in 0..expected_num_sends {
1388            let get_saved_fut = iter.get_next();
1389            assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1390            let results = exec
1391                .run_singlethreaded(get_saved_fut)
1392                .expect("Failed to get next chunk of saved networks results");
1393            // the size of received chunk should either be max chunk size or whatever is left
1394            // to receive in the last chunk
1395            if i < expected_num_sends - 1 {
1396                assert_eq!(results.len(), MAX_CONFIGS_PER_RESPONSE);
1397            } else {
1398                assert_eq!(results.len(), configs.len() % MAX_CONFIGS_PER_RESPONSE);
1399            }
1400            saved_networks_results.extend(results);
1401        }
1402        let get_saved_end_fut = iter.get_next();
1403        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1404        let results = exec
1405            .run_singlethreaded(get_saved_end_fut)
1406            .expect("Failed to get next chunk of saved networks results");
1407        assert!(results.is_empty());
1408
1409        // check whether each network we saved is in the results and that nothing else is there.
1410        for network_config in &configs {
1411            assert!(saved_networks_results.contains(network_config));
1412        }
1413        assert_eq!(configs.len(), saved_networks_results.len());
1414    }
1415
1416    #[fuchsia::test]
1417    fn register_update_listener() {
1418        let mut exec = fasync::TestExecutor::new();
1419        let mut test_values = test_setup();
1420        let serve_fut = serve_provider_requests(
1421            test_values.iface_manager,
1422            test_values.update_sender,
1423            test_values.saved_networks,
1424            test_values.scan_requester,
1425            test_values.client_provider_lock,
1426            test_values.requests,
1427            test_values.telemetry_sender,
1428        );
1429        let mut serve_fut = pin!(serve_fut);
1430
1431        // No request has been sent yet. Future should be idle.
1432        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1433
1434        // Request a new controller.
1435        let (_controller, _update_stream) = request_controller(&test_values.provider);
1436        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1437        assert_matches!(
1438            exec.run_until_stalled(&mut test_values.listener_updates.next()),
1439            Poll::Ready(Some(listener::Message::NewListener(_)))
1440        );
1441    }
1442
1443    #[fuchsia::test]
1444    fn get_listener() {
1445        let mut exec = fasync::TestExecutor::new();
1446        let (listener, requests) = create_proxy::<fidl_policy::ClientListenerMarker>();
1447        let requests = requests.into_stream();
1448
1449        let (update_sender, mut listener_updates) = mpsc::unbounded();
1450        let serve_fut = serve_listener_requests(update_sender, requests);
1451        let mut serve_fut = pin!(serve_fut);
1452
1453        // No request has been sent yet. Future should be idle.
1454        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1455
1456        // Register listener.
1457        let (update_sink, _update_stream) =
1458            create_request_stream::<fidl_policy::ClientStateUpdatesMarker>();
1459        listener.get_listener(update_sink).expect("error getting listener");
1460
1461        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1462        assert_matches!(
1463            exec.run_until_stalled(&mut listener_updates.next()),
1464            Poll::Ready(Some(listener::Message::NewListener(_)))
1465        );
1466    }
1467
1468    #[fuchsia::test]
1469    fn multiple_controllers_write_attempt() {
1470        let mut exec = fasync::TestExecutor::new();
1471        let test_values = test_setup();
1472        let serve_fut = serve_provider_requests(
1473            test_values.iface_manager,
1474            test_values.update_sender,
1475            test_values.saved_networks,
1476            test_values.scan_requester,
1477            test_values.client_provider_lock,
1478            test_values.requests,
1479            test_values.telemetry_sender,
1480        );
1481        let mut serve_fut = pin!(serve_fut);
1482
1483        // No request has been sent yet. Future should be idle.
1484        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1485
1486        // Request a controller.
1487        let (controller1, _) = request_controller(&test_values.provider);
1488        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1489
1490        // Request another controller.
1491        let (controller2, _) = request_controller(&test_values.provider);
1492        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1493
1494        // Ensure first controller is operable. Issue connect request.
1495        let connect_fut = controller1.connect(&test_values.net_id_open);
1496        let mut connect_fut = pin!(connect_fut);
1497
1498        // Process connect request from first controller. Verify success.
1499        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1500
1501        assert_matches!(
1502            exec.run_until_stalled(&mut connect_fut),
1503            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1504        );
1505
1506        // Ensure second controller is not operable. Issue connect request.
1507        let connect_fut = controller2.connect(&test_values.net_id_open);
1508        let mut connect_fut = pin!(connect_fut);
1509
1510        // Process connect request from second controller. Verify failure.
1511        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1512        assert_matches!(
1513            exec.run_until_stalled(&mut connect_fut),
1514            Poll::Ready(Err(fidl::Error::ClientChannelClosed {
1515                status: zx::Status::ALREADY_BOUND,
1516                ..
1517            }))
1518        );
1519
1520        // Drop first controller. A new controller can now take control.
1521        drop(controller1);
1522        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1523
1524        // Request another controller.
1525        let (controller3, _) = request_controller(&test_values.provider);
1526        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1527
1528        // Ensure third controller is operable. Issue connect request.
1529        let connect_fut = controller3.connect(&test_values.net_id_open);
1530        let mut connect_fut = pin!(connect_fut);
1531
1532        // Process connect request from third controller. Verify success.
1533        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1534
1535        assert_matches!(
1536            exec.run_until_stalled(&mut connect_fut),
1537            Poll::Ready(Ok(fidl_policy::RequestStatus::Acknowledged))
1538        );
1539    }
1540
1541    #[fuchsia::test]
1542    fn multiple_controllers_epitaph() {
1543        let mut exec = fasync::TestExecutor::new();
1544        let test_values = test_setup();
1545        let serve_fut = serve_provider_requests(
1546            test_values.iface_manager,
1547            test_values.update_sender,
1548            test_values.saved_networks.clone(),
1549            test_values.scan_requester,
1550            test_values.client_provider_lock,
1551            test_values.requests,
1552            test_values.telemetry_sender,
1553        );
1554        let mut serve_fut = pin!(serve_fut);
1555
1556        // No request has been sent yet. Future should be idle.
1557        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1558
1559        // Request a controller.
1560        let (_controller1, _) = request_controller(&test_values.provider);
1561        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1562
1563        // Request another controller.
1564        let (controller2, _) = request_controller(&test_values.provider);
1565        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1566
1567        // Verify Epitaph was received.
1568        let mut controller2_event_stream = controller2.take_event_stream();
1569        let controller2_event_fut = controller2_event_stream.next();
1570        let mut controller2_event_fut = pin!(controller2_event_fut);
1571        assert_matches!(
1572            exec.run_until_stalled(&mut controller2_event_fut),
1573            Poll::Ready(Some(Err(fidl::Error::ClientChannelClosed {
1574                status: zx::Status::ALREADY_BOUND,
1575                ..
1576            })))
1577        );
1578        assert!(controller2.is_closed());
1579    }
1580
1581    struct FakeIfaceManagerNoIfaces {}
1582
1583    #[async_trait(?Send)]
1584    impl IfaceManagerApi for FakeIfaceManagerNoIfaces {
1585        async fn disconnect(
1586            &mut self,
1587            _network_id: client_types::NetworkIdentifier,
1588            _reason: client_types::DisconnectReason,
1589        ) -> Result<(), Error> {
1590            Err(format_err!("No ifaces"))
1591        }
1592
1593        async fn connect(&mut self, _connect_req: ConnectAttemptRequest) -> Result<(), Error> {
1594            Err(format_err!("No ifaces"))
1595        }
1596
1597        async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
1598            unimplemented!()
1599        }
1600
1601        async fn has_idle_client(&mut self) -> Result<bool, Error> {
1602            unimplemented!()
1603        }
1604
1605        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1606            unimplemented!()
1607        }
1608
1609        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
1610            unimplemented!()
1611        }
1612
1613        async fn get_sme_proxy_for_scan(&mut self) -> Result<SmeForScan, Error> {
1614            Err(format_err!("No ifaces"))
1615        }
1616
1617        async fn stop_client_connections(
1618            &mut self,
1619            _reason: client_types::DisconnectReason,
1620        ) -> Result<(), Error> {
1621            unimplemented!()
1622        }
1623
1624        async fn start_client_connections(&mut self) -> Result<(), Error> {
1625            unimplemented!()
1626        }
1627
1628        async fn start_ap(
1629            &mut self,
1630            _config: ap_fsm::ApConfig,
1631        ) -> Result<oneshot::Receiver<()>, Error> {
1632            unimplemented!()
1633        }
1634
1635        async fn stop_ap(&mut self, _ssid: types::Ssid, _password: Vec<u8>) -> Result<(), Error> {
1636            unimplemented!()
1637        }
1638
1639        async fn stop_all_aps(&mut self) -> Result<(), Error> {
1640            unimplemented!()
1641        }
1642
1643        async fn set_country(
1644            &mut self,
1645            _country_code: Option<types::CountryCode>,
1646        ) -> Result<(), Error> {
1647            unimplemented!()
1648        }
1649    }
1650
1651    #[fuchsia::test]
1652    fn no_client_interface() {
1653        let mut exec = fasync::TestExecutor::new();
1654        let test_values = test_setup();
1655
1656        let iface_manager = Arc::new(Mutex::new(FakeIfaceManagerNoIfaces {}));
1657
1658        let serve_fut = serve_provider_requests(
1659            iface_manager,
1660            test_values.update_sender,
1661            test_values.saved_networks,
1662            test_values.scan_requester,
1663            test_values.client_provider_lock,
1664            test_values.requests,
1665            test_values.telemetry_sender,
1666        );
1667        let mut serve_fut = pin!(serve_fut);
1668
1669        // No request has been sent yet. Future should be idle.
1670        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1671
1672        // Request a controller.
1673        let (controller, _) = request_controller(&test_values.provider);
1674        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1675
1676        // Issue connect request.
1677        let connect_fut = controller.connect(&test_values.net_id_open);
1678        let mut connect_fut = pin!(connect_fut);
1679
1680        // Process connect request from first controller. Verify success.
1681        assert_matches!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
1682        assert_matches!(
1683            exec.run_until_stalled(&mut connect_fut),
1684            Poll::Ready(Ok(fidl_policy::RequestStatus::RejectedIncompatibleMode))
1685        );
1686    }
1687
1688    // Gets a saved network config with a particular SSID, security type, and credential.
1689    // If there are more than one configs saved for the same SSID, security type, and credential,
1690    // the function will panic.
1691    async fn get_config(
1692        saved_networks: Arc<dyn SavedNetworksManagerApi>,
1693        id: NetworkIdentifier,
1694        cred: Credential,
1695    ) -> Option<NetworkConfig> {
1696        let mut cfgs = saved_networks
1697            .lookup(&id)
1698            .await
1699            .into_iter()
1700            .filter(|cfg| cfg.credential == cred)
1701            .collect::<Vec<_>>();
1702        // there should not be multiple configs with the same SSID, security type, and credential.
1703        assert!(cfgs.len() <= 1);
1704        cfgs.pop()
1705    }
1706
1707    #[fuchsia::test]
1708    async fn get_correct_config() {
1709        let saved_networks = Arc::new(FakeSavedNetworksManager::new());
1710        let network_id = NetworkIdentifier::try_from("foo", SecurityType::Wpa2).unwrap();
1711        let cfg = NetworkConfig::new(
1712            network_id.clone(),
1713            Credential::Password(b"password".to_vec()),
1714            false,
1715            None,
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}