// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::{
        access_point::{state_machine as ap_fsm, state_machine::AccessPointApi, types as ap_types},
        client::{
            network_selection::NetworkSelector, state_machine as client_fsm, types as client_types,
        },
        config_management::SavedNetworksManagerApi,
        mode_management::{
            iface_manager_api::IfaceManagerApi,
            iface_manager_types::*,
            phy_manager::{CreateClientIfacesReason, PhyManagerApi},
        },
        util::{future_with_metadata, listener},
    },
    anyhow::{format_err, Error},
    fidl::endpoints::create_proxy,
    fidl_fuchsia_wlan_common, fidl_fuchsia_wlan_device, fidl_fuchsia_wlan_policy,
    fidl_fuchsia_wlan_sme, fuchsia_async as fasync,
    fuchsia_cobalt::CobaltSender,
    fuchsia_zircon as zx,
    futures::{
        channel::{mpsc, oneshot},
        future::{ready, BoxFuture},
        lock::Mutex,
        select,
        stream::FuturesUnordered,
        FutureExt, StreamExt,
    },
    log::{error, info, warn},
    std::{sync::Arc, unimplemented},
    void::Void,
    wlan_metrics_registry,
};

// Maximum allowed interval between scans when attempting to reconnect client interfaces.  This
// value is taken from legacy state machine.
const MAX_AUTO_CONNECT_RETRY_SECONDS: i64 = 10;

/// Wraps around vital information associated with a WLAN client interface.  In all cases, a client
/// interface will have an ID and a ClientSmeProxy to make requests of the interface.  If a client
/// is configured to connect to a WLAN network, it will store the network configuration information
/// associated with that network as well as a communcation channel to make requests of the state
/// machine that maintains client connectivity.
struct ClientIfaceContainer {
    iface_id: u16,
    sme_proxy: fidl_fuchsia_wlan_sme::ClientSmeProxy,
    config: Option<ap_types::NetworkIdentifier>,
    client_state_machine: Option<Box<dyn client_fsm::ClientApi + Send>>,
    driver_features: Vec<fidl_fuchsia_wlan_common::DriverFeature>,
}

pub(crate) struct ApIfaceContainer {
    pub iface_id: u16,
    pub config: Option<ap_fsm::ApConfig>,
    pub ap_state_machine: Box<dyn AccessPointApi + Send + Sync>,
    enabled_time: Option<zx::Time>,
}

#[derive(Clone, Debug)]
pub struct StateMachineMetadata {
    pub iface_id: u16,
    pub role: fidl_fuchsia_wlan_device::MacRole,
}

async fn create_client_state_machine(
    iface_id: u16,
    dev_svc_proxy: &mut fidl_fuchsia_wlan_device_service::DeviceServiceProxy,
    client_update_sender: listener::ClientListenerMessageSender,
    saved_networks: Arc<dyn SavedNetworksManagerApi>,
    network_selector: Arc<NetworkSelector>,
    connect_req: Option<(client_types::ConnectRequest, oneshot::Sender<()>)>,
    cobalt_api: CobaltSender,
) -> Result<
    (
        Box<dyn client_fsm::ClientApi + Send>,
        future_with_metadata::FutureWithMetadata<(), StateMachineMetadata>,
    ),
    Error,
> {
    // Create a client state machine for the newly discovered interface.
    let (sender, receiver) = mpsc::channel(1);
    let new_client = client_fsm::Client::new(sender);

    // Create a new client SME proxy.  This is required because each new client state machine will
    // take the event stream from the SME proxy.  A subsequent attempt to take the event stream
    // would cause wlancfg to panic.
    let (sme_proxy, remote) = create_proxy()?;
    let status = dev_svc_proxy.get_client_sme(iface_id, remote).await?;
    fuchsia_zircon::ok(status)?;
    let event_stream = sme_proxy.take_event_stream();

    let fut = client_fsm::serve(
        iface_id,
        sme_proxy,
        event_stream,
        receiver,
        client_update_sender,
        saved_networks,
        connect_req,
        network_selector,
        cobalt_api,
    );

    let metadata =
        StateMachineMetadata { iface_id, role: fidl_fuchsia_wlan_device::MacRole::Client };
    let fut = future_with_metadata::FutureWithMetadata::new(metadata, Box::pin(fut));

    Ok((Box::new(new_client), fut))
}

/// Accounts for WLAN interfaces that are present and utilizes them to service requests that are
/// made of the policy layer.
pub(crate) struct IfaceManagerService {
    phy_manager: Arc<Mutex<dyn PhyManagerApi + Send>>,
    client_update_sender: listener::ClientListenerMessageSender,
    ap_update_sender: listener::ApListenerMessageSender,
    dev_svc_proxy: fidl_fuchsia_wlan_device_service::DeviceServiceProxy,
    clients: Vec<ClientIfaceContainer>,
    aps: Vec<ApIfaceContainer>,
    saved_networks: Arc<dyn SavedNetworksManagerApi>,
    network_selector: Arc<NetworkSelector>,
    fsm_futures:
        FuturesUnordered<future_with_metadata::FutureWithMetadata<(), StateMachineMetadata>>,
    cobalt_api: CobaltSender,
    clients_enabled_time: Option<zx::Time>,
}

impl IfaceManagerService {
    pub fn new(
        phy_manager: Arc<Mutex<dyn PhyManagerApi + Send>>,
        client_update_sender: listener::ClientListenerMessageSender,
        ap_update_sender: listener::ApListenerMessageSender,
        dev_svc_proxy: fidl_fuchsia_wlan_device_service::DeviceServiceProxy,
        saved_networks: Arc<dyn SavedNetworksManagerApi>,
        network_selector: Arc<NetworkSelector>,
        cobalt_api: CobaltSender,
    ) -> Self {
        IfaceManagerService {
            phy_manager: phy_manager.clone(),
            client_update_sender,
            ap_update_sender,
            dev_svc_proxy,
            clients: Vec::new(),
            aps: Vec::new(),
            saved_networks: saved_networks,
            network_selector,
            fsm_futures: FuturesUnordered::new(),
            cobalt_api,
            clients_enabled_time: None,
        }
    }

    /// Checks for any known, unconfigured clients.  If one exists, its ClientIfaceContainer is
    /// returned to the caller.
    ///
    /// If all ifaces are configured, asks the PhyManager for an iface ID.  If the returned iface
    /// ID is an already-configured iface, that iface is removed from the configured clients list
    /// and returned to the caller.
    ///
    /// If it is not, a new ClientIfaceContainer is created from the returned iface ID and returned
    /// to the caller.
    async fn get_client(&mut self, iface_id: Option<u16>) -> Result<ClientIfaceContainer, Error> {
        let iface_id = match iface_id {
            Some(iface_id) => iface_id,
            None => {
                // If no iface_id is specified and if there there are any unconfigured client
                // ifaces, use the first available unconfigured iface.
                if let Some(removal_index) = self
                    .clients
                    .iter()
                    .position(|client_container| client_container.config.is_none())
                {
                    return Ok(self.clients.remove(removal_index));
                }

                // If all of the known client ifaces are configured, ask the PhyManager for a
                // client iface.
                match self.phy_manager.lock().await.get_client() {
                    None => return Err(format_err!("no client ifaces available")),
                    Some(id) => id,
                }
            }
        };
        self.setup_client_container(iface_id).await
    }

    async fn get_wpa3_capable_client(
        &mut self,
        iface_id: Option<u16>,
    ) -> Result<ClientIfaceContainer, Error> {
        let iface_id = match iface_id {
            Some(iface_id) => iface_id,
            None => {
                // If no iface_id is specified and if there there are any unconfigured client
                // ifaces, use the first available unconfigured iface.
                if let Some(removal_index) = self.clients.iter().position(|client_container| {
                    client_container.config.is_none()
                        && wpa3_in_features(&client_container.driver_features)
                }) {
                    return Ok(self.clients.remove(removal_index));
                }

                // If all of the known client ifaces are configured, ask the PhyManager for a
                // client iface.
                match self.phy_manager.lock().await.get_wpa3_capable_client() {
                    None => return Err(format_err!("no client ifaces available")),
                    Some(id) => id,
                }
            }
        };

        self.setup_client_container(iface_id).await
    }

    /// Remove the client iface from the list of configured ifaces if it is there, and create a
    /// ClientIfaceContainer for it if it is needed.
    async fn setup_client_container(
        &mut self,
        iface_id: u16,
    ) -> Result<ClientIfaceContainer, Error> {
        // See if the selected iface ID is among the configured clients.
        if let Some(removal_index) =
            self.clients.iter().position(|client_container| client_container.iface_id == iface_id)
        {
            return Ok(self.clients.remove(removal_index));
        }

        // If the iface ID is not among configured clients, create a new ClientIfaceContainer for
        // the iface ID.
        let (sme_proxy, remote) = create_proxy()?;
        let status = self.dev_svc_proxy.get_client_sme(iface_id, remote).await?;
        fuchsia_zircon::ok(status)?;

        // Get the driver features for this iface.
        let (status, iface_info) = self.dev_svc_proxy.query_iface(iface_id).await?;
        fuchsia_zircon::ok(status)?;
        let iface_info = iface_info
            .ok_or_else(|| format_err!("Error occurred getting iface's driver features"))?;

        Ok(ClientIfaceContainer {
            iface_id: iface_id,
            sme_proxy,
            config: None,
            client_state_machine: None,
            driver_features: iface_info.driver_features,
        })
    }

    /// Queries to PhyManager to determine if there are any interfaces that can be used as AP's.
    ///
    /// If the PhyManager indicates that there is an existing interface that should be used for the
    /// AP request, return the existing AP interface.
    ///
    /// If the indicated AP interface has not been used before, spawn a new AP state machine for
    /// the interface and return the new interface.
    async fn get_ap(&mut self, iface_id: Option<u16>) -> Result<ApIfaceContainer, Error> {
        let iface_id = match iface_id {
            Some(iface_id) => iface_id,
            None => {
                // If no iface ID is specified, ask the PhyManager for an AP iface ID.
                let mut phy_manager = self.phy_manager.lock().await;
                match phy_manager.create_or_get_ap_iface().await {
                    Ok(Some(iface_id)) => iface_id,
                    Ok(None) => return Err(format_err!("no available PHYs can support AP ifaces")),
                    phy_manager_error => {
                        return Err(format_err!("could not get AP {:?}", phy_manager_error));
                    }
                }
            }
        };

        // Check if this iface ID is already accounted for.
        if let Some(removal_index) =
            self.aps.iter().position(|ap_container| ap_container.iface_id == iface_id)
        {
            return Ok(self.aps.remove(removal_index));
        }

        // If this iface ID is not yet accounted for, create a new ApIfaceContainer.
        let (sme_proxy, remote) = create_proxy()?;
        let status = self.dev_svc_proxy.get_ap_sme(iface_id, remote).await?;
        fuchsia_zircon::ok(status)?;

        // Spawn the AP state machine.
        let (sender, receiver) = mpsc::channel(1);
        let state_machine = ap_fsm::AccessPoint::new(sender);

        let event_stream = sme_proxy.take_event_stream();
        let state_machine_fut = ap_fsm::serve(
            iface_id,
            sme_proxy,
            event_stream,
            receiver,
            self.ap_update_sender.clone(),
        )
        .boxed();

        // Begin running and monitoring the AP state machine future.
        let metadata = StateMachineMetadata {
            iface_id: iface_id,
            role: fidl_fuchsia_wlan_device::MacRole::Ap,
        };
        let fut = future_with_metadata::FutureWithMetadata::new(metadata, state_machine_fut);
        self.fsm_futures.push(fut);

        Ok(ApIfaceContainer {
            iface_id: iface_id,
            config: None,
            ap_state_machine: Box::new(state_machine),
            enabled_time: None,
        })
    }

    /// Attempts to stop the AP and then exit the AP state machine.
    async fn stop_and_exit_ap_state_machine(
        mut ap_state_machine: Box<dyn AccessPointApi + Send + Sync>,
    ) -> Result<(), Error> {
        let (sender, receiver) = oneshot::channel();
        ap_state_machine.stop(sender)?;
        receiver.await?;

        let (sender, receiver) = oneshot::channel();
        ap_state_machine.exit(sender)?;
        receiver.await?;

        Ok(())
    }

    fn disconnect(
        &mut self,
        network_id: ap_types::NetworkIdentifier,
        reason: client_types::DisconnectReason,
    ) -> BoxFuture<'static, Result<(), Error>> {
        // Find the client interface associated with the given network config and disconnect from
        // the network.
        let mut fsm_ack_receiver = None;
        let mut iface_id = None;

        // If a client is configured for the specified network, tell the state machine to
        // disconnect.  This will cause the state machine's future to exit so that the monitoring
        // loop discovers the completed future and attempts to reconnect the interface.
        for client in self.clients.iter_mut() {
            if client.config.as_ref() == Some(&network_id) {
                client.config = None;

                let (responder, receiver) = oneshot::channel();
                match client.client_state_machine.as_mut() {
                    Some(state_machine) => match state_machine.disconnect(reason, responder) {
                        Ok(()) => {}
                        Err(e) => {
                            client.client_state_machine = None;

                            return ready(Err(format_err!("failed to send disconnect: {:?}", e)))
                                .boxed();
                        }
                    },
                    None => {
                        return ready(Ok(())).boxed();
                    }
                }

                client.config = None;
                client.client_state_machine = None;
                fsm_ack_receiver = Some(receiver);
                iface_id = Some(client.iface_id);
                break;
            }
        }

        let receiver = match fsm_ack_receiver {
            Some(receiver) => receiver,
            None => return ready(Ok(())).boxed(),
        };
        let iface_id = match iface_id {
            Some(iface_id) => iface_id,
            None => return ready(Ok(())).boxed(),
        };

        let fut = async move {
            match receiver.await {
                Ok(()) => return Ok(()),
                error => {
                    Err(format_err!("failed to disconnect client iface {}: {:?}", iface_id, error))
                }
            }
        };
        return fut.boxed();
    }

    async fn connect(
        &mut self,
        connect_req: client_types::ConnectRequest,
    ) -> Result<oneshot::Receiver<()>, Error> {
        // Get a ClientIfaceContainer.
        let mut client_iface =
            if connect_req.target.network.type_ == client_types::SecurityType::Wpa3 {
                self.get_wpa3_capable_client(None).await?
            } else {
                self.get_client(None).await?
            };

        // Set the new config on this client
        client_iface.config = Some(connect_req.target.network.clone());

        // Create the connection request
        let (sender, receiver) = oneshot::channel();

        // Check if there's an existing state machine we can use
        match client_iface.client_state_machine.as_mut() {
            Some(existing_csm) => {
                existing_csm.connect(connect_req, sender)?;
            }
            None => {
                // Create the state machine and controller.
                let (new_client, fut) = create_client_state_machine(
                    client_iface.iface_id,
                    &mut self.dev_svc_proxy,
                    self.client_update_sender.clone(),
                    self.saved_networks.clone(),
                    self.network_selector.clone(),
                    Some((connect_req, sender)),
                    self.cobalt_api.clone(),
                )
                .await?;
                client_iface.client_state_machine = Some(new_client);

                // Begin running and monitoring the client state machine future.
                self.fsm_futures.push(fut);
            }
        }

        self.clients.push(client_iface);
        Ok(receiver)
    }

    fn record_idle_client(&mut self, iface_id: u16) {
        for client in self.clients.iter_mut() {
            if client.iface_id == iface_id {
                // Check if the state machine has exited.  If it has not, then another call to
                // connect has replaced the state machine already and this interface should be left
                // alone.
                match client.client_state_machine.as_ref() {
                    Some(state_machine) => {
                        if state_machine.is_alive() {
                            return;
                        }
                    }
                    None => {}
                }
                client.config = None;
                client.client_state_machine = None;
                return;
            }
        }
    }

    fn idle_clients(&self) -> Vec<u16> {
        let mut idle_clients = Vec::new();

        for client in self.clients.iter() {
            if client.config.is_none() {
                idle_clients.push(client.iface_id);
                continue;
            }

            match client.client_state_machine.as_ref() {
                Some(state_machine) => {
                    if !state_machine.is_alive() {
                        idle_clients.push(client.iface_id);
                    }
                }
                None => idle_clients.push(client.iface_id),
            }
        }

        idle_clients
    }

    /// Checks the specified interface to see if there is an active state machine for it.  If there
    /// is, this indicates that a connect request has already reconnected this interface and no
    /// further action is required.  If no state machine exists for the interface, attempts to
    /// connect the interface to the specified network.
    async fn attempt_client_reconnect(
        &mut self,
        iface_id: u16,
        connect_req: client_types::ConnectRequest,
    ) -> Result<(), Error> {
        for client in self.clients.iter_mut() {
            if client.iface_id == iface_id {
                match client.client_state_machine.as_ref() {
                    None => {}
                    Some(state_machine) => {
                        if state_machine.is_alive() {
                            return Ok(());
                        }
                    }
                }

                // Create the state machine and controller.
                let (sender, _) = oneshot::channel();
                let (new_client, fut) = create_client_state_machine(
                    client.iface_id,
                    &mut self.dev_svc_proxy,
                    self.client_update_sender.clone(),
                    self.saved_networks.clone(),
                    self.network_selector.clone(),
                    Some((connect_req.clone(), sender)),
                    self.cobalt_api.clone(),
                )
                .await?;

                self.fsm_futures.push(fut);
                client.config = Some(connect_req.target.network);
                client.client_state_machine = Some(new_client);
                break;
            }
        }

        Ok(())
    }

    async fn handle_added_iface(&mut self, iface_id: u16) -> Result<(), Error> {
        let (status, iface_info) = self.dev_svc_proxy.query_iface(iface_id).await?;
        fuchsia_zircon::ok(status)?;
        let iface_info = match iface_info {
            Some(iface_info) => iface_info,
            None => return Err(format_err!("no iface information available for {:?}", iface_id)),
        };

        match iface_info.role {
            fidl_fuchsia_wlan_device::MacRole::Client => {
                // If this client has already been recorded, take no action.
                for client in self.clients.iter() {
                    if client.iface_id == iface_id {
                        return Ok(());
                    }
                }

                let mut client_iface = self.get_client(Some(iface_id)).await?;

                // Create the state machine and controller.  The state machine is setup with no
                // initial network config.  This will cause it to quickly exit, notifying the
                // monitor loop that the interface needs attention.
                let (new_client, fut) = create_client_state_machine(
                    client_iface.iface_id,
                    &mut self.dev_svc_proxy,
                    self.client_update_sender.clone(),
                    self.saved_networks.clone(),
                    self.network_selector.clone(),
                    None,
                    self.cobalt_api.clone(),
                )
                .await?;

                // Begin running and monitoring the client state machine future.
                self.fsm_futures.push(fut);

                client_iface.client_state_machine = Some(new_client);
                self.clients.push(client_iface);
            }
            fidl_fuchsia_wlan_device::MacRole::Ap => {
                let ap_iface = self.get_ap(Some(iface_id)).await?;
                self.aps.push(ap_iface);
            }
            fidl_fuchsia_wlan_device::MacRole::Mesh => {
                // Mesh roles are not currently supported.
            }
        }

        Ok(())
    }

    async fn handle_removed_iface(&mut self, iface_id: u16) {
        // Delete the reference from the PhyManager.
        self.phy_manager.lock().await.on_iface_removed(iface_id);

        // If the interface was deleted, but IfaceManager still has a reference to it, then the
        // driver has likely performed some low-level recovery or the interface driver has crashed.
        // In this case, remove the old reference to the interface ID and then create a new
        // interface of the appropriate type.
        if let Some(iface_index) =
            self.clients.iter().position(|client_container| client_container.iface_id == iface_id)
        {
            let _ = self.clients.remove(iface_index);
            let client_ifaces = match self
                .phy_manager
                .lock()
                .await
                .create_all_client_ifaces(CreateClientIfacesReason::RecoverClientIfaces)
                .await
            {
                Ok(iface_ids) => iface_ids,
                Err((iface_ids, e)) => {
                    warn!("failed to recover some client interfaces: {:?}", e);
                    iface_ids
                }
            };

            for iface_id in client_ifaces {
                match self.get_client(Some(iface_id)).await {
                    Ok(iface) => self.clients.push(iface),
                    Err(e) => {
                        error!("failed to recreate client {}: {:?}", iface_id, e);
                    }
                };
            }
        }

        // While client behavior is automated based on saved network configs and available SSIDs
        // observed in scan results, the AP behavior is largely controlled by API clients.  The AP
        // state machine will send back a failure notification in the event that the interface was
        // destroyed unexpectedly.  For the AP, simply remove the reference to the interface.  If
        // the API client so desires, they may ask the policy layer to start another AP interface.
        self.aps.retain(|ap_container| ap_container.iface_id != iface_id);
    }

    async fn scan(
        &mut self,
        mut scan_request: fidl_fuchsia_wlan_sme::ScanRequest,
    ) -> Result<fidl_fuchsia_wlan_sme::ScanTransactionProxy, Error> {
        let client_iface = self.get_client(None).await?;

        let (local, remote) = fidl::endpoints::create_proxy()?;
        let scan_result = client_iface.sme_proxy.scan(&mut scan_request, remote);

        self.clients.push(client_iface);

        match scan_result {
            Ok(()) => Ok(local),
            Err(e) => Err(format_err!("failed to scan: {:?}", e)),
        }
    }

    async fn get_sme_proxy_for_scan(
        &mut self,
    ) -> Result<fidl_fuchsia_wlan_sme::ClientSmeProxy, Error> {
        let client_iface = self.get_client(None).await?;
        let sme_proxy = client_iface.sme_proxy.clone();
        self.clients.push(client_iface);
        Ok(sme_proxy)
    }

    fn stop_client_connections(
        &mut self,
        reason: client_types::DisconnectReason,
    ) -> BoxFuture<'static, Result<(), Error>> {
        if let Some(start_time) = self.clients_enabled_time.take() {
            let elapsed_time = zx::Time::get_monotonic() - start_time;
            self.cobalt_api.log_elapsed_time(
                wlan_metrics_registry::CLIENT_CONNECTIONS_ENABLED_DURATION_METRIC_ID,
                (),
                elapsed_time.into_micros(),
            );
        }

        let client_ifaces: Vec<ClientIfaceContainer> = self.clients.drain(..).collect();
        let phy_manager = self.phy_manager.clone();
        let update_sender = self.client_update_sender.clone();

        let fut = async move {
            // Disconnect and discard all of the configured client ifaces.
            for mut client_iface in client_ifaces {
                let client = match client_iface.client_state_machine.as_mut() {
                    Some(state_machine) => state_machine,
                    None => continue,
                };
                let (responder, receiver) = oneshot::channel();
                match client.disconnect(reason, responder) {
                    Ok(()) => {}
                    Err(e) => error!("failed to issue disconnect: {:?}", e),
                }
                match receiver.await {
                    Ok(()) => {}
                    Err(e) => error!("failed to disconnect: {:?}", e),
                }
            }

            // Signal to the update listener that client connections have been disabled.
            let update = listener::ClientStateUpdate {
                state: Some(fidl_fuchsia_wlan_policy::WlanClientState::ConnectionsDisabled),
                networks: vec![],
            };
            if let Err(e) = update_sender.unbounded_send(listener::Message::NotifyListeners(update))
            {
                error!("Failed to send state update: {:?}", e)
            };

            // Tell the PhyManager to stop all client connections.
            let mut phy_manager = phy_manager.lock().await;
            phy_manager.destroy_all_client_ifaces().await?;

            Ok(())
        };

        fut.boxed()
    }

    async fn start_client_connections(&mut self) -> Result<(), Error> {
        let mut phy_manager = self.phy_manager.lock().await;
        match phy_manager
            .create_all_client_ifaces(CreateClientIfacesReason::StartClientConnections)
            .await
        {
            Ok(_) => {
                // Send an update to the update listener indicating that client connections are now
                // enabled.
                let update = listener::ClientStateUpdate {
                    state: Some(fidl_fuchsia_wlan_policy::WlanClientState::ConnectionsEnabled),
                    networks: vec![],
                };
                if let Err(e) = self
                    .client_update_sender
                    .unbounded_send(listener::Message::NotifyListeners(update))
                {
                    error!("Failed to send state update: {:?}", e)
                };
            }
            Err((_, phy_manager_error)) => {
                return Err(format_err!(
                    "could not start client connection {:?}",
                    phy_manager_error
                ));
            }
        }

        if self.clients_enabled_time.is_none() {
            self.clients_enabled_time = Some(zx::Time::get_monotonic());
        }
        Ok(())
    }

    async fn start_ap(&mut self, config: ap_fsm::ApConfig) -> Result<oneshot::Receiver<()>, Error> {
        let mut ap_iface_container = self.get_ap(None).await?;

        let (sender, receiver) = oneshot::channel();
        ap_iface_container.config = Some(config.clone());
        match ap_iface_container.ap_state_machine.start(config, sender) {
            Ok(()) => {
                if ap_iface_container.enabled_time.is_none() {
                    ap_iface_container.enabled_time = Some(zx::Time::get_monotonic());
                }

                self.aps.push(ap_iface_container)
            }
            Err(e) => {
                let mut phy_manager = self.phy_manager.lock().await;
                phy_manager.destroy_ap_iface(ap_iface_container.iface_id).await?;
                return Err(format_err!("could not start ap: {}", e));
            }
        }

        Ok(receiver)
    }

    fn stop_ap(
        &mut self,
        ssid: Vec<u8>,
        credential: Vec<u8>,
    ) -> BoxFuture<'static, Result<(), Error>> {
        if let Some(removal_index) =
            self.aps.iter().position(|ap_container| match ap_container.config.as_ref() {
                Some(config) => config.id.ssid == ssid && config.credential == credential,
                None => false,
            })
        {
            let phy_manager = self.phy_manager.clone();
            let mut ap_container = self.aps.remove(removal_index);

            if let Some(start_time) = ap_container.enabled_time.take() {
                let elapsed_time = zx::Time::get_monotonic() - start_time;
                self.cobalt_api.log_elapsed_time(
                    wlan_metrics_registry::ACCESS_POINT_ENABLED_DURATION_METRIC_ID,
                    (),
                    elapsed_time.into_micros(),
                );
            }

            let fut = async move {
                let stop_result =
                    Self::stop_and_exit_ap_state_machine(ap_container.ap_state_machine).await;

                let mut phy_manager = phy_manager.lock().await;
                phy_manager.destroy_ap_iface(ap_container.iface_id).await?;

                stop_result?;
                Ok(())
            };

            return fut.boxed();
        }

        return ready(Ok(())).boxed();
    }

    // Stop all APs, exit all of the state machines, and destroy all AP ifaces.
    fn stop_all_aps(&mut self) -> BoxFuture<'static, Result<(), Error>> {
        let mut aps: Vec<ApIfaceContainer> = self.aps.drain(..).collect();
        let phy_manager = self.phy_manager.clone();

        for ap_container in aps.iter_mut() {
            if let Some(start_time) = ap_container.enabled_time.take() {
                let elapsed_time = zx::Time::get_monotonic() - start_time;
                self.cobalt_api.log_elapsed_time(
                    wlan_metrics_registry::ACCESS_POINT_ENABLED_DURATION_METRIC_ID,
                    (),
                    elapsed_time.into_micros(),
                );
            }
        }

        let fut = async move {
            let mut failed_iface_deletions: u8 = 0;
            for iface in aps.drain(..) {
                match IfaceManagerService::stop_and_exit_ap_state_machine(iface.ap_state_machine)
                    .await
                {
                    Ok(()) => {}
                    Err(e) => {
                        failed_iface_deletions += 1;
                        error!("failed to stop AP: {}", e);
                    }
                }

                let mut phy_manager = phy_manager.lock().await;
                match phy_manager.destroy_ap_iface(iface.iface_id).await {
                    Ok(()) => {}
                    Err(e) => {
                        failed_iface_deletions += 1;
                        error!("failed to delete AP {}: {}", iface.iface_id, e);
                    }
                }
            }

            if failed_iface_deletions == 0 {
                return Ok(());
            } else {
                return Err(format_err!("failed to delete {} ifaces", failed_iface_deletions));
            }
        };

        fut.boxed()
    }

    /// Returns whether or not there is a client interface that is WPA3 capable, in other words
    /// wheter or not this device can connect to a network using WPA3. Check with the PhyManager
    /// in case it is aware of an iface that IfaceManager is not tracking.
    pub async fn has_wpa3_capable_client(&self) -> bool {
        let guard = self.phy_manager.lock().await;
        return guard.has_wpa3_client_iface();
    }
}

/// Returns whether the list of DriverFeatures contains one that indicates WPA3 support.
pub fn wpa3_in_features(driver_features: &Vec<fidl_fuchsia_wlan_common::DriverFeature>) -> bool {
    driver_features.iter().any(|feature| {
        feature == &fidl_fuchsia_wlan_common::DriverFeature::SaeDriverAuth
            || feature == &fidl_fuchsia_wlan_common::DriverFeature::SaeSmeAuth
    })
}

async fn initiate_network_selection(
    iface_manager: &IfaceManagerService,
    iface_manager_client: Arc<Mutex<dyn IfaceManagerApi + Send>>,
    network_selector: Arc<NetworkSelector>,
    network_selection_futures: &mut FuturesUnordered<
        BoxFuture<'static, Option<client_types::ConnectionCandidate>>,
    >,
) {
    if !iface_manager.idle_clients().is_empty()
        && iface_manager.saved_networks.known_network_count().await > 0
        && network_selection_futures.is_empty()
    {
        info!("Initiating network selection for idle client interface.");
        let fut = async move {
            let ignore_list = vec![];
            network_selector
                .find_best_connection_candidate(iface_manager_client.clone(), &ignore_list)
                .await
        };
        network_selection_futures.push(fut.boxed());
    }
}

async fn handle_network_selection_results(
    network_selection_result: Option<client_types::ConnectionCandidate>,
    iface_manager: &mut IfaceManagerService,
    reconnect_monitor_interval: &mut i64,
    connectivity_monitor_timer: &mut fasync::Interval,
) {
    if let Some(connection_candidate) = network_selection_result {
        *reconnect_monitor_interval = 1;

        let connect_req = client_types::ConnectRequest {
            target: connection_candidate,
            reason: client_types::ConnectReason::IdleInterfaceAutoconnect,
        };

        let mut idle_clients = iface_manager.idle_clients();
        if !idle_clients.is_empty() {
            // Any client interfaces that have recently presented as idle will be
            // reconnected.
            for iface_id in idle_clients.drain(..) {
                if let Err(e) =
                    iface_manager.attempt_client_reconnect(iface_id, connect_req.clone()).await
                {
                    warn!("Could not reconnect iface {}: {:?}", iface_id, e);
                }
            }
        }
    } else {
        info!("No saved networks available to reconnect to");
        *reconnect_monitor_interval =
            (2 * (*reconnect_monitor_interval)).min(MAX_AUTO_CONNECT_RETRY_SECONDS);
    }

    *connectivity_monitor_timer =
        fasync::Interval::new(zx::Duration::from_seconds(*reconnect_monitor_interval));
}

async fn handle_terminated_state_machine(
    terminated_fsm: StateMachineMetadata,
    iface_manager: &mut IfaceManagerService,
    iface_manager_client: Arc<Mutex<dyn IfaceManagerApi + Send>>,
    selector: Arc<NetworkSelector>,
    network_selection_futures: &mut FuturesUnordered<
        BoxFuture<'static, Option<client_types::ConnectionCandidate>>,
    >,
) {
    match terminated_fsm.role {
        fidl_fuchsia_wlan_device::MacRole::Ap => {
            // If the state machine exited normally, the IfaceManagerService will have already
            // destroyed the interface.  If not, then the state machine exited because it could not
            // communicate with the SME and the interface is likely unusable.
            let mut phy_manager = iface_manager.phy_manager.lock().await;
            if phy_manager.destroy_ap_iface(terminated_fsm.iface_id).await.is_err() {
                return;
            }
        }
        fidl_fuchsia_wlan_device::MacRole::Client => {
            iface_manager.record_idle_client(terminated_fsm.iface_id);
            initiate_network_selection(
                &iface_manager,
                iface_manager_client.clone(),
                selector.clone(),
                network_selection_futures,
            )
            .await;
        }
        fidl_fuchsia_wlan_device::MacRole::Mesh => {
            // Not yet supported.
            unimplemented!();
        }
    }
}

fn initiate_set_country(
    iface_manager: &mut IfaceManagerService,
    req: SetCountryRequest,
) -> BoxFuture<'static, IfaceManagerOperation> {
    // Store the initial AP configs so that they can be started later.
    let initial_ap_configs =
        iface_manager.aps.iter().filter_map(|container| container.config.clone()).collect();

    // Create futures to stop all of the APs and stop client connections
    let stop_client_connections_fut = iface_manager
        .stop_client_connections(client_types::DisconnectReason::RegulatoryRegionChange);
    let stop_aps_fut = iface_manager.stop_all_aps();

    // Once the clients and APs have been stopped, set the country code.
    let phy_manager = iface_manager.phy_manager.clone();
    let regulatory_fut = async move {
        let client_connections_initially_enabled =
            phy_manager.lock().await.client_connections_enabled();

        let set_country_result = if let Err(e) = stop_client_connections_fut.await {
            Err(format_err!(
                "failed to stop client connection in preparation for setting
            country code: {:?}",
                e
            ))
        } else if let Err(e) = stop_aps_fut.await {
            Err(format_err!("failed to stop APs in preparation for setting country code: {:?}", e))
        } else {
            let mut phy_manager = phy_manager.lock().await;
            phy_manager
                .set_country_code(req.country_code)
                .await
                .map_err(|e| format_err!("failed to set regulatory region: {:?}", e))
        };

        let result = SetCountryOperationState {
            client_connections_initially_enabled,
            initial_ap_configs,
            set_country_result,
            responder: req.responder,
        };

        // Return all information required to resume to the old state.
        IfaceManagerOperation::SetCountry(result)
    };
    regulatory_fut.boxed()
}

async fn restore_state_after_setting_country_code(
    iface_manager: &mut IfaceManagerService,
    previous_state: SetCountryOperationState,
) {
    // Prior to setting the country code, it is essential that client connections and APs are all
    // stopped.  If stopping clients or APs fails or if setting the country code fails, the whole
    // process of setting the country code must be considered a failure.
    //
    // Bringing clients and APs back online following the regulatory region setting may fail and is
    // possibly recoverable.  Log failures, but do not report errors in scenarios where recreating
    // the client and AP interfaces fails.  This allows API clients to retry and attempt to create
    // the interfaces themselves by making policy API requests.
    if previous_state.client_connections_initially_enabled {
        if let Err(e) = iface_manager.start_client_connections().await {
            error!("failed to resume client connections after setting country code: {:?}", e);
        }
    }

    for config in previous_state.initial_ap_configs {
        if let Err(e) = iface_manager.start_ap(config).await {
            error!("failed to resume AP after setting country code: {:?}", e);
        }
    }

    if previous_state.responder.send(previous_state.set_country_result).is_err() {
        error!("could not respond to SetCountryRequest");
    }
}

pub(crate) async fn serve_iface_manager_requests(
    mut iface_manager: IfaceManagerService,
    iface_manager_client: Arc<Mutex<dyn IfaceManagerApi + Send>>,
    network_selector: Arc<NetworkSelector>,
    mut requests: mpsc::Receiver<IfaceManagerRequest>,
) -> Result<Void, Error> {
    // Client and AP state machines need to be allowed to run in order for several operations to
    // complete.  In such cases, futures can be added to this list to progress them once the state
    // machines have the opportunity to run.
    let mut operation_futures = FuturesUnordered::new();

    // Scans will be initiated to perform network selection if clients become disconnected.
    let mut network_selection_futures = FuturesUnordered::new();

    // Create a timer to periodically check to ensure that all client interfaces are connected.
    let mut reconnect_monitor_interval: i64 = 1;
    let mut connectivity_monitor_timer =
        fasync::Interval::new(zx::Duration::from_seconds(reconnect_monitor_interval));

    loop {
        select! {
            terminated_fsm = iface_manager.fsm_futures.select_next_some() => {
                info!("state machine exited: {:?}", terminated_fsm.1);
                handle_terminated_state_machine(
                    terminated_fsm.1,
                    &mut iface_manager,
                    iface_manager_client.clone(),
                    network_selector.clone(),
                    &mut network_selection_futures,
                ).await;
            },
            () = connectivity_monitor_timer.select_next_some() => {
                initiate_network_selection(
                    &iface_manager,
                    iface_manager_client.clone(),
                    network_selector.clone(),
                    &mut network_selection_futures
                ).await;
            },
            op = operation_futures.select_next_some() => match op {
                IfaceManagerOperation::ConfigureStateMachine => {},
                IfaceManagerOperation::SetCountry(previous_state) => {
                    restore_state_after_setting_country_code(
                        &mut iface_manager,
                        previous_state
                    ).await;
                }
            },
            network_selection_result = network_selection_futures.select_next_some() => {
                handle_network_selection_results(
                    network_selection_result,
                    &mut iface_manager,
                    &mut reconnect_monitor_interval,
                    &mut connectivity_monitor_timer
                ).await;
            },
            req = requests.select_next_some() => {
                match req {
                    IfaceManagerRequest::Disconnect(DisconnectRequest { network_id, responder, reason }) => {
                        let fut = iface_manager.disconnect(network_id, reason);
                        let disconnect_fut = async move {
                            if responder.send(fut.await).is_err() {
                                error!("could not respond to DisconnectRequest");
                            }
                            IfaceManagerOperation::ConfigureStateMachine
                        };
                        operation_futures.push(disconnect_fut.boxed());
                    }
                    IfaceManagerRequest::Connect(ConnectRequest { request, responder }) => {
                        if responder.send(iface_manager.connect(request).await).is_err() {
                            error!("could not respond to ConnectRequest");
                        }
                    }
                    IfaceManagerRequest::RecordIdleIface(RecordIdleIfaceRequest { iface_id, responder } ) => {
                        if responder.send(iface_manager.record_idle_client(iface_id)).is_err() {
                            error!("could not respond to RecordIdleIfaceRequest");
                        }
                    }
                    IfaceManagerRequest::HasIdleIface(HasIdleIfaceRequest { responder }) => {
                        if responder.send(!iface_manager.idle_clients().is_empty()).is_err() {
                            error!("could not respond to  HasIdleIfaceRequest");
                        }
                    }
                    IfaceManagerRequest::AddIface(AddIfaceRequest { iface_id, responder } ) => {
                        if let Err(e) = iface_manager.handle_added_iface(iface_id).await {
                            warn!("failed to add new interface {}: {:?}", iface_id, e);
                        }
                        if responder.send(()).is_err() {
                            error!("could not respond to AddIfaceRequest");
                        }
                    }
                    IfaceManagerRequest::RemoveIface(RemoveIfaceRequest { iface_id, responder }) => {
                        if responder.send(iface_manager.handle_removed_iface(iface_id).await).is_err() {
                            error!("could not respond to RemoveIfaceRequest");
                        }
                    }
                    IfaceManagerRequest::Scan(ScanRequest {  scan_request, responder }) => {
                        if responder.send(iface_manager.scan( scan_request).await).is_err() {
                            error!("could not respond to ScanRequest");
                        }
                    }
                    IfaceManagerRequest::GetScanProxy(ScanProxyRequest {  responder }) => {
                        if responder.send(iface_manager.get_sme_proxy_for_scan().await).is_err() {
                            error!("could not respond to ScanRequest");
                        }
                    }
                    IfaceManagerRequest::StopClientConnections(StopClientConnectionsRequest { reason, responder }) => {
                        let fut = iface_manager.stop_client_connections(reason);
                        let stop_client_connections_fut = async move {
                            if responder.send(fut.await).is_err() {
                                error!("could not respond to StopClientConnectionsRequest");
                            }
                            IfaceManagerOperation::ConfigureStateMachine
                        };
                        operation_futures.push(stop_client_connections_fut.boxed());
                    }
                    IfaceManagerRequest::StartClientConnections(StartClientConnectionsRequest { responder }) => {
                        if responder.send(iface_manager.start_client_connections().await).is_err() {
                            error!("could not respond to StartClientConnectionRequest");
                        }
                    }
                    IfaceManagerRequest::StartAp(StartApRequest { config, responder }) => {
                        if responder.send(iface_manager.start_ap(config).await).is_err() {
                            error!("could not respond to StartApRequest");
                        }
                    }
                    IfaceManagerRequest::StopAp(StopApRequest { ssid, password, responder }) => {
                        let stop_ap_fut = iface_manager.stop_ap(ssid, password);
                        let stop_ap_fut = async move {
                            if responder.send(stop_ap_fut.await).is_err() {
                                error!("could not respond to StopApRequest");
                            }
                            IfaceManagerOperation::ConfigureStateMachine
                        };
                        operation_futures.push(stop_ap_fut.boxed());
                    }
                    IfaceManagerRequest::StopAllAps(StopAllApsRequest { responder }) => {
                        let stop_all_aps_fut = iface_manager.stop_all_aps();
                        let stop_all_aps_fut = async move {
                            if responder.send(stop_all_aps_fut.await).is_err() {
                                error!("could not respond to StopAllApsRequest");
                            }
                            IfaceManagerOperation::ConfigureStateMachine
                        };
                        operation_futures.push(stop_all_aps_fut.boxed());
                    }
                    IfaceManagerRequest::HasWpa3Iface(HasWpa3IfaceRequest { responder }) => {
                        if responder.send(iface_manager.has_wpa3_capable_client().await).is_err() {
                            error!("could not respond to HasWpa3IfaceRequest");
                        }

                    }
                    IfaceManagerRequest::SetCountry(req) => {
                        let regulatory_fut =
                            initiate_set_country(&mut iface_manager, req);
                        operation_futures.push(regulatory_fut);
                    }
                };
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::{
            access_point::types,
            client::types as client_types,
            config_management::{
                Credential, NetworkIdentifier, SavedNetworksManager, SecurityType,
            },
            mode_management::phy_manager::{self, PhyManagerError},
            regulatory_manager::REGION_CODE_LEN,
            util::testing::{
                create_mock_cobalt_sender, create_mock_cobalt_sender_and_receiver,
                generate_random_bss_desc, poll_sme_req,
            },
        },
        async_trait::async_trait,
        eui48::MacAddress,
        fidl::endpoints::create_proxy,
        fidl_fuchsia_cobalt::CobaltEvent,
        fidl_fuchsia_stash as fidl_stash,
        fuchsia_async::TestExecutor,
        fuchsia_inspect::{self as inspect},
        futures::{
            channel::mpsc,
            stream::{StreamExt, StreamFuture},
            task::Poll,
            TryFutureExt, TryStreamExt,
        },
        pin_utils::pin_mut,
        rand::{distributions::Alphanumeric, thread_rng, Rng},
        tempfile::TempDir,
        test_case::test_case,
        wlan_common::{
            assert_variant,
            channel::{Cbw, Phy},
            fake_fidl_bss, RadioConfig,
        },
    };

    // Responses that FakePhyManager will provide
    pub const TEST_CLIENT_IFACE_ID: u16 = 0;
    pub const TEST_AP_IFACE_ID: u16 = 1;

    // Fake WLAN network that tests will scan for and connect to.
    pub static TEST_SSID: &str = "test_ssid";
    pub static TEST_PASSWORD: &str = "test_password";

    /// Produces wlan network configuration objects to be used in tests.
    pub fn create_connect_request(ssid: &str, password: &str) -> client_types::ConnectRequest {
        let network = ap_types::NetworkIdentifier {
            ssid: ssid.as_bytes().to_vec(),
            type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
        };
        let credential = Credential::Password(password.as_bytes().to_vec());

        client_types::ConnectRequest {
            target: client_types::ConnectionCandidate {
                network,
                credential,
                observed_in_passive_scan: Some(true),
                bss: Some(generate_random_bss_desc()),
                multiple_bss_candidates: Some(true),
            },
            reason: client_types::ConnectReason::FidlConnectRequest,
        }
    }

    /// Holds all of the boilerplate required for testing IfaceManager.
    /// * DeviceServiceProxy and DeviceServiceRequestStream
    ///   * Allow for the construction of Clients and ClientIfaceContainers and the ability to send
    ///     responses to their requests.
    /// * ClientListenerMessageSender and MessageStream
    ///   * Allow for the construction of ClientIfaceContainers and the absorption of
    ///     ClientStateUpdates.
    /// * ApListenerMessageSender and MessageStream
    ///   * Allow for the construction of ApIfaceContainers and the absorption of
    ///     ApStateUpdates.
    /// * KnownEssStore, SavedNetworksManager, TempDir
    ///   * Allow for the querying of network credentials and storage of connection history.
    pub struct TestValues {
        pub device_service_proxy: fidl_fuchsia_wlan_device_service::DeviceServiceProxy,
        pub device_service_stream: fidl_fuchsia_wlan_device_service::DeviceServiceRequestStream,
        pub monitor_service_proxy: fidl_fuchsia_wlan_device_service::DeviceMonitorProxy,
        pub monitor_service_stream: fidl_fuchsia_wlan_device_service::DeviceMonitorRequestStream,
        pub client_update_sender: listener::ClientListenerMessageSender,
        pub client_update_receiver: mpsc::UnboundedReceiver<listener::ClientListenerMessage>,
        pub ap_update_sender: listener::ApListenerMessageSender,
        pub ap_update_receiver: mpsc::UnboundedReceiver<listener::ApMessage>,
        pub saved_networks: Arc<dyn SavedNetworksManagerApi>,
        pub network_selector: Arc<NetworkSelector>,
        pub node: inspect::Node,
        pub cobalt_api: CobaltSender,
        pub cobalt_receiver: mpsc::Receiver<CobaltEvent>,
    }

    fn rand_string() -> String {
        thread_rng().sample_iter(&Alphanumeric).take(20).collect()
    }

    /// Create a TestValues for a unit test.
    pub fn test_setup(exec: &mut TestExecutor) -> TestValues {
        let (device_service_proxy, device_service_requests) =
            create_proxy::<fidl_fuchsia_wlan_device_service::DeviceServiceMarker>()
                .expect("failed to create SeviceService proxy");
        let device_service_stream =
            device_service_requests.into_stream().expect("failed to create stream");

        let (monitor_service_proxy, monitor_service_requests) =
            create_proxy::<fidl_fuchsia_wlan_device_service::DeviceMonitorMarker>()
                .expect("failed to create SeviceService proxy");
        let monitor_service_stream =
            monitor_service_requests.into_stream().expect("failed to create stream");

        let (client_sender, client_receiver) = mpsc::unbounded();
        let (ap_sender, ap_receiver) = mpsc::unbounded();

        let saved_networks = exec
            .run_singlethreaded(SavedNetworksManager::new_for_test())
            .expect("failed to create saved networks manager.");
        let saved_networks = Arc::new(saved_networks);
        let inspector = inspect::Inspector::new();
        let node = inspector.root().create_child("phy_manager");
        let (cobalt_api, cobalt_receiver) = create_mock_cobalt_sender_and_receiver();
        let network_selector = Arc::new(NetworkSelector::new(
            saved_networks.clone(),
            cobalt_api.clone(),
            inspector.root().create_child("network_selection"),
        ));

        TestValues {
            device_service_proxy,
            device_service_stream,
            monitor_service_proxy,
            monitor_service_stream,
            client_update_sender: client_sender,
            client_update_receiver: client_receiver,
            ap_update_sender: ap_sender,
            ap_update_receiver: ap_receiver,
            saved_networks: saved_networks,
            node: node,
            network_selector,
            cobalt_api,
            cobalt_receiver,
        }
    }

    /// Creates a new PhyManagerPtr for tests.
    fn create_empty_phy_manager(
        device_service: fidl_fuchsia_wlan_device_service::DeviceServiceProxy,
        monitor_service: fidl_fuchsia_wlan_device_service::DeviceMonitorProxy,
        node: inspect::Node,
    ) -> Arc<Mutex<dyn PhyManagerApi + Send>> {
        Arc::new(Mutex::new(phy_manager::PhyManager::new(device_service, monitor_service, node)))
    }

    #[derive(Debug)]
    struct FakePhyManager {
        create_iface_ok: bool,
        destroy_iface_ok: bool,
        set_country_ok: bool,
        wpa3_iface: Option<u16>,
        country_code: Option<[u8; REGION_CODE_LEN]>,
        client_connections_enabled: bool,
    }

    #[async_trait]
    impl PhyManagerApi for FakePhyManager {
        async fn add_phy(&mut self, _phy_id: u16) -> Result<(), PhyManagerError> {
            unimplemented!()
        }

        fn remove_phy(&mut self, _phy_id: u16) {
            unimplemented!()
        }

        async fn on_iface_added(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
            unimplemented!()
        }

        fn on_iface_removed(&mut self, _iface_id: u16) {}

        async fn create_all_client_ifaces(
            &mut self,
            _reason: CreateClientIfacesReason,
        ) -> Result<Vec<u16>, (Vec<u16>, PhyManagerError)> {
            if self.create_iface_ok {
                Ok(vec![TEST_CLIENT_IFACE_ID])
            } else {
                Err((vec![], PhyManagerError::IfaceCreateFailure))
            }
        }

        fn client_connections_enabled(&self) -> bool {
            self.client_connections_enabled
        }

        async fn destroy_all_client_ifaces(&mut self) -> Result<(), PhyManagerError> {
            if self.destroy_iface_ok {
                Ok(())
            } else {
                Err(PhyManagerError::IfaceDestroyFailure)
            }
        }

        fn get_client(&mut self) -> Option<u16> {
            Some(TEST_CLIENT_IFACE_ID)
        }

        fn get_wpa3_capable_client(&mut self) -> Option<u16> {
            self.wpa3_iface
        }

        async fn create_or_get_ap_iface(&mut self) -> Result<Option<u16>, PhyManagerError> {
            if self.create_iface_ok {
                Ok(Some(TEST_AP_IFACE_ID))
            } else {
                Err(PhyManagerError::IfaceCreateFailure)
            }
        }

        async fn destroy_ap_iface(&mut self, _iface_id: u16) -> Result<(), PhyManagerError> {
            if self.destroy_iface_ok {
                Ok(())
            } else {
                Err(PhyManagerError::IfaceDestroyFailure)
            }
        }

        async fn destroy_all_ap_ifaces(&mut self) -> Result<(), PhyManagerError> {
            if self.destroy_iface_ok {
                Ok(())
            } else {
                Err(PhyManagerError::IfaceDestroyFailure)
            }
        }

        fn suggest_ap_mac(&mut self, _mac: MacAddress) {
            unimplemented!()
        }

        fn get_phy_ids(&self) -> Vec<u16> {
            unimplemented!()
        }

        fn log_phy_add_failure(&mut self) {
            unimplemented!();
        }

        async fn set_country_code(
            &mut self,
            country_code: Option<[u8; REGION_CODE_LEN]>,
        ) -> Result<(), PhyManagerError> {
            if self.set_country_ok {
                self.country_code = country_code;
                Ok(())
            } else {
                Err(PhyManagerError::PhySetCountryFailure)
            }
        }

        fn has_wpa3_client_iface(&self) -> bool {
            self.wpa3_iface.is_some()
        }
    }

    struct FakeClient {
        disconnect_ok: bool,
        is_alive: bool,
        expected_connect_request: Option<client_types::ConnectRequest>,
    }

    impl FakeClient {
        fn new() -> Self {
            FakeClient { disconnect_ok: true, is_alive: true, expected_connect_request: None }
        }
    }

    #[async_trait]
    impl client_fsm::ClientApi for FakeClient {
        fn connect(
            &mut self,
            request: client_types::ConnectRequest,
            responder: oneshot::Sender<()>,
        ) -> Result<(), Error> {
            assert_eq!(Some(request), self.expected_connect_request);
            let _ = responder.send(());
            Ok(())
        }
        fn disconnect(
            &mut self,
            _reason: client_types::DisconnectReason,
            responder: oneshot::Sender<()>,
        ) -> Result<(), Error> {
            if self.disconnect_ok {
                let _ = responder.send(());
                Ok(())
            } else {
                Err(format_err!("fake failed to disconnect"))
            }
        }
        fn is_alive(&self) -> bool {
            self.is_alive
        }
    }

    struct FakeAp {
        start_succeeds: bool,
        stop_succeeds: bool,
        exit_succeeds: bool,
    }

    #[async_trait]
    impl AccessPointApi for FakeAp {
        fn start(
            &mut self,
            _request: ap_fsm::ApConfig,
            responder: oneshot::Sender<()>,
        ) -> Result<(), anyhow::Error> {
            if self.start_succeeds {
                let _ = responder.send(());
                Ok(())
            } else {
                Err(format_err!("start failed"))
            }
        }

        fn stop(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error> {
            if self.stop_succeeds {
                let _ = responder.send(());
                Ok(())
            } else {
                Err(format_err!("stop failed"))
            }
        }

        fn exit(&mut self, responder: oneshot::Sender<()>) -> Result<(), anyhow::Error> {
            if self.exit_succeeds {
                let _ = responder.send(());
                Ok(())
            } else {
                Err(format_err!("exit failed"))
            }
        }
    }

    fn create_iface_manager_with_client(
        test_values: &TestValues,
        configured: bool,
    ) -> (IfaceManagerService, StreamFuture<fidl_fuchsia_wlan_sme::ClientSmeRequestStream>) {
        let (sme_proxy, server) = create_proxy::<fidl_fuchsia_wlan_sme::ClientSmeMarker>()
            .expect("failed to create an sme channel");
        let mut client_container = ClientIfaceContainer {
            iface_id: TEST_CLIENT_IFACE_ID,
            sme_proxy,
            config: None,
            client_state_machine: None,
            driver_features: Vec::new(),
        };
        let phy_manager = FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        };
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender.clone(),
            test_values.ap_update_sender.clone(),
            test_values.device_service_proxy.clone(),
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api.clone(),
        );

        if configured {
            client_container.config = Some(ap_types::NetworkIdentifier {
                ssid: TEST_SSID.as_bytes().to_vec(),
                type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
            });
            client_container.client_state_machine = Some(Box::new(FakeClient::new()));
        }
        iface_manager.clients.push(client_container);

        (iface_manager, server.into_stream().unwrap().into_future())
    }

    fn create_ap_config(ssid: &str, password: &str) -> ap_fsm::ApConfig {
        let radio_config = RadioConfig::new(Phy::Ht, Cbw::Cbw20, 6);
        ap_fsm::ApConfig {
            id: ap_types::NetworkIdentifier {
                ssid: ssid.as_bytes().to_vec(),
                type_: fidl_fuchsia_wlan_policy::SecurityType::None,
            },
            credential: password.as_bytes().to_vec(),
            radio_config,
            mode: types::ConnectivityMode::Unrestricted,
            band: types::OperatingBand::Any,
        }
    }

    fn create_iface_manager_with_ap(
        test_values: &TestValues,
        fake_ap: FakeAp,
    ) -> IfaceManagerService {
        let ap_container = ApIfaceContainer {
            iface_id: TEST_AP_IFACE_ID,
            config: None,
            ap_state_machine: Box::new(fake_ap),
            enabled_time: None,
        };
        let phy_manager = FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        };
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender.clone(),
            test_values.ap_update_sender.clone(),
            test_values.device_service_proxy.clone(),
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api.clone(),
        );

        iface_manager.aps.push(ap_container);
        iface_manager
    }

    /// Tests the case where the only available client iface is one that has been configured.  The
    /// Client SME proxy associated with the configured iface should be used for scanning.
    #[fuchsia::test]
    fn test_scan_with_configured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        // Scan and ensure that the response is handled properly
        let scan_fut = iface_manager.scan(fidl_fuchsia_wlan_sme::ScanRequest::Passive(
            fidl_fuchsia_wlan_sme::PassiveScanRequest {},
        ));

        pin_mut!(scan_fut);
        let _scan_proxy = match exec.run_until_stalled(&mut scan_fut) {
            Poll::Ready(proxy) => proxy,
            Poll::Pending => panic!("no scan was requested"),
        };
    }

    /// Tests the case where the only available client iface is one that has is unconfigured.  The
    /// Client SME proxy associated with the unconfigured iface should be used for scanning.
    #[fuchsia::test]
    fn test_scan_with_unconfigured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an unconfigured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, false);

        // Scan and ensure that the response is handled properly
        let scan_fut = iface_manager.scan(fidl_fuchsia_wlan_sme::ScanRequest::Passive(
            fidl_fuchsia_wlan_sme::PassiveScanRequest {},
        ));

        pin_mut!(scan_fut);
        let _scan_proxy = match exec.run_until_stalled(&mut scan_fut) {
            Poll::Ready(proxy) => proxy,
            Poll::Pending => panic!("no scan was requested"),
        };
    }

    /// Tests the scan behavior in the case where no client ifaces are present.  Ensures that the
    /// scan call results in an error.
    #[fuchsia::test]
    fn test_scan_with_no_ifaces() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a PhyManager with no knowledge of any client ifaces.
        let test_values = test_setup(&mut exec);
        let phy_manager = create_empty_phy_manager(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );

        // Create and IfaceManager and issue a scan request.
        let mut iface_manager = IfaceManagerService::new(
            phy_manager,
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );
        let scan_fut = iface_manager.scan(fidl_fuchsia_wlan_sme::ScanRequest::Passive(
            fidl_fuchsia_wlan_sme::PassiveScanRequest {},
        ));

        // Ensure that the scan request results in an error.
        pin_mut!(scan_fut);
        assert_variant!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where a scan request cannot be made of the SME proxy.
    #[fuchsia::test]
    fn test_scan_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        // Drop the SME's serving end so that the request to scan will fail.
        drop(next_sme_req);

        // Scan and ensure that an error is returned.
        let scan_fut = iface_manager.scan(fidl_fuchsia_wlan_sme::ScanRequest::Passive(
            fidl_fuchsia_wlan_sme::PassiveScanRequest {},
        ));

        pin_mut!(scan_fut);
        assert_variant!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where a scan is requested, the PhyManager provides a client iface ID, but
    /// when the IfaceManager attempts to create an SME proxy, the creation fails.
    #[fuchsia::test]
    fn test_scan_sme_creation_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager and drop its client.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);
        let _ = iface_manager.clients.pop();

        // Drop the serving end of our device service proxy so that the request to create an SME
        // proxy fails.
        drop(test_values.device_service_stream);

        // Scan and ensure that an error is returned.
        let scan_fut = iface_manager.scan(fidl_fuchsia_wlan_sme::ScanRequest::Passive(
            fidl_fuchsia_wlan_sme::PassiveScanRequest {},
        ));

        pin_mut!(scan_fut);
        assert_variant!(exec.run_until_stalled(&mut scan_fut), Poll::Ready(Err(_)));
    }

    /// Move stash requests forward so that a save request can progress.
    fn process_stash_write(
        mut exec: &mut fuchsia_async::TestExecutor,
        mut stash_server: &mut fidl_stash::StoreAccessorRequestStream,
    ) {
        assert_variant!(
            exec.run_until_stalled(&mut stash_server.try_next()),
            Poll::Ready(Ok(Some(fidl_stash::StoreAccessorRequest::SetValue { .. })))
        );
        process_stash_flush(&mut exec, &mut stash_server);
    }

    fn process_stash_delete(
        mut exec: &mut fuchsia_async::TestExecutor,
        mut stash_server: &mut fidl_stash::StoreAccessorRequestStream,
    ) {
        assert_variant!(
            exec.run_until_stalled(&mut stash_server.try_next()),
            Poll::Ready(Ok(Some(fidl_stash::StoreAccessorRequest::DeletePrefix { .. })))
        );
        process_stash_flush(&mut exec, &mut stash_server);
    }

    fn process_stash_flush(
        exec: &mut fuchsia_async::TestExecutor,
        stash_server: &mut fidl_stash::StoreAccessorRequestStream,
    ) {
        assert_variant!(
            exec.run_until_stalled(&mut stash_server.try_next()),
            Poll::Ready(Ok(Some(fidl_stash::StoreAccessorRequest::Flush{responder}))) => {
                responder.send(&mut Ok(())).expect("failed to send stash response");
            }
        );
    }

    fn run_state_machine_futures(
        exec: &mut fuchsia_async::TestExecutor,
        iface_manager: &mut IfaceManagerService,
    ) {
        for mut state_machine in iface_manager.fsm_futures.iter_mut() {
            assert_variant!(exec.run_until_stalled(&mut state_machine), Poll::Pending);
        }
    }

    /// Tests the case where connect is called and the only available client interface is already
    /// configured.
    #[fuchsia::test]
    fn test_connect_with_configured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let other_test_ssid = "other_ssid_connecting";

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Configure the mock CSM with the expected connect request
        let connect_request = create_connect_request(other_test_ssid, TEST_PASSWORD);
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: true,
            expected_connect_request: Some(connect_request.clone()),
        }));

        // Ask the IfaceManager to connect.
        let config = connect_request;
        let connect_response_fut = {
            let connect_fut = iface_manager.connect(config);
            pin_mut!(connect_fut);

            // Run the connect request to completion.
            match exec.run_until_stalled(&mut connect_fut) {
                Poll::Ready(connect_result) => match connect_result {
                    Ok(receiver) => receiver.into_future(),
                    Err(e) => panic!("failed to connect with {}", e),
                },
                Poll::Pending => panic!("expected the connect request to finish"),
            }
        };

        // Start running the client state machine.
        run_state_machine_futures(&mut exec, &mut iface_manager);

        // Verify that the oneshot has been acked.
        pin_mut!(connect_response_fut);
        assert_variant!(exec.run_until_stalled(&mut connect_response_fut), Poll::Ready(Ok(())));

        // Verify that the ClientIfaceContainer has the correct config.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(
            iface_manager.clients[0].config,
            Some(
                NetworkIdentifier::new(other_test_ssid.as_bytes().to_vec(), SecurityType::Wpa)
                    .into()
            )
        );
    }

    /// Tests the case where connect is called while the only available interface is currently
    /// unconfigured.
    #[fuchsia::test]
    fn test_connect_with_unconfigured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, mut _sme_stream) =
            create_iface_manager_with_client(&test_values, false);

        let temp_dir = TempDir::new().expect("failed to create temporary directory");
        let path = temp_dir.path().join(rand_string());
        let tmp_path = temp_dir.path().join(rand_string());
        let (saved_networks, mut stash_server) =
            exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
        test_values.saved_networks = Arc::new(saved_networks);

        // Add credentials for the test network to the saved networks.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let save_network_fut = test_values.saved_networks.store(network_id.clone(), credential);
        pin_mut!(save_network_fut);
        assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

        process_stash_write(&mut exec, &mut stash_server);

        {
            let connect_response_fut = {
                let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
                let connect_fut = iface_manager.connect(config);
                pin_mut!(connect_fut);

                // Expect that we have requested a client SME proxy.
                assert_variant!(exec.run_until_stalled(&mut connect_fut), Poll::Pending);

                let mut device_service_fut = test_values.device_service_stream.into_future();
                let sme_server = assert_variant!(
                    poll_device_service_req(&mut exec, &mut device_service_fut),
                    Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                        iface_id: TEST_CLIENT_IFACE_ID, sme, responder
                    }) => {
                        // Send back a positive acknowledgement.
                        assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());

                        sme
                    }
                );
                _sme_stream = sme_server.into_stream().unwrap().into_future();

                pin_mut!(connect_fut);
                match exec.run_until_stalled(&mut connect_fut) {
                    Poll::Ready(connect_result) => match connect_result {
                        Ok(receiver) => receiver.into_future(),
                        Err(e) => panic!("failed to connect with {}", e),
                    },
                    Poll::Pending => panic!("expected the connect request to finish"),
                }
            };

            // Start running the client state machine.
            run_state_machine_futures(&mut exec, &mut iface_manager);

            // Acknowledge the disconnection attempt.
            assert_variant!(
                poll_sme_req(&mut exec, &mut _sme_stream),
                Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Disconnect{ responder, reason: fidl_fuchsia_wlan_sme::UserDisconnectReason::Startup }) => {
                    responder.send().expect("could not send response")
                }
            );

            // Make sure that the connect request has been sent out.
            run_state_machine_futures(&mut exec, &mut iface_manager);
            assert_variant!(
                poll_sme_req(&mut exec, &mut _sme_stream),
                Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Connect{ req, txn, control_handle: _ }) => {
                    assert_eq!(req.ssid, TEST_SSID.as_bytes().to_vec());
                    assert_eq!(req.credential, fidl_fuchsia_wlan_sme::Credential::Password(TEST_PASSWORD.as_bytes().to_vec()));
                    let (_stream, ctrl) = txn.expect("connect txn unused")
                        .into_stream_and_control_handle().expect("error accessing control handle");
                    ctrl.send_on_finished(fidl_fuchsia_wlan_sme::ConnectResultCode::Success)
                        .expect("failed to send connection completion");
                }
            );

            // Run the state machine future again so that it acks the oneshot.
            run_state_machine_futures(&mut exec, &mut iface_manager);

            // Verify that the oneshot has been acked.
            pin_mut!(connect_response_fut);
            assert_variant!(exec.run_until_stalled(&mut connect_response_fut), Poll::Ready(Ok(())));
        }

        // Verify that the ClientIfaceContainer has been moved from unconfigured to configured.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(iface_manager.clients[0].config, Some(network_id.into()));
    }

    /// Tests the case where connect is called for a WPA3 connection an there is an unconfigured
    /// WPA3 iface available.
    #[test_case(fidl_fuchsia_wlan_common::DriverFeature::SaeDriverAuth)]
    #[test_case(fidl_fuchsia_wlan_common::DriverFeature::SaeSmeAuth)]
    #[fuchsia::test(add_test_attr = false)]
    fn test_connect_with_unconfigured_wpa3_iface(
        wpa3_feature: fidl_fuchsia_wlan_common::DriverFeature,
    ) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        let mut test_values = test_setup(&mut exec);
        // The default FakePhyManager will not have a WPA3 iface which is intentional because if
        // an unconfigured iface is available with WPA3, it should be used without asking
        // PhyManager for an iface.
        let (mut iface_manager, mut _sme_stream) =
            create_iface_manager_with_client(&test_values, false);
        iface_manager.clients[0].driver_features.push(wpa3_feature);

        let temp_dir = TempDir::new().expect("failed to create temporary directory");
        let path = temp_dir.path().join(rand_string());
        let tmp_path = temp_dir.path().join(rand_string());
        let (saved_networks, mut stash_server) =
            exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
        test_values.saved_networks = Arc::new(saved_networks);

        // Add credentials for the test network to the saved networks.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa3);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let save_network_fut =
            test_values.saved_networks.store(network_id.clone(), credential.clone());
        pin_mut!(save_network_fut);
        assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

        process_stash_write(&mut exec, &mut stash_server);

        {
            let connect_response_fut = {
                let config = client_types::ConnectRequest {
                    target: client_types::ConnectionCandidate {
                        network: network_id.clone().into(),
                        credential,
                        observed_in_passive_scan: Some(true),
                        bss: Some(generate_random_bss_desc()),
                        multiple_bss_candidates: Some(true),
                    },
                    reason: client_types::ConnectReason::FidlConnectRequest,
                };
                let connect_fut = iface_manager.connect(config);
                pin_mut!(connect_fut);

                // Expect that we have requested a client SME proxy.
                assert_variant!(exec.run_until_stalled(&mut connect_fut), Poll::Pending);

                let mut device_service_fut = test_values.device_service_stream.into_future();
                let sme_server = assert_variant!(
                    poll_device_service_req(&mut exec, &mut device_service_fut),
                    Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                        iface_id: TEST_CLIENT_IFACE_ID, sme, responder
                    }) => {
                        // Send back a positive acknowledgement.
                        assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());

                        sme
                    }
                );
                _sme_stream = sme_server.into_stream().unwrap().into_future();

                match exec.run_until_stalled(&mut connect_fut) {
                    Poll::Ready(connect_result) => match connect_result {
                        Ok(receiver) => receiver.into_future(),
                        Err(e) => panic!("failed to connect with {}", e),
                    },
                    Poll::Pending => panic!("expected the connect request to finish"),
                }
            };

            // Start running the client state machine.
            run_state_machine_futures(&mut exec, &mut iface_manager);

            // Acknowledge the disconnection attempt.
            assert_variant!(
                poll_sme_req(&mut exec, &mut _sme_stream),
                Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Disconnect{ responder, reason: fidl_fuchsia_wlan_sme::UserDisconnectReason::Startup }) => {
                    responder.send().expect("could not send response")
                }
            );

            // Make sure that the connect request has been sent out.
            run_state_machine_futures(&mut exec, &mut iface_manager);
            assert_variant!(
                poll_sme_req(&mut exec, &mut _sme_stream),
                Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Connect{ req, txn, control_handle: _ }) => {
                    assert_eq!(req.ssid, TEST_SSID.as_bytes().to_vec());
                    assert_eq!(req.credential, fidl_fuchsia_wlan_sme::Credential::Password(TEST_PASSWORD.as_bytes().to_vec()));
                    let (_stream, ctrl) = txn.expect("connect txn unused")
                        .into_stream_and_control_handle().expect("error accessing control handle");
                    ctrl.send_on_finished(fidl_fuchsia_wlan_sme::ConnectResultCode::Success)
                        .expect("failed to send connection completion");
                }
            );

            // Run the state machine future again so that it acks the oneshot.
            run_state_machine_futures(&mut exec, &mut iface_manager);

            // Verify that the oneshot has been acked.
            pin_mut!(connect_response_fut);
            assert_variant!(exec.run_until_stalled(&mut connect_response_fut), Poll::Ready(Ok(())));
        }

        // Verify that the ClientIfaceContainer has been moved from unconfigured to configured.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(iface_manager.clients[0].config, Some(network_id.into()));
    }

    /// Tests the case where connect is called for a WPA3 connection and a client iface exists but
    /// does not support WPA3. The connect should fail without trying to connect.
    #[fuchsia::test]
    fn test_connect_wpa3_no_wpa3_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        let test_values = test_setup(&mut exec);
        // By default IfaceManager has an iface but not one with WPA3.
        let (mut iface_manager, mut _sme_stream) =
            create_iface_manager_with_client(&test_values, false);

        // Call connect on the IfaceManager
        let network = ap_types::NetworkIdentifier {
            ssid: b"some_ssid".to_vec(),
            type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa3,
        };
        let credential = Credential::Password(b"some_password".to_vec());

        let config = client_types::ConnectRequest {
            target: client_types::ConnectionCandidate {
                network,
                credential,
                observed_in_passive_scan: Some(true),
                bss: Some(generate_random_bss_desc()),
                multiple_bss_candidates: None,
            },
            reason: client_types::ConnectReason::FidlConnectRequest,
        };
        let connect_fut = iface_manager.connect(config);

        // Verify that the request to connect results in an error.
        pin_mut!(connect_fut);
        assert_variant!(exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where a connect is called and the WPA3 capable iface is configured.
    /// PhyManager should be asked for an iface that supports WPA3.
    #[fuchsia::test]
    fn test_connect_wpa3_with_configured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        // Build the connect request for connecting to the WPA3 network.
        let network = ap_types::NetworkIdentifier {
            ssid: b"some_wpa3_network".to_vec(),
            type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa3,
        };
        let credential = Credential::Password(b"password".to_vec());
        let connect_request = client_types::ConnectRequest {
            target: client_types::ConnectionCandidate {
                network: network.clone(),
                credential,
                observed_in_passive_scan: Some(true),
                bss: Some(generate_random_bss_desc()),
                multiple_bss_candidates: Some(true),
            },
            reason: client_types::ConnectReason::FidlConnectRequest,
        };

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        // Use a PhyManager that has a WPA3 client iface.
        iface_manager.phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: false,
            wpa3_iface: Some(0),
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        }));

        // Configure the mock CSM with the expected connect request
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: true,
            expected_connect_request: Some(connect_request.clone()),
        }));

        // Ask the IfaceManager to connect to a new network.
        let connect_response_fut = {
            let connect_fut = iface_manager.connect(connect_request);
            pin_mut!(connect_fut);

            // Run the connect request to completion.
            match exec.run_until_stalled(&mut connect_fut) {
                Poll::Ready(connect_result) => match connect_result {
                    Ok(receiver) => receiver.into_future(),
                    Err(e) => panic!("failed to connect with {}", e),
                },
                Poll::Pending => panic!("expected the connect request to finish"),
            }
        };

        // Start running the client state machine.
        run_state_machine_futures(&mut exec, &mut iface_manager);

        // Verify that the oneshot has been acked.
        pin_mut!(connect_response_fut);
        assert_variant!(exec.run_until_stalled(&mut connect_response_fut), Poll::Ready(Ok(())));

        // Verify that the ClientIfaceContainer has the correct config.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(iface_manager.clients[0].config, Some(network));
    }

    /// Tests the case where connect is called, but no client ifaces exist.
    #[fuchsia::test]
    fn test_connect_with_no_ifaces() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a PhyManager with no knowledge of any client ifaces.
        let test_values = test_setup(&mut exec);
        let phy_manager = create_empty_phy_manager(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );

        let mut iface_manager = IfaceManagerService::new(
            phy_manager,
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Call connect on the IfaceManager
        let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
        let connect_fut = iface_manager.connect(config);

        // Verify that the request to connect results in an error.
        pin_mut!(connect_fut);
        assert_variant!(exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where the PhyManager knows of a client iface, but the IfaceManager is not
    /// able to create an SME proxy for it.
    #[fuchsia::test]
    fn test_connect_sme_creation_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager and drop its client
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        let _ = iface_manager.clients.pop();

        // Drop the serving end of our device service proxy so that the request to create an SME
        // proxy fails.
        drop(test_values.device_service_stream);

        // Update the saved networks with knowledge of the test SSID and credentials.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        // Ask the IfaceManager to connect and make sure that it fails.
        let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
        let connect_fut = iface_manager.connect(config);

        pin_mut!(connect_fut);
        assert_variant!(exec.run_until_stalled(&mut connect_fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where disconnect is called on a configured client.
    #[fuchsia::test]
    fn test_disconnect_configured_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Issue a call to disconnect from the network.
            let network_id = ap_types::NetworkIdentifier {
                ssid: TEST_SSID.as_bytes().to_vec(),
                type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
            };
            let disconnect_fut = iface_manager
                .disconnect(network_id, client_types::DisconnectReason::NetworkUnsaved);

            // Ensure that disconnect returns a successful response.
            pin_mut!(disconnect_fut);
            assert_variant!(exec.run_until_stalled(&mut disconnect_fut), Poll::Ready(Ok(_)));
        }

        // Verify that the ClientIfaceContainer has been moved from configured to unconfigured.
        assert_eq!(iface_manager.clients.len(), 1);
        assert!(iface_manager.clients[0].config.is_none());
    }

    /// Tests the case where disconnect is called for a network for which the IfaceManager is not
    /// configured.  Verifies that the configured client is unaffected.
    #[fuchsia::test]
    fn test_disconnect_nonexistent_config() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a ClientIfaceContainer with a valid client.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Create a PhyManager with knowledge of a single client iface.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Issue a disconnect request for a bogus network configuration.
            let network_id = ap_types::NetworkIdentifier {
                ssid: "nonexistent_ssid".as_bytes().to_vec(),
                type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
            };
            let disconnect_fut = iface_manager
                .disconnect(network_id, client_types::DisconnectReason::NetworkUnsaved);

            // Ensure that the request returns immediately.
            pin_mut!(disconnect_fut);
            assert!(exec.run_until_stalled(&mut disconnect_fut).is_ready());
        }

        // Verify that the configured client has not been affected.
        assert_eq!(iface_manager.clients.len(), 1);
        assert!(iface_manager.clients[0].config.is_some());
    }

    /// Tests the case where disconnect is called and no client ifaces are present.
    #[fuchsia::test]
    fn test_disconnect_no_clients() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Call disconnect on the IfaceManager
        let network_id = ap_types::NetworkIdentifier {
            ssid: "nonexistent_ssid".as_bytes().to_vec(),
            type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
        };
        let disconnect_fut =
            iface_manager.disconnect(network_id, client_types::DisconnectReason::NetworkUnsaved);

        // Verify that disconnect returns immediately.
        pin_mut!(disconnect_fut);
        assert_variant!(exec.run_until_stalled(&mut disconnect_fut), Poll::Ready(Ok(_)));
    }

    /// Tests the case where the call to disconnect the client fails.
    #[fuchsia::test]
    fn test_disconnect_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Make the client state machine's disconnect call fail.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: true,
            expected_connect_request: None,
        }));

        // Call disconnect on the IfaceManager
        let network_id = ap_types::NetworkIdentifier {
            ssid: TEST_SSID.as_bytes().to_vec(),
            type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
        };
        let disconnect_fut =
            iface_manager.disconnect(network_id, client_types::DisconnectReason::NetworkUnsaved);

        pin_mut!(disconnect_fut);
        assert_variant!(exec.run_until_stalled(&mut disconnect_fut), Poll::Ready(Err(_)));
    }

    /// Tests stop_client_connections when there is a client that is connected.
    #[fuchsia::test]
    fn test_stop_connected_client() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients_enabled_time = Some(zx::Time::get_monotonic());

        // Create a PhyManager with a single, known client iface.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Stop all client connections.
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
        }

        // Ensure that no client interfaces are accounted for.
        assert!(iface_manager.clients.is_empty());

        // Ensure an update was sent
        let client_state_update = listener::ClientStateUpdate {
            state: Some(fidl_fuchsia_wlan_policy::WlanClientState::ConnectionsDisabled),
            networks: vec![],
        };
        assert_variant!(
            test_values.client_update_receiver.try_next(),
            Ok(Some(listener::Message::NotifyListeners(updates))) => {
            assert_eq!(updates, client_state_update);
        });

        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));

        // Ensure the client connections enabled time was reset to None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Call stop_client_connections when the only available client is unconfigured.
    #[fuchsia::test]
    fn test_stop_unconfigured_client() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients_enabled_time = Some(zx::Time::get_monotonic());

        // Create a PhyManager with one known client.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Call stop_client_connections.
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
        }

        // Ensure there are no remaining client ifaces.
        assert!(iface_manager.clients.is_empty());

        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));

        // Ensure the client connections enabled time was reset to None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where stop_client_connections is called, but there are no client ifaces.
    #[fuchsia::test]
    fn test_stop_no_clients() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);

        // Create and empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );
        iface_manager.clients_enabled_time = Some(zx::Time::get_monotonic());

        // Call stop_client_connections.
        {
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );

            // Ensure stop_client_connections returns immediately and is successful.
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
        }

        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));

        // Ensure the client connections enabled time was reset to None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where client connections are stopped, but stopping one of the client state
    /// machines fails.
    #[fuchsia::test]
    fn test_stop_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients_enabled_time = Some(zx::Time::get_monotonic());
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: true,
            expected_connect_request: None,
        }));

        // Create a PhyManager with a single, known client iface.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Stop all client connections.
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
        }

        // Ensure that no client interfaces are accounted for.
        assert!(iface_manager.clients.is_empty());

        // Regardless of whether or not stop succeeds or fails, a metric should be logged.
        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));

        // Ensure the client connections enabled time was reset to None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where the IfaceManager fails to tear down all of the client ifaces.
    #[fuchsia::test]
    fn test_stop_iface_destruction_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients_enabled_time = Some(zx::Time::get_monotonic());
        iface_manager.phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: false,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        }));

        // Create a PhyManager with a single, known client iface.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        {
            // Stop all client connections.
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Err(_)));
        }

        // Ensure that no client interfaces are accounted for.
        assert!(iface_manager.clients.is_empty());

        // Regardless of whether or not stop succeeds or fails, a metric should be logged.
        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));

        // Ensure the client connections enabled time was reset to None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where StopClientConnections is called when the client interfaces are already
    /// stopped.
    #[fuchsia::test]
    fn test_stop_client_when_already_stopped() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Call stop_client_connections.
        {
            let stop_fut = iface_manager.stop_client_connections(
                client_types::DisconnectReason::FidlStopClientConnectionsRequest,
            );

            // Ensure stop_client_connections returns immediately and is successful.
            pin_mut!(stop_fut);
            assert_variant!(exec.run_until_stalled(&mut stop_fut), Poll::Ready(Ok(_)));
        }

        // Ensure no metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Err(_));

        // Ensure the client connections enabled is None.
        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where an existing iface is marked as idle.
    #[fuchsia::test]
    fn test_mark_iface_idle() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Setup the client state machine so that it looks like it is no longer alive.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        assert!(iface_manager.clients[0].config.is_some());
        iface_manager.record_idle_client(TEST_CLIENT_IFACE_ID);
        assert!(iface_manager.clients[0].config.is_none());
    }

    /// Tests the case where a running and configured iface is marked as idle.
    #[fuchsia::test]
    fn test_mark_active_iface_idle() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        assert!(iface_manager.clients[0].config.is_some());

        // The request to mark the interface as idle should be ignored since the interface's state
        // machine is still running.
        iface_manager.record_idle_client(TEST_CLIENT_IFACE_ID);
        assert!(iface_manager.clients[0].config.is_some());
    }

    /// Tests the case where a non-existent iface is marked as idle.
    #[fuchsia::test]
    fn test_mark_nonexistent_iface_idle() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        assert!(iface_manager.clients[0].config.is_some());
        iface_manager.record_idle_client(123);
        assert!(iface_manager.clients[0].config.is_some());
    }

    /// Tests the case where an iface is not configured and has_idle_client is called.
    #[fuchsia::test]
    fn test_unconfigured_iface_idle_check() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (iface_manager, _) = create_iface_manager_with_client(&test_values, false);
        assert!(!iface_manager.idle_clients().is_empty());
    }

    /// Tests the case where an iface is configured and alive and has_idle_client is called.
    #[fuchsia::test]
    fn test_configured_alive_iface_idle_check() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        assert!(iface_manager.idle_clients().is_empty());
    }

    /// Tests the case where an iface is configured and dead and has_idle_client is called.
    #[fuchsia::test]
    fn test_configured_dead_iface_idle_check() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Make the client state machine's liveness check fail.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        assert!(!iface_manager.idle_clients().is_empty());
    }

    /// Tests the case where not ifaces are present and has_idle_client is called.
    #[fuchsia::test]
    fn test_no_ifaces_idle_check() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        let _ = iface_manager.clients.pop();
        assert!(iface_manager.idle_clients().is_empty());
    }

    /// Tests the case where starting client connections succeeds.
    #[fuchsia::test]
    fn test_start_clients_succeeds() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        {
            let start_fut = iface_manager.start_client_connections();

            // Ensure stop_client_connections returns immediately and is successful.
            pin_mut!(start_fut);
            assert_variant!(exec.run_until_stalled(&mut start_fut), Poll::Ready(Ok(_)));
        }

        // Ensure an update was sent
        let client_state_update = listener::ClientStateUpdate {
            state: Some(fidl_fuchsia_wlan_policy::WlanClientState::ConnectionsEnabled),
            networks: vec![],
        };
        assert_variant!(
            test_values.client_update_receiver.try_next(),
            Ok(Some(listener::Message::NotifyListeners(updates))) => {
            assert_eq!(updates, client_state_update);
        });

        assert!(iface_manager.clients_enabled_time.is_some());
    }

    /// Tests the case where starting client connections fails.
    #[fuchsia::test]
    fn test_start_clients_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok: false,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        }));

        {
            let start_fut = iface_manager.start_client_connections();
            pin_mut!(start_fut);
            assert_variant!(exec.run_until_stalled(&mut start_fut), Poll::Ready(Err(_)));
        }

        assert!(iface_manager.clients_enabled_time.is_none());
    }

    /// Tests the case where the IfaceManager is able to request that the AP state machine start
    /// the access point.
    #[fuchsia::test]
    fn test_start_ap_succeeds() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);

        {
            let fut = iface_manager.start_ap(config);

            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(_)));
        }

        assert!(iface_manager.aps[0].enabled_time.is_some());
    }

    /// Tests the case where the IfaceManager is not able to request that the AP state machine start
    /// the access point.
    #[fuchsia::test]
    fn test_start_ap_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: false, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);

        {
            let fut = iface_manager.start_ap(config);

            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }
    }

    /// Tests the case where start is called on the IfaceManager, but there are no AP ifaces.
    #[fuchsia::test]
    fn test_start_ap_no_ifaces() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Call start_ap.
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);
        let fut = iface_manager.start_ap(config);

        pin_mut!(fut);
        assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
    }

    /// Tests the case where stop_ap is called for a config that is accounted for by the
    /// IfaceManager.
    #[fuchsia::test]
    fn test_stop_ap_succeeds() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);
        iface_manager.aps[0].config = Some(config);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        {
            let fut = iface_manager
                .stop_ap(TEST_SSID.as_bytes().to_vec(), TEST_PASSWORD.as_bytes().to_vec());
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }
        assert!(iface_manager.aps.is_empty());

        // Ensure a metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where IfaceManager is requested to stop a config that is not accounted for.
    #[fuchsia::test]
    fn test_stop_ap_invalid_config() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        {
            let fut = iface_manager
                .stop_ap(TEST_SSID.as_bytes().to_vec(), TEST_PASSWORD.as_bytes().to_vec());
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }
        assert!(!iface_manager.aps.is_empty());

        // Ensure no metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Err(_));

        // Ensure the AP start time has not been cleared.
        assert!(iface_manager.aps[0].enabled_time.is_some());
    }

    /// Tests the case where IfaceManager attempts to stop the AP state machine, but the request
    /// fails.
    #[fuchsia::test]
    fn test_stop_ap_stop_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: false, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);
        iface_manager.aps[0].config = Some(config);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        {
            let fut = iface_manager
                .stop_ap(TEST_SSID.as_bytes().to_vec(), TEST_PASSWORD.as_bytes().to_vec());
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }

        assert!(iface_manager.aps.is_empty());

        // Ensure metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where IfaceManager stops the AP state machine, but the request to exit
    /// fails.
    #[fuchsia::test]
    fn test_stop_ap_exit_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: false };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);
        iface_manager.aps[0].config = Some(config);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        {
            let fut = iface_manager
                .stop_ap(TEST_SSID.as_bytes().to_vec(), TEST_PASSWORD.as_bytes().to_vec());
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }

        assert!(iface_manager.aps.is_empty());

        // Ensure metric was logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where stop is called on the IfaceManager, but there are no AP ifaces.
    #[fuchsia::test]
    fn test_stop_ap_no_ifaces() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );
        let fut =
            iface_manager.stop_ap(TEST_SSID.as_bytes().to_vec(), TEST_PASSWORD.as_bytes().to_vec());
        pin_mut!(fut);
        assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
    }

    /// Tests the case where stop_all_aps is called and it succeeds.
    #[fuchsia::test]
    fn test_stop_all_aps_succeeds() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        // Insert a second iface and add it to the list of APs.
        let second_iface = ApIfaceContainer {
            iface_id: 2,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: Some(zx::Time::get_monotonic()),
        };
        iface_manager.aps.push(second_iface);

        {
            let fut = iface_manager.stop_all_aps();
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }
        assert!(iface_manager.aps.is_empty());

        // Ensure metrics are logged for both AP interfaces.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where stop_all_aps is called and the request to stop fails for an iface.
    #[fuchsia::test]
    fn test_stop_all_aps_stop_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: false, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        // Insert a second iface and add it to the list of APs.
        let second_iface = ApIfaceContainer {
            iface_id: 2,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: Some(zx::Time::get_monotonic()),
        };
        iface_manager.aps.push(second_iface);

        {
            let fut = iface_manager.stop_all_aps();
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }
        assert!(iface_manager.aps.is_empty());

        // Ensure metrics are logged for both AP interfaces.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where stop_all_aps is called and the request to stop fails for an iface.
    #[fuchsia::test]
    fn test_stop_all_aps_exit_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: false };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        iface_manager.aps[0].enabled_time = Some(zx::Time::get_monotonic());

        // Insert a second iface and add it to the list of APs.
        let second_iface = ApIfaceContainer {
            iface_id: 2,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: Some(zx::Time::get_monotonic()),
        };
        iface_manager.aps.push(second_iface);

        {
            let fut = iface_manager.stop_all_aps();
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }
        assert!(iface_manager.aps.is_empty());

        // Ensure metrics are logged for both AP interfaces.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    /// Tests the case where stop_all_aps is called on the IfaceManager, but there are no AP
    /// ifaces.
    #[fuchsia::test]
    fn test_stop_all_aps_no_ifaces() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        let fut = iface_manager.stop_all_aps();
        pin_mut!(fut);
        assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));

        // Ensure no metrics are logged.
        assert_variant!(test_values.cobalt_receiver.try_next(), Err(_));
    }

    /// Tests the case where there is a single AP interface and it is asked to start twice and then
    /// asked to stop.
    #[fuchsia::test]
    fn test_start_ap_twice_then_stop() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);

        // Issue an initial start command.
        {
            let fut = iface_manager.start_ap(config);

            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(_)));
        }

        // Record the initial start time.
        let initial_start_time = iface_manager.aps[0].enabled_time.clone();

        // Now issue a second start command.
        let alternate_ssid = "some_other_ssid";
        let alternate_password = "some_other_password";
        let config = create_ap_config(alternate_ssid, alternate_password);
        {
            let fut = iface_manager.start_ap(config);

            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(_)));
        }

        // Verify that the start time has not been updated.
        assert_eq!(initial_start_time, iface_manager.aps[0].enabled_time);

        // Verify that no metric has been recorded.
        assert_variant!(test_values.cobalt_receiver.try_next(), Err(_));

        // Now issue a stop command.
        {
            let fut = iface_manager.stop_all_aps();
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }
        assert!(iface_manager.aps.is_empty());

        // Make sure the metric has been sent.
        assert_variant!(test_values.cobalt_receiver.try_next(), Ok(Some(_)));
    }

    #[fuchsia::test]
    fn test_recover_removed_client_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager with a client and an AP.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);
        let removed_iface_id = 123;
        iface_manager.clients[0].iface_id = removed_iface_id;

        let ap_iface = ApIfaceContainer {
            iface_id: TEST_AP_IFACE_ID,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: None,
        };
        iface_manager.aps.push(ap_iface);

        // Notify the IfaceManager that the client interface has been removed.
        {
            let fut = iface_manager.handle_removed_iface(removed_iface_id);
            pin_mut!(fut);

            // Expect a DeviceService request an SME proxy.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                exec.run_until_stalled(&mut test_values.device_service_stream.next()),
                Poll::Ready(Some(Ok(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
                }))) => {
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK)
                        .expect("failed to send AP SME response.");
                }
            );

            // Expected a DeviceService request to get driver features
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                exec.run_until_stalled(&mut test_values.device_service_stream.next()),
                Poll::Ready(Some(Ok(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_CLIENT_IFACE_ID, responder
                }))) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Client,
                        id: TEST_CLIENT_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Failed to send iface response");
                }
            );

            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        assert!(!iface_manager.aps.is_empty());

        // Verify that a new client interface was created.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(iface_manager.clients[0].iface_id, TEST_CLIENT_IFACE_ID);
    }

    #[fuchsia::test]
    fn test_client_iface_recovery_fails() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager with a client and an AP.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);
        let removed_iface_id = 123;
        iface_manager.clients[0].iface_id = removed_iface_id;

        let ap_iface = ApIfaceContainer {
            iface_id: TEST_AP_IFACE_ID,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: None,
        };
        iface_manager.aps.push(ap_iface);

        // Notify the IfaceManager that the client interface has been removed.
        {
            let fut = iface_manager.handle_removed_iface(removed_iface_id);
            pin_mut!(fut);

            // Expect a DeviceService request an SME proxy.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                exec.run_until_stalled(&mut test_values.device_service_stream.next()),
                Poll::Ready(Some(Ok(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
                }))) => {
                    responder
                        .send(fuchsia_zircon::sys::ZX_ERR_NOT_FOUND)
                        .expect("failed to send AP SME response.");
                }
            );

            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        assert!(!iface_manager.aps.is_empty());

        // Verify that a new client interface was created.
        assert!(iface_manager.clients.is_empty());
    }

    #[fuchsia::test]
    fn test_do_not_recover_removed_ap_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager with a client and an AP.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        let removed_iface_id = 123;
        let ap_iface = ApIfaceContainer {
            iface_id: removed_iface_id,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: None,
        };
        iface_manager.aps.push(ap_iface);

        // Notify the IfaceManager that the AP interface has been removed.
        {
            let fut = iface_manager.handle_removed_iface(removed_iface_id);
            pin_mut!(fut);

            // The future should now run to completion.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        assert!(!iface_manager.clients.is_empty());

        // Verify that a new AP interface was not created.
        assert!(iface_manager.aps.is_empty());
    }

    #[fuchsia::test]
    fn test_remove_nonexistent_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManager with a client and an AP.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        let ap_iface = ApIfaceContainer {
            iface_id: TEST_AP_IFACE_ID,
            config: None,
            ap_state_machine: Box::new(FakeAp {
                start_succeeds: true,
                stop_succeeds: true,
                exit_succeeds: true,
            }),
            enabled_time: None,
        };
        iface_manager.aps.push(ap_iface);

        // Notify the IfaceManager that an interface that has not been accounted for has been
        // removed.
        {
            let fut = iface_manager.handle_removed_iface(1234);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        assert!(!iface_manager.clients.is_empty());
        assert!(!iface_manager.aps.is_empty());
    }

    fn poll_device_service_req(
        exec: &mut fuchsia_async::TestExecutor,
        next_req: &mut StreamFuture<fidl_fuchsia_wlan_device_service::DeviceServiceRequestStream>,
    ) -> Poll<fidl_fuchsia_wlan_device_service::DeviceServiceRequest> {
        exec.run_until_stalled(next_req).map(|(req, stream)| {
            *next_req = stream.into_future();
            req.expect("did not expect the SME request stream to end")
                .expect("error polling SME request stream")
        })
    }

    #[fuchsia::test]
    fn test_add_client_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        {
            // Notify the IfaceManager of a new interface.
            let fut = iface_manager.handle_added_iface(TEST_CLIENT_IFACE_ID);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            // Expect and interface query and notify that this is a client interface.
            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_CLIENT_IFACE_ID, responder
                }) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Client,
                        id: TEST_CLIENT_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Sending iface response");
                }
            );

            // Expect that we have requested a client SME proxy from get_client.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
                }) => {
                    // Send back a positive acknowledgement.
                    assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
                }
            );

            // Expect a QueryIface request for the new iface's driver features and respond to it.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_CLIENT_IFACE_ID, responder
                }) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Client,
                        id: TEST_CLIENT_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Sending iface response");
                }
            );

            // Expect that we have requested a client SME proxy from creating the client state
            // machine.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
                }) => {
                    // Send back a positive acknowledgement.
                    assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
                }
            );

            // Run the future to completion.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }

        // Ensure that the client interface has been added.
        assert!(iface_manager.aps.is_empty());
        assert_eq!(iface_manager.clients[0].iface_id, TEST_CLIENT_IFACE_ID);
    }

    #[fuchsia::test]
    fn test_add_ap_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        {
            // Notify the IfaceManager of a new interface.
            let fut = iface_manager.handle_added_iface(TEST_AP_IFACE_ID);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            // Expect that the interface properties are queried and notify that it is an AP iface.
            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_AP_IFACE_ID, responder
                }) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Ap,
                        id: TEST_AP_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Sending iface response");
                }
            );

            // Run the future so that an AP SME proxy is requested.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            let responder = assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetApSme {
                    iface_id: TEST_AP_IFACE_ID, sme: _, responder
                }) => responder
            );

            // Send back a positive acknowledgement.
            assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());

            // Run the future to completion.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }

        // Ensure that the AP interface has been added.
        assert!(iface_manager.clients.is_empty());
        assert_eq!(iface_manager.aps[0].iface_id, TEST_AP_IFACE_ID);
    }

    #[fuchsia::test]
    fn test_add_nonexistent_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks,
            test_values.network_selector,
            test_values.cobalt_api,
        );

        {
            // Notify the IfaceManager of a new interface.
            let fut = iface_manager.handle_added_iface(TEST_AP_IFACE_ID);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            // Expect an iface query and send back an error
            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_AP_IFACE_ID, responder
                }) => {
                    responder
                        .send(fuchsia_zircon::sys::ZX_ERR_NOT_FOUND, None)
                        .expect("Sending iface response");
                }
            );

            // Run the future to completion.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Err(_)));
        }

        // Ensure that no interfaces have been added.
        assert!(iface_manager.clients.is_empty());
        assert!(iface_manager.aps.is_empty());
    }

    #[fuchsia::test]
    fn test_add_existing_client_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        // Notify the IfaceManager of a new interface.
        {
            let fut = iface_manager.handle_added_iface(TEST_CLIENT_IFACE_ID);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            // Expect an interface query and notify that it is a client.
            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_CLIENT_IFACE_ID, responder
                }) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Client,
                        id: TEST_CLIENT_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Sending iface response");
                }
            );

            // The future should then run to completion as it finds the existing interface.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }

        // Verify that nothing new has been appended to the clients vector or the aps vector.
        assert_eq!(iface_manager.clients.len(), 1);
        assert_eq!(iface_manager.aps.len(), 0);
    }

    #[fuchsia::test]
    fn test_add_existing_ap_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);

        // Notify the IfaceManager of a new interface.
        {
            let fut = iface_manager.handle_added_iface(TEST_AP_IFACE_ID);
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            // Expect an interface query and notify that it is a client.
            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                    iface_id: TEST_AP_IFACE_ID, responder
                }) => {
                    let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                        role: fidl_fuchsia_wlan_device::MacRole::Ap,
                        id: TEST_AP_IFACE_ID,
                        phy_id: 0,
                        phy_assigned_id: 0,
                        mac_addr: [0; 6],
                        driver_features: Vec::new(),
                    };
                    responder
                        .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                        .expect("Sending iface response");
                }
            );

            // The future should then run to completion as it finds the existing interface.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(Ok(())));
        }

        // Verify that nothing new has been appended to the clients vector or the aps vector.
        assert_eq!(iface_manager.clients.len(), 0);
        assert_eq!(iface_manager.aps.len(), 1);
    }

    enum TestType {
        Pass,
        Fail,
        ClientError,
    }

    fn run_service_test<T: std::fmt::Debug>(
        exec: &mut fuchsia_async::TestExecutor,
        network_selector: Arc<NetworkSelector>,
        iface_manager: IfaceManagerService,
        req: IfaceManagerRequest,
        mut req_receiver: oneshot::Receiver<Result<T, Error>>,
        device_service_stream: fidl_fuchsia_wlan_device_service::DeviceServiceRequestStream,
        test_type: TestType,
    ) {
        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));

        // Start the service loop
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Send the client's request
        sender.try_send(req).expect("failed to send request");

        // Service any device service requests in the event that a new client SME proxy is required
        // for the operation under test.
        let mut device_service_fut = device_service_stream.into_future();
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
        match poll_device_service_req(exec, &mut device_service_fut) {
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                iface_id: TEST_CLIENT_IFACE_ID,
                sme: _,
                responder,
            }) => {
                // Send back a positive acknowledgement.
                assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
            }
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetApSme {
                iface_id: TEST_AP_IFACE_ID,
                sme: _,
                responder,
            }) => {
                // Send back a positive acknowledgement.
                assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
            }
            _ => {}
        }

        match test_type {
            TestType::Pass => {
                // Process the request.
                assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

                // Assert that the receiving end gets a successful result.
                assert_variant!(exec.run_until_stalled(&mut req_receiver), Poll::Ready(Ok(Ok(_))));
            }
            TestType::Fail => {
                // Process the request.
                assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

                // Assert that the receiving end gets a successful result.
                assert_variant!(exec.run_until_stalled(&mut req_receiver), Poll::Ready(Ok(Err(_))));
            }
            TestType::ClientError => {
                // Simulate a client failure.
                drop(req_receiver);
            }
        }

        // Make sure the service keeps running.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
    }

    fn run_service_test_with_unit_return(
        exec: &mut fuchsia_async::TestExecutor,
        network_selector: Arc<NetworkSelector>,
        iface_manager: IfaceManagerService,
        req: IfaceManagerRequest,
        mut req_receiver: oneshot::Receiver<()>,
        test_type: TestType,
    ) {
        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));

        // Start the service loop
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Send the client's request
        sender.try_send(req).expect("failed to send request");

        match test_type {
            TestType::Pass => {
                // Process the request.
                assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

                // Assert that the receiving end gets a successful result.
                assert_variant!(exec.run_until_stalled(&mut req_receiver), Poll::Ready(Ok(())));
            }
            TestType::Fail => {
                // Process the request.
                assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

                // Assert that the receiving end gets a successful result.
                assert_variant!(exec.run_until_stalled(&mut req_receiver), Poll::Ready(Ok(())));
            }
            TestType::ClientError => {
                // Simulate a client failure.
                drop(req_receiver);
            }
        }

        // Make sure the service keeps running.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
    }

    #[test_case(FakeClient {disconnect_ok: true, is_alive:true, expected_connect_request: None},
        TestType::Pass; "successfully disconnects configured client")]
    #[test_case(FakeClient {disconnect_ok: false, is_alive:true, expected_connect_request: None},
        TestType::Fail; "fails to disconnect configured client")]
    #[test_case(FakeClient {disconnect_ok: true, is_alive:true, expected_connect_request: None},
        TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_disconnect_test(fake_client: FakeClient, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients[0].client_state_machine = Some(Box::new(fake_client));

        // Send a disconnect request.
        let (ack_sender, ack_receiver) = oneshot::channel();
        let req = DisconnectRequest {
            network_id: fidl_fuchsia_wlan_policy::NetworkIdentifier {
                ssid: TEST_SSID.as_bytes().to_vec(),
                type_: fidl_fuchsia_wlan_policy::SecurityType::Wpa,
            },
            reason: client_types::DisconnectReason::NetworkUnsaved,
            responder: ack_sender,
        };
        let req = IfaceManagerRequest::Disconnect(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            ack_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(FakeClient {disconnect_ok: true, is_alive:true, expected_connect_request: Some(create_connect_request(TEST_SSID, TEST_PASSWORD))},
        TestType::Pass; "successfully connected a client")]
    #[test_case(FakeClient {disconnect_ok: true, is_alive:true, expected_connect_request: Some(create_connect_request(TEST_SSID, TEST_PASSWORD))},
        TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_connect_test(fake_client: FakeClient, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _stream) = create_iface_manager_with_client(&test_values, false);
        let connect_req = fake_client.expected_connect_request.clone().unwrap();
        iface_manager.clients[0].client_state_machine = Some(Box::new(fake_client));

        // Send a connect request.
        let (ack_sender, ack_receiver) = oneshot::channel();
        let req = ConnectRequest { request: connect_req, responder: ack_sender };
        let req = IfaceManagerRequest::Connect(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            ack_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    // This test is a bit of a twofer as it covers both the mechanism for recording idle interfaces
    // as well as the mechanism for querying idle interfaces.
    #[fuchsia::test]
    fn test_service_record_idle_client() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);

        // Make the client state machine's liveness check fail.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let network_selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks,
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create mpsc channel to handle requests.
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Send an idle interface request
        let (ack_sender, mut ack_receiver) = oneshot::channel();
        let req = RecordIdleIfaceRequest { iface_id: TEST_CLIENT_IFACE_ID, responder: ack_sender };
        let req = IfaceManagerRequest::RecordIdleIface(req);

        sender.try_send(req).expect("failed to send request");

        // Run the service loop and expect the request to be serviced and for the loop to not exit.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

        // Wait for the response.
        assert_variant!(exec.run_until_stalled(&mut ack_receiver), Poll::Ready(Ok(())));

        // Check if an idle interface is present.
        let (idle_iface_sender, mut idle_iface_receiver) = oneshot::channel();
        let req = HasIdleIfaceRequest { responder: idle_iface_sender };
        let req = IfaceManagerRequest::HasIdleIface(req);
        sender.try_send(req).expect("failed to send request");

        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

        // Make sure that the interface has been marked idle.
        assert_variant!(exec.run_until_stalled(&mut idle_iface_receiver), Poll::Ready(Ok(true)));
    }

    #[fuchsia::test]
    fn test_service_record_idle_client_response_failure() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);

        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let network_selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks,
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create mpsc channel to handle requests.
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Send an idle interface request
        let (ack_sender, ack_receiver) = oneshot::channel();
        let req = RecordIdleIfaceRequest { iface_id: TEST_CLIENT_IFACE_ID, responder: ack_sender };
        let req = IfaceManagerRequest::RecordIdleIface(req);

        sender.try_send(req).expect("failed to send request");

        // Drop the receiving end and make sure the service continues running.
        drop(ack_receiver);

        // Run the service loop and expect the request to be serviced and for the loop to not exit.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
    }

    #[fuchsia::test]
    fn test_service_query_idle_client_response_failure() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);

        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let network_selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks,
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create mpsc channel to handle requests.
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Check if an idle interface is present.
        let (idle_iface_sender, idle_iface_receiver) = oneshot::channel();
        let req = HasIdleIfaceRequest { responder: idle_iface_sender };
        let req = IfaceManagerRequest::HasIdleIface(req);
        sender.try_send(req).expect("failed to send request");

        // Drop the receiving end and make sure the service continues running.
        drop(idle_iface_receiver);

        // Run the service loop and expect the request to be serviced and for the loop to not exit.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
    }

    #[derive(Debug)]
    struct FakeIfaceManagerRequester {
        scan_proxy_requested: bool,
    }

    impl FakeIfaceManagerRequester {
        fn new() -> Self {
            FakeIfaceManagerRequester { scan_proxy_requested: false }
        }
    }

    #[async_trait]
    impl IfaceManagerApi for FakeIfaceManagerRequester {
        async fn disconnect(
            &mut self,
            _network_id: types::NetworkIdentifier,
            _reason: client_types::DisconnectReason,
        ) -> Result<(), Error> {
            unimplemented!()
        }

        async fn connect(
            &mut self,
            _connect_req: client_types::ConnectRequest,
        ) -> Result<oneshot::Receiver<()>, Error> {
            unimplemented!()
        }

        async fn record_idle_client(&mut self, _iface_id: u16) -> Result<(), Error> {
            unimplemented!()
        }

        async fn has_idle_client(&mut self) -> Result<bool, Error> {
            unimplemented!()
        }

        async fn handle_added_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
            unimplemented!()
        }

        async fn handle_removed_iface(&mut self, _iface_id: u16) -> Result<(), Error> {
            unimplemented!()
        }

        async fn scan(
            &mut self,
            _scan_request: fidl_fuchsia_wlan_sme::ScanRequest,
        ) -> Result<fidl_fuchsia_wlan_sme::ScanTransactionProxy, Error> {
            unimplemented!()
        }

        async fn get_sme_proxy_for_scan(
            &mut self,
        ) -> Result<fidl_fuchsia_wlan_sme::ClientSmeProxy, Error> {
            self.scan_proxy_requested = true;
            Err(format_err!("scan failed"))
        }

        async fn stop_client_connections(
            &mut self,
            _reason: client_types::DisconnectReason,
        ) -> Result<(), Error> {
            unimplemented!()
        }

        async fn start_client_connections(&mut self) -> Result<(), Error> {
            unimplemented!()
        }

        async fn start_ap(
            &mut self,
            _config: ap_fsm::ApConfig,
        ) -> Result<oneshot::Receiver<()>, Error> {
            unimplemented!()
        }

        async fn stop_ap(&mut self, _ssid: Vec<u8>, _password: Vec<u8>) -> Result<(), Error> {
            unimplemented!()
        }

        async fn stop_all_aps(&mut self) -> Result<(), Error> {
            unimplemented!()
        }

        async fn has_wpa3_capable_client(&mut self) -> Result<bool, Error> {
            Ok(true)
        }

        async fn set_country(
            &mut self,
            _country_code: Option<[u8; REGION_CODE_LEN]>,
        ) -> Result<(), Error> {
            unimplemented!()
        }
    }

    #[fuchsia::test]
    fn test_service_add_iface_succeeds() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks.clone(),
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Create other components to run the service.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let network_selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks,
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create mpsc channel to handle requests.
        let (mut sender, receiver) = mpsc::channel(1);
        let serve_fut = serve_iface_manager_requests(
            iface_manager,
            iface_manager_client,
            network_selector,
            receiver,
        );
        pin_mut!(serve_fut);

        // Report a new interface.
        let (new_iface_sender, mut new_iface_receiver) = oneshot::channel();
        let req = AddIfaceRequest { iface_id: TEST_CLIENT_IFACE_ID, responder: new_iface_sender };
        let req = IfaceManagerRequest::AddIface(req);
        sender.try_send(req).expect("failed to send request");

        // Run the service loop to begin processing the request.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

        // Expect and interface query and notify that this is a client interface.
        let mut device_service_fut = test_values.device_service_stream.into_future();
        assert_variant!(
            poll_device_service_req(&mut exec, &mut device_service_fut),
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                iface_id: TEST_CLIENT_IFACE_ID, responder
            }) => {
                let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                    role: fidl_fuchsia_wlan_device::MacRole::Client,
                    id: TEST_CLIENT_IFACE_ID,
                    phy_id: 0,
                    phy_assigned_id: 0,
                    mac_addr: [0; 6],
                    driver_features: Vec::new(),
                };
                responder
                    .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                    .expect("Sending iface response");
            }
        );

        // Expect that we have requested a client SME proxy from get_client.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
        assert_variant!(
            poll_device_service_req(&mut exec, &mut device_service_fut),
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
            }) => {
                // Send back a positive acknowledgement.
                assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
            }
        );

        // Expect that we have queried an iface from get_client creating a new IfaceContainer.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
        assert_variant!(
            poll_device_service_req(&mut exec, &mut device_service_fut),
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::QueryIface {
                iface_id: TEST_CLIENT_IFACE_ID, responder
            }) => {
                let mut response = fidl_fuchsia_wlan_device_service::QueryIfaceResponse {
                    role: fidl_fuchsia_wlan_device::MacRole::Client,
                    id: TEST_CLIENT_IFACE_ID,
                    phy_id: 0,
                    phy_assigned_id: 0,
                    mac_addr: [0; 6],
                    driver_features: Vec::new(),
                };
                responder
                    .send(fuchsia_zircon::sys::ZX_OK, Some(&mut response))
                    .expect("Sending iface response");
            }
        );

        // Expect that we have requested a client SME proxy from creating the client state machine.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);
        assert_variant!(
            poll_device_service_req(&mut exec, &mut device_service_fut),
            Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                iface_id: TEST_CLIENT_IFACE_ID, sme: _, responder
            }) => {
                // Send back a positive acknowledgement.
                assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
            }
        );

        // Run the service again to ensure the response is sent.
        assert_variant!(exec.run_until_stalled(&mut serve_fut), Poll::Pending);

        // Check that the response was received.
        assert_variant!(exec.run_until_stalled(&mut new_iface_receiver), Poll::Ready(Ok(())));
    }

    #[test_case(TestType::Fail; "failed to add interface")]
    #[test_case(TestType::ClientError; "client dropped receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_add_iface_negative_tests(test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let phy_manager = phy_manager::PhyManager::new(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api,
        );

        // Report a new interface.
        let (new_iface_sender, new_iface_receiver) = oneshot::channel();
        let req = AddIfaceRequest { iface_id: TEST_CLIENT_IFACE_ID, responder: new_iface_sender };
        let req = IfaceManagerRequest::AddIface(req);

        // Drop the device stream so that querying the interface properties will fail.
        drop(test_values.device_service_stream);

        run_service_test_with_unit_return(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            new_iface_receiver,
            test_type,
        );
    }

    #[test_case(TestType::Pass; "successfully removed iface")]
    #[test_case(TestType::ClientError; "client dropped receiving end")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_remove_iface_test(test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);

        // Notify of interface removal.
        let (remove_iface_sender, remove_iface_receiver) = oneshot::channel();
        let req = RemoveIfaceRequest { iface_id: 123, responder: remove_iface_sender };
        let req = IfaceManagerRequest::RemoveIface(req);

        run_service_test_with_unit_return(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            remove_iface_receiver,
            test_type,
        );
    }

    #[test_case(TestType::Pass; "successfully scanned")]
    #[test_case(TestType::Fail; "failed to scanned")]
    #[test_case(TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_scan_test(test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (iface_manager, _stream) = match test_type {
            TestType::Pass | TestType::ClientError => {
                let (iface_manager, stream) = create_iface_manager_with_client(&test_values, true);
                (iface_manager, Some(stream))
            }
            TestType::Fail => {
                let phy_manager = phy_manager::PhyManager::new(
                    test_values.device_service_proxy.clone(),
                    test_values.monitor_service_proxy.clone(),
                    test_values.node,
                );
                let iface_manager = IfaceManagerService::new(
                    Arc::new(Mutex::new(phy_manager)),
                    test_values.client_update_sender,
                    test_values.ap_update_sender,
                    test_values.device_service_proxy,
                    test_values.saved_networks.clone(),
                    test_values.network_selector.clone(),
                    test_values.cobalt_api,
                );
                (iface_manager, None)
            }
        };

        // Make a scan request.
        let (scan_sender, scan_receiver) = oneshot::channel();
        let req = ScanRequest {
            scan_request: fidl_fuchsia_wlan_sme::ScanRequest::Passive(
                fidl_fuchsia_wlan_sme::PassiveScanRequest {},
            ),
            responder: scan_sender,
        };
        let req = IfaceManagerRequest::Scan(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            scan_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(
        FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::Pass;
        "successfully started client connections"
    )]
    #[test_case(
        FakePhyManager {
            create_iface_ok: false,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::Fail;
        "failed to start client connections"
    )]
    #[test_case(
        FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::ClientError;
        "client dropped receiver"
    )]
    #[fuchsia::test(add_test_attr = false)]
    fn service_start_client_connections_test(phy_manager: FakePhyManager, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api,
        );

        // Make start client connections request
        let (start_sender, start_receiver) = oneshot::channel();
        let req = StartClientConnectionsRequest { responder: start_sender };
        let req = IfaceManagerRequest::StartClientConnections(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            start_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(
        FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::Pass;
        "successfully stopped client connections"
    )]
    #[test_case(
        FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: false,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::Fail;
        "failed to stop client connections"
    )]
    #[test_case(
        FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true
        },
        TestType::ClientError;
        "client dropped receiver"
    )]
    #[fuchsia::test(add_test_attr = false)]
    fn service_stop_client_connections_test(phy_manager: FakePhyManager, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);

        // Create an empty PhyManager and IfaceManager.
        let iface_manager = IfaceManagerService::new(
            Arc::new(Mutex::new(phy_manager)),
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api,
        );

        // Make stop client connections request
        let (stop_sender, stop_receiver) = oneshot::channel();
        let req = StopClientConnectionsRequest {
            responder: stop_sender,
            reason: client_types::DisconnectReason::FidlStopClientConnectionsRequest,
        };
        let req = IfaceManagerRequest::StopClientConnections(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            stop_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::Pass; "successfully starts AP")]
    #[test_case(FakeAp { start_succeeds: false, stop_succeeds: true, exit_succeeds: true }, TestType::Fail; "fails to start AP")]
    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_start_ap_test(fake_ap: FakeAp, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an IfaceManager with a fake AP interface.
        let iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);

        // Request that an AP be started.
        let (start_sender, start_receiver) = oneshot::channel();
        let req = StartApRequest {
            config: create_ap_config(TEST_SSID, TEST_PASSWORD),
            responder: start_sender,
        };
        let req = IfaceManagerRequest::StartAp(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            start_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::Pass; "successfully stops AP")]
    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: false, exit_succeeds: true }, TestType::Fail; "fails to stop AP")]
    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_stop_ap_test(fake_ap: FakeAp, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an IfaceManager with a configured fake AP interface.
        let mut iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);
        let config = create_ap_config(TEST_SSID, TEST_PASSWORD);
        iface_manager.aps[0].config = Some(config);

        // Request that an AP be stopped.
        let (stop_sender, stop_receiver) = oneshot::channel();
        let req = StopApRequest {
            ssid: TEST_SSID.as_bytes().to_vec(),
            password: TEST_PASSWORD.as_bytes().to_vec(),
            responder: stop_sender,
        };
        let req = IfaceManagerRequest::StopAp(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            stop_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::Pass; "successfully stops AP")]
    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: false, exit_succeeds: true }, TestType::Fail; "fails to stop AP")]
    #[test_case(FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true }, TestType::ClientError; "client drops receiver")]
    #[fuchsia::test(add_test_attr = false)]
    fn service_stop_all_aps_test(fake_ap: FakeAp, test_type: TestType) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an IfaceManager with a fake AP interface.
        let iface_manager = create_iface_manager_with_ap(&test_values, fake_ap);

        // Request that an AP be started.
        let (stop_sender, stop_receiver) = oneshot::channel();
        let req = StopAllApsRequest { responder: stop_sender };
        let req = IfaceManagerRequest::StopAllAps(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            stop_receiver,
            test_values.device_service_stream,
            test_type,
        );
    }

    /// Tests the case where the IfaceManager attempts to reconnect a client interface that has
    /// disconnected.
    #[fuchsia::test]
    fn test_reconnect_disconnected_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        // Make the client state machine report that it is dead.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: false,
            expected_connect_request: None,
        }));

        let temp_dir = TempDir::new().expect("failed to create temporary directory");
        let path = temp_dir.path().join(rand_string());
        let tmp_path = temp_dir.path().join(rand_string());
        let (saved_networks, mut stash_server) =
            exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
        test_values.saved_networks = Arc::new(saved_networks);

        // Update the saved networks with knowledge of the test SSID and credentials.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let save_network_fut = test_values.saved_networks.store(network_id, credential);
        pin_mut!(save_network_fut);
        assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

        process_stash_write(&mut exec, &mut stash_server);

        // Ask the IfaceManager to reconnect.
        let mut sme_stream = {
            let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
            let reconnect_fut =
                iface_manager.attempt_client_reconnect(TEST_CLIENT_IFACE_ID, config);
            pin_mut!(reconnect_fut);
            assert_variant!(exec.run_until_stalled(&mut reconnect_fut), Poll::Pending);

            // There should be a request for a client SME proxy.
            let mut device_service_fut = test_values.device_service_stream.into_future();
            let sme_server = assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme, responder
                }) => {
                    assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());
                    sme
                }
            );

            // The reconnect future should finish up.
            assert_variant!(exec.run_until_stalled(&mut reconnect_fut), Poll::Ready(Ok(())));

            sme_server.into_stream().unwrap().into_future()
        };

        // Start running the new state machine.
        run_state_machine_futures(&mut exec, &mut iface_manager);

        // Acknowledge the disconnection attempt.
        assert_variant!(
            poll_sme_req(&mut exec, &mut sme_stream),
            Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Disconnect{ responder, reason: fidl_fuchsia_wlan_sme::UserDisconnectReason::Startup }) => {
                responder.send().expect("could not send response")
            }
        );

        // Make sure that the connect request has been sent out.
        run_state_machine_futures(&mut exec, &mut iface_manager);
        assert_variant!(
            poll_sme_req(&mut exec, &mut sme_stream),
            Poll::Ready(fidl_fuchsia_wlan_sme::ClientSmeRequest::Connect{ req, txn, control_handle: _ }) => {
                assert_eq!(req.ssid, TEST_SSID.as_bytes().to_vec());
                assert_eq!(req.credential, fidl_fuchsia_wlan_sme::Credential::Password(TEST_PASSWORD.as_bytes().to_vec()));
                let (_stream, ctrl) = txn.expect("connect txn unused")
                    .into_stream_and_control_handle().expect("error accessing control handle");
                ctrl.send_on_finished(fidl_fuchsia_wlan_sme::ConnectResultCode::Success)
                    .expect("failed to send connection completion");
            }
        );

        // Verify that the state machine future is still alive.
        run_state_machine_futures(&mut exec, &mut iface_manager);
        assert!(!iface_manager.fsm_futures.is_empty());
    }

    /// Tests the case where the IfaceManager attempts to reconnect a client interface that does
    /// not exist.  This simulates the case where the client state machine exits because client
    /// connections have been stopped.
    #[fuchsia::test]
    fn test_reconnect_nonexistent_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an empty IfaceManager
        let test_values = test_setup(&mut exec);
        let phy_manager = create_empty_phy_manager(
            test_values.device_service_proxy.clone(),
            test_values.monitor_service_proxy.clone(),
            test_values.node,
        );
        let mut iface_manager = IfaceManagerService::new(
            phy_manager,
            test_values.client_update_sender,
            test_values.ap_update_sender,
            test_values.device_service_proxy,
            test_values.saved_networks.clone(),
            test_values.network_selector,
            test_values.cobalt_api,
        );

        // Update the saved networks with knowledge of the test SSID and credentials.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        assert!(exec
            .run_singlethreaded(test_values.saved_networks.store(network_id, credential))
            .expect("failed to store a network password")
            .is_none());

        // Ask the IfaceManager to reconnect.
        {
            let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
            let reconnect_fut =
                iface_manager.attempt_client_reconnect(TEST_CLIENT_IFACE_ID, config);
            pin_mut!(reconnect_fut);
            assert_variant!(exec.run_until_stalled(&mut reconnect_fut), Poll::Ready(Ok(())));
        }

        // Ensure that there are no new state machines.
        assert!(iface_manager.fsm_futures.is_empty());
    }

    /// Tests the case where the IfaceManager attempts to reconnect a client interface that is
    /// already connected to another networks.  This simulates the case where a client state
    /// machine exits because a new connect request has come in.
    #[fuchsia::test]
    fn test_reconnect_connected_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);
        let (mut iface_manager, _sme_stream) = create_iface_manager_with_client(&test_values, true);

        // Make the client state machine report that it is alive.
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: false,
            is_alive: true,
            expected_connect_request: None,
        }));

        let temp_dir = TempDir::new().expect("failed to create temporary directory");
        let path = temp_dir.path().join(rand_string());
        let tmp_path = temp_dir.path().join(rand_string());
        let (saved_networks, mut stash_server) =
            exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
        test_values.saved_networks = Arc::new(saved_networks);

        // Update the saved networks with knowledge of the test SSID and credentials.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let save_network_fut = test_values.saved_networks.store(network_id, credential);
        pin_mut!(save_network_fut);
        assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

        process_stash_write(&mut exec, &mut stash_server);

        // Ask the IfaceManager to reconnect.
        {
            let config = create_connect_request(TEST_SSID, TEST_PASSWORD);
            let reconnect_fut =
                iface_manager.attempt_client_reconnect(TEST_CLIENT_IFACE_ID, config);
            pin_mut!(reconnect_fut);
            assert_variant!(exec.run_until_stalled(&mut reconnect_fut), Poll::Ready(Ok(())));
        }

        // Ensure that there are no new state machines.
        assert!(iface_manager.fsm_futures.is_empty());
    }

    enum NetworkSelectionMissingAttribute {
        AllAttributesPresent,
        IdleClient,
        SavedNetwork,
        NetworkSelectionInProgress,
    }

    #[test_case(NetworkSelectionMissingAttribute::AllAttributesPresent; "scan is requested")]
    #[test_case(NetworkSelectionMissingAttribute::IdleClient; "no idle clients")]
    #[test_case(NetworkSelectionMissingAttribute::SavedNetwork; "no saved networks")]
    #[test_case(NetworkSelectionMissingAttribute::NetworkSelectionInProgress; "selection already in progress")]
    #[fuchsia::test(add_test_attr = false)]
    fn test_initiate_network_selection(test_type: NetworkSelectionMissingAttribute) {
        // Start out by setting the test up such that we would expect a scan to be requested.
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let mut test_values = test_setup(&mut exec);

        // Insert a saved network.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let mut stash_server = {
            let temp_dir = TempDir::new().expect("failed to create temporary directory");
            let path = temp_dir.path().join(rand_string());
            let tmp_path = temp_dir.path().join(rand_string());
            let (saved_networks, mut stash_server) =
                exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
            test_values.saved_networks = Arc::new(saved_networks);

            // Update the saved networks with knowledge of the test SSID and credentials.
            let save_network_fut =
                test_values.saved_networks.store(network_id.clone(), credential.clone());
            pin_mut!(save_network_fut);
            assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

            process_stash_write(&mut exec, &mut stash_server);

            stash_server
        };

        // Make the client state machine report that it is not alive.
        let (mut iface_manager, _sme_stream) = create_iface_manager_with_client(&test_values, true);
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));

        // Create an empty FuturesUnordered to hold the network selection request.
        let mut network_selection_futures = FuturesUnordered::<
            BoxFuture<'static, Option<client_types::ConnectionCandidate>>,
        >::new();

        // Create a network selector to be used by the network selection request.
        let selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks.clone(),
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Setup the test to prevent a network selection from happening for whatever reason was specified.
        match test_type {
            NetworkSelectionMissingAttribute::AllAttributesPresent => {}
            NetworkSelectionMissingAttribute::IdleClient => {
                // Make the client state machine report that it is alive.
                iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
                    disconnect_ok: true,
                    is_alive: true,
                    expected_connect_request: None,
                }));
            }
            NetworkSelectionMissingAttribute::SavedNetwork => {
                // Remove the saved network so that there are no known networks to connect to.
                let remove_network_fut = test_values.saved_networks.remove(network_id, credential);
                pin_mut!(remove_network_fut);
                assert_variant!(exec.run_until_stalled(&mut remove_network_fut), Poll::Pending);
                process_stash_delete(&mut exec, &mut stash_server);
            }
            NetworkSelectionMissingAttribute::NetworkSelectionInProgress => {
                // Insert a future so that it looks like a scan is in progress.
                network_selection_futures.push(ready(None).boxed());
            }
        }

        {
            // Run the future to completion.
            let fut = initiate_network_selection(
                &iface_manager,
                iface_manager_client.clone(),
                selector,
                &mut network_selection_futures,
            );
            pin_mut!(fut);
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        // Run all network_selection futures to completion.
        for mut network_selection_future in network_selection_futures.iter_mut() {
            assert_variant!(exec.run_until_stalled(&mut network_selection_future), Poll::Ready(_));
        }

        // Check the outcome based on the expected failure mode.
        let fut = iface_manager_client.lock();
        pin_mut!(fut);
        let iface_manager_client = assert_variant!(
            exec.run_until_stalled(&mut fut),
            Poll::Ready(iface_manager_client) => iface_manager_client
        );

        // We are using a scan request issuance as a proxy to determine if the network selection
        // module took action.
        match test_type {
            NetworkSelectionMissingAttribute::AllAttributesPresent => {
                assert!(iface_manager_client.scan_proxy_requested);
            }
            NetworkSelectionMissingAttribute::IdleClient
            | NetworkSelectionMissingAttribute::SavedNetwork
            | NetworkSelectionMissingAttribute::NetworkSelectionInProgress => {
                assert!(!iface_manager_client.scan_proxy_requested);
            }
        }
    }

    #[fuchsia::test]
    fn test_scan_result_backoff() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create an IfaceManagerService
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _stream) = create_iface_manager_with_client(&test_values, true);

        // Create a timer to periodically check to ensure that all client interfaces are connected.
        let mut reconnect_monitor_interval: i64 = 1;
        let mut connectivity_monitor_timer =
            fasync::Interval::new(zx::Duration::from_seconds(reconnect_monitor_interval));

        // Simulate multiple failed scan attempts and ensure that the timer interval backs off as
        // expected.
        let expected_wait_times =
            vec![2, 4, 8, MAX_AUTO_CONNECT_RETRY_SECONDS, MAX_AUTO_CONNECT_RETRY_SECONDS];

        for i in 0..5 {
            {
                let fut = handle_network_selection_results(
                    None,
                    &mut iface_manager,
                    &mut reconnect_monitor_interval,
                    &mut connectivity_monitor_timer,
                );
                pin_mut!(fut);
                assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
            }
            assert_eq!(reconnect_monitor_interval, expected_wait_times[i]);
        }
    }

    #[fuchsia::test]
    fn test_reconnect_on_network_selection_results() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an interface manager with an unconfigured client interface.
        let (mut iface_manager, _sme_stream) =
            create_iface_manager_with_client(&test_values, false);
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        // Setup for a reconnection attempt.
        let mut reconnect_monitor_interval = 1;
        let mut connectivity_monitor_timer =
            fasync::Interval::new(zx::Duration::from_seconds(reconnect_monitor_interval));

        // Create a candidate network.
        let ssid = TEST_SSID.as_bytes().to_vec();
        let network_id = NetworkIdentifier::new(ssid.clone(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let network = Some(client_types::ConnectionCandidate {
            network: network_id.into(),
            credential: credential,
            bss: Some(fake_fidl_bss!(Open, bssid: [20, 30, 40, 50, 60, 70])),
            observed_in_passive_scan: Some(true),
            multiple_bss_candidates: Some(true),
        });

        {
            // Run reconnection attempt
            let fut = handle_network_selection_results(
                network,
                &mut iface_manager,
                &mut reconnect_monitor_interval,
                &mut connectivity_monitor_timer,
            );

            pin_mut!(fut);

            // Expect a client SME proxy request
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Pending);

            let mut device_service_fut = test_values.device_service_stream.into_future();
            assert_variant!(
                poll_device_service_req(&mut exec, &mut device_service_fut),
                Poll::Ready(fidl_fuchsia_wlan_device_service::DeviceServiceRequest::GetClientSme {
                    iface_id: TEST_CLIENT_IFACE_ID, sme, responder
                }) => {
                    // Send back a positive acknowledgement.
                    assert!(responder.send(fuchsia_zircon::sys::ZX_OK).is_ok());

                    sme
                }
            );

            // The future should then complete.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        // The reconnect attempt should have seen an idle client interface and created a new client
        // state machine future for it.
        assert!(!iface_manager.fsm_futures.is_empty());

        // There should not be any idle clients.
        assert!(iface_manager.idle_clients().is_empty());
    }

    #[fuchsia::test]
    fn test_idle_client_remains_after_failed_reconnection() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Create an interface manager with an unconfigured client interface.
        let (mut iface_manager, _sme_stream) =
            create_iface_manager_with_client(&test_values, false);
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        // Setup for a reconnection attempt.
        let mut reconnect_monitor_interval = 1;
        let mut connectivity_monitor_timer =
            fasync::Interval::new(zx::Duration::from_seconds(reconnect_monitor_interval));

        // Create a candidate network.
        let ssid = TEST_SSID.as_bytes().to_vec();
        let network_id = NetworkIdentifier::new(ssid.clone(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let network = Some(client_types::ConnectionCandidate {
            network: network_id.into(),
            credential: credential,
            bss: Some(fake_fidl_bss!(Open, bssid: [20, 30, 40, 50, 60, 70])),
            observed_in_passive_scan: Some(true),
            multiple_bss_candidates: Some(true),
        });

        {
            // Run reconnection attempt
            let fut = handle_network_selection_results(
                network,
                &mut iface_manager,
                &mut reconnect_monitor_interval,
                &mut connectivity_monitor_timer,
            );

            pin_mut!(fut);

            // Drop the device service stream so that the SME request fails.
            drop(test_values.device_service_stream);

            // The future should then complete.
            assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        // There should still be an idle client
        assert!(!iface_manager.idle_clients().is_empty());
    }

    #[fuchsia::test]
    fn test_terminated_client() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let mut test_values = test_setup(&mut exec);

        // Create a fake network entry so that a reconnect will be attempted.
        let network_id = NetworkIdentifier::new(TEST_SSID.as_bytes().to_vec(), SecurityType::Wpa);
        let credential = Credential::Password(TEST_PASSWORD.as_bytes().to_vec());
        let temp_dir = TempDir::new().expect("failed to create temporary directory");
        let path = temp_dir.path().join(rand_string());
        let tmp_path = temp_dir.path().join(rand_string());
        let (saved_networks, mut stash_server) =
            exec.run_singlethreaded(SavedNetworksManager::new_and_stash_server(path, tmp_path));
        test_values.saved_networks = Arc::new(saved_networks);

        // Update the saved networks with knowledge of the test SSID and credentials.
        {
            let save_network_fut =
                test_values.saved_networks.store(network_id.clone(), credential.clone());
            pin_mut!(save_network_fut);
            assert_variant!(exec.run_until_stalled(&mut save_network_fut), Poll::Pending);

            process_stash_write(&mut exec, &mut stash_server);
        }

        // Create a network selector.
        let selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks.clone(),
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create an interface manager with an unconfigured client interface.
        let (mut iface_manager, _sme_stream) =
            create_iface_manager_with_client(&test_values, false);
        iface_manager.clients[0].client_state_machine = Some(Box::new(FakeClient {
            disconnect_ok: true,
            is_alive: false,
            expected_connect_request: None,
        }));

        // Create remaining boilerplate to call handle_terminated_state_machine.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let mut network_selection_futures = FuturesUnordered::new();

        let metadata = StateMachineMetadata {
            role: fidl_fuchsia_wlan_device::MacRole::Client,
            iface_id: TEST_CLIENT_IFACE_ID,
        };

        {
            let fut = handle_terminated_state_machine(
                metadata,
                &mut iface_manager,
                iface_manager_client,
                selector,
                &mut network_selection_futures,
            );
            pin_mut!(fut);

            assert_eq!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        // Verify that there is a disconnected client.
        assert!(iface_manager.idle_clients().contains(&TEST_CLIENT_IFACE_ID));

        // Verify that a scan has been kicked off.
        assert!(!network_selection_futures.is_empty());
    }

    #[fuchsia::test]
    fn test_terminated_ap() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);
        let selector = Arc::new(NetworkSelector::new(
            test_values.saved_networks.clone(),
            create_mock_cobalt_sender(),
            inspect::Inspector::new().root().create_child("network_selector"),
        ));

        // Create an interface manager with an unconfigured client interface.
        let (mut iface_manager, _next_sme_req) =
            create_iface_manager_with_client(&test_values, true);

        // Create remaining boilerplate to call handle_terminated_state_machine.
        let iface_manager_client = Arc::new(Mutex::new(FakeIfaceManagerRequester::new()));
        let mut network_selection_futures = FuturesUnordered::new();

        let metadata = StateMachineMetadata {
            role: fidl_fuchsia_wlan_device::MacRole::Ap,
            iface_id: TEST_AP_IFACE_ID,
        };

        {
            let fut = handle_terminated_state_machine(
                metadata,
                &mut iface_manager,
                iface_manager_client,
                selector,
                &mut network_selection_futures,
            );
            pin_mut!(fut);

            assert_eq!(exec.run_until_stalled(&mut fut), Poll::Ready(()));
        }

        // Verify that the IfaceManagerService does not have an AP interface.
        assert!(iface_manager.aps.is_empty());
    }

    /// Test that if PhyManager knows of a client iface that supports WPA3, has_wpa3_capable_client
    /// will return true.
    #[fuchsia::test]
    fn test_has_wpa3_capable_client() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);
        iface_manager.phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: Some(0),
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        }));
        let fut = iface_manager.has_wpa3_capable_client();
        pin_mut!(fut);
        assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(true));
    }

    /// Test that if PhyManager does not have a WPA3 client iface, has_wpa3_capable_client will
    /// return false.
    #[fuchsia::test]
    fn test_has_no_wpa3_capable_iface() {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");

        // Create a configured ClientIfaceContainer.
        let test_values = test_setup(&mut exec);
        let (mut iface_manager, _) = create_iface_manager_with_client(&test_values, true);

        iface_manager.phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok: true,
            destroy_iface_ok: true,
            wpa3_iface: None,
            set_country_ok: true,
            country_code: None,
            client_connections_enabled: true,
        }));
        let fut = iface_manager.has_wpa3_capable_client();
        pin_mut!(fut);
        assert_variant!(exec.run_until_stalled(&mut fut), Poll::Ready(false));
    }

    /// Tests the operation of setting the country code.  The test cases of interest are:
    /// 1. Client connections and APs are initially enabled and all operations succeed.
    /// 2. Client connections are initially enabled and all operations succeed except restarting
    ///    client connections.
    ///    * In this scenario, the country code has been properly applied and the device should be
    ///      allowed to continue running.  Higher layers can optionally re-enable client
    ///      connections to recover.
    /// 3. APs are initially enabled and all operations succeed except restarting the AP.
    ///    * As in the above scenario, the device can be allowed to continue running and the API
    ///      client can attempt to restart the AP manually.
    /// 4. Stop client connections fails.
    /// 5. Stop all APs fails.
    /// 6. Set country fails.
    #[test_case(
        true, true, true, true, true, TestType::Pass;
        "client and AP enabled and all operations succeed"
    )]
    #[test_case(
        true, false, true, true, false, TestType::Pass;
        "client enabled and restarting client fails"
    )]
    #[test_case(
        false, true, true, true, false, TestType::Pass;
        "AP enabled and start AP fails after setting country"
    )]
    #[test_case(
        true, false, false, true, true, TestType::Fail;
        "stop client connections fails"
    )]
    #[test_case(
        false, true, false, true, true, TestType::Fail;
        "stop APs fails"
    )]
    #[test_case(
        false, true, true, false, true, TestType::Fail;
        "set country fails"
    )]
    #[fuchsia::test(add_test_attr = false)]
    fn set_country_service_test(
        client_connections_enabled: bool,
        ap_enabled: bool,
        destroy_iface_ok: bool,
        set_country_ok: bool,
        create_iface_ok: bool,
        test_type: TestType,
    ) {
        let mut exec = fuchsia_async::TestExecutor::new().expect("failed to create an executor");
        let test_values = test_setup(&mut exec);

        // Seed a FakePhyManager with the test configuration information and provide the PhyManager
        // to a new IfaceManagerService to test the behavior given the configuration.
        let phy_manager = Arc::new(Mutex::new(FakePhyManager {
            create_iface_ok,
            destroy_iface_ok,
            set_country_ok,
            wpa3_iface: None,
            country_code: None,
            client_connections_enabled,
        }));

        let mut iface_manager = IfaceManagerService::new(
            phy_manager.clone(),
            test_values.client_update_sender.clone(),
            test_values.ap_update_sender.clone(),
            test_values.device_service_proxy.clone(),
            test_values.saved_networks.clone(),
            test_values.network_selector.clone(),
            test_values.cobalt_api.clone(),
        );

        // If the test calls for it, create an AP interface to test that the IfaceManager preserves
        // the configuration and restores it after setting the country code.
        if ap_enabled {
            let fake_ap = FakeAp { start_succeeds: true, stop_succeeds: true, exit_succeeds: true };
            let ap_container = ApIfaceContainer {
                iface_id: TEST_AP_IFACE_ID,
                config: Some(create_ap_config(TEST_SSID, TEST_PASSWORD)),
                ap_state_machine: Box::new(fake_ap),
                enabled_time: None,
            };
            iface_manager.aps.push(ap_container);
        }

        // Call set_country and drive the operation to completion.
        let (set_country_sender, set_country_receiver) = oneshot::channel();
        let req = SetCountryRequest { country_code: Some([0, 0]), responder: set_country_sender };
        let req = IfaceManagerRequest::SetCountry(req);

        run_service_test(
            &mut exec,
            test_values.network_selector,
            iface_manager,
            req,
            set_country_receiver,
            test_values.device_service_stream,
            test_type,
        );

        if destroy_iface_ok && set_country_ok {
            let phy_manager_fut = phy_manager.lock();
            pin_mut!(phy_manager_fut);
            assert_variant!(
                exec.run_until_stalled(&mut phy_manager_fut),
                Poll::Ready(phy_manager) => {
                    assert_eq!(phy_manager.country_code, Some([0, 0]))
                }
            );
        }
    }
}
