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