// Copyright 2019 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 std::collections::{HashMap, HashSet};
use std::convert::TryFrom as _;
use std::num::NonZeroU16;
use std::ops::{Deref as _, DerefMut as _};
use std::sync::{Arc, Once};

use anyhow::{format_err, Context as _, Error};
use assert_matches::assert_matches;
use fidl_fuchsia_net as fidl_net;
use fidl_fuchsia_net_stack as fidl_net_stack;
use fidl_fuchsia_net_stack_ext::FidlReturn as _;
use fidl_fuchsia_netemul_network as net;
use fuchsia_async as fasync;
use futures::lock::Mutex;
use net_types::{
    ip::{AddrSubnetEither, IpAddr, Ipv4Addr, Ipv6Addr, SubnetEither},
    SpecifiedAddr,
};
use netstack3_core::{
    context::{CounterContext, EventContext, InstantContext, RngContext, TimerContext},
    get_all_ip_addr_subnets, get_ipv4_configuration, get_ipv6_configuration,
    icmp::{BufferIcmpContext, IcmpConnId, IcmpContext, IcmpIpExt},
    update_ipv4_configuration, update_ipv6_configuration, AddableEntryEither, BufferUdpContext,
    Ctx, DeviceId, DeviceLayerEventDispatcher, IpExt, NonSyncContext, TimerId, UdpBoundId,
    UdpContext,
};
use packet::{Buf, BufferMut, Serializer};
use packet_formats::icmp::{IcmpEchoReply, IcmpMessage, IcmpUnusedCode};
use rand::rngs::OsRng;

use crate::bindings::{
    context::Lockable,
    devices::{
        CommonInfo, DeviceInfo, DeviceSpecificInfo, Devices, EthernetInfo, LoopbackInfo,
        NetdeviceInfo,
    },
    socket::datagram::{IcmpEcho, SocketCollectionIpExt, Udp},
    util::{ConversionContext as _, IntoFidl as _, TryFromFidlWithContext as _, TryIntoFidl as _},
    BindingsNonSyncCtxImpl, DeviceStatusNotifier, LockableContext, RequestStreamExt as _,
    StackTime, DEFAULT_LOOPBACK_MTU,
};

/// log::Log implementation that uses stdout.
///
/// Useful when debugging tests.
struct Logger;

impl log::Log for Logger {
    fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
        true
    }

    fn log(&self, record: &log::Record<'_>) {
        println!("[{}] ({}) {}", record.level(), record.module_path().unwrap_or(""), record.args())
    }

    fn flush(&self) {}
}

static LOGGER: Logger = Logger;

static LOGGER_ONCE: Once = Once::new();

/// Install a logger for tests.
pub(crate) fn set_logger_for_test() {
    // log::set_logger will panic if called multiple times; using a Once makes
    // set_logger_for_test idempotent
    LOGGER_ONCE.call_once(|| {
        log::set_logger(&LOGGER).unwrap();
        log::set_max_level(log::LevelFilter::Trace);
    })
}

/// A dispatcher that can be used for tests with the ability to optionally
/// intercept events to use as signals during testing.
///
/// `TestDispatcher` implements [`StackDispatcher`] and keeps an internal
/// [`BindingsDispatcherState`]. All the traits that are needed to have a
/// correct [`EventDispatcher`] are re-implemented by it so any events can be
/// short circuited into internal event watchers as opposed to routing into the
/// internal [`BindingsDispatcherState]`.
pub(crate) struct TestNonSyncCtx {
    ctx: BindingsNonSyncCtxImpl,
    /// A oneshot signal that is hit whenever changes to interface status occur
    /// and it is set.
    status_changed_signal: Option<futures::channel::oneshot::Sender<()>>,
}

impl Default for TestNonSyncCtx {
    fn default() -> TestNonSyncCtx {
        TestNonSyncCtx { ctx: Default::default(), status_changed_signal: None }
    }
}

impl TestNonSyncCtx {
    /// Shorthand method to get a [`DeviceInfo`] from the device's bindings
    /// identifier.
    fn get_device_info(&self, id: u64) -> Option<&DeviceInfo> {
        AsRef::<Devices>::as_ref(self).get_device(id)
    }
}

impl DeviceStatusNotifier for TestNonSyncCtx {
    fn device_status_changed(&mut self, id: u64) {
        if let Some(s) = self.status_changed_signal.take() {
            s.send(()).unwrap();
        }
        // we can always send that forward to the real dispatcher, no need to
        // short-circuit it.
        self.ctx.device_status_changed(id);
    }
}

impl<T> AsRef<T> for TestNonSyncCtx
where
    BindingsNonSyncCtxImpl: AsRef<T>,
{
    fn as_ref(&self) -> &T {
        self.ctx.as_ref()
    }
}

impl<T> AsMut<T> for TestNonSyncCtx
where
    BindingsNonSyncCtxImpl: AsMut<T>,
{
    fn as_mut(&mut self) -> &mut T {
        self.ctx.as_mut()
    }
}

impl CounterContext for TestNonSyncCtx {
    fn increment_counter(&mut self, key: &'static str) {
        self.ctx.increment_counter(key)
    }
}

impl RngContext for TestNonSyncCtx {
    type Rng = OsRng;

    fn rng(&self) -> &OsRng {
        &self.ctx.rng
    }

    fn rng_mut(&mut self) -> &mut OsRng {
        &mut self.ctx.rng
    }
}

impl InstantContext for TestNonSyncCtx {
    type Instant = StackTime;

    fn now(&self) -> StackTime {
        self.ctx.now()
    }
}

impl TimerContext<TimerId> for TestNonSyncCtx {
    fn schedule_timer_instant(&mut self, time: StackTime, id: TimerId) -> Option<StackTime> {
        self.ctx.schedule_timer_instant(time, id)
    }

    fn cancel_timer(&mut self, id: TimerId) -> Option<StackTime> {
        self.ctx.cancel_timer(id)
    }

    fn cancel_timers_with<F: FnMut(&TimerId) -> bool>(&mut self, f: F) {
        self.ctx.cancel_timers_with(f);
    }

    fn scheduled_instant(&self, id: TimerId) -> Option<StackTime> {
        self.ctx.scheduled_instant(id)
    }
}

impl<B: BufferMut> DeviceLayerEventDispatcher<B> for TestNonSyncCtx {
    fn send_frame<S: Serializer<Buffer = B>>(
        &mut self,
        device: DeviceId,
        frame: S,
    ) -> Result<(), S> {
        self.ctx.send_frame(device, frame)
    }
}

impl<T: 'static + Send> EventContext<T> for TestNonSyncCtx {
    fn on_event(&mut self, _event: T) {}
}

impl<I: SocketCollectionIpExt<Udp> + IcmpIpExt> UdpContext<I> for TestNonSyncCtx {
    fn receive_icmp_error(&mut self, id: UdpBoundId<I>, err: I::ErrorCode) {
        UdpContext::receive_icmp_error(&mut self.ctx, id, err)
    }
}

impl<I: SocketCollectionIpExt<Udp> + IpExt, B: BufferMut> BufferUdpContext<I, B>
    for TestNonSyncCtx
{
    fn receive_udp_from_conn(
        &mut self,
        conn: netstack3_core::UdpConnId<I>,
        src_ip: I::Addr,
        src_port: NonZeroU16,
        body: &B,
    ) {
        self.ctx.receive_udp_from_conn(conn, src_ip, src_port, body)
    }

    /// Receive a UDP packet for a listener.
    fn receive_udp_from_listen(
        &mut self,
        listener: netstack3_core::UdpListenerId<I>,
        src_ip: I::Addr,
        dst_ip: I::Addr,
        src_port: Option<NonZeroU16>,
        body: &B,
    ) {
        self.ctx.receive_udp_from_listen(listener, src_ip, dst_ip, src_port, body)
    }
}

impl<I: SocketCollectionIpExt<IcmpEcho> + IcmpIpExt> IcmpContext<I> for TestNonSyncCtx {
    fn receive_icmp_error(&mut self, conn: IcmpConnId<I>, seq_num: u16, err: I::ErrorCode) {
        IcmpContext::<I>::receive_icmp_error(&mut self.ctx, conn, seq_num, err)
    }
}

impl<I, B> BufferIcmpContext<I, B> for TestNonSyncCtx
where
    I: SocketCollectionIpExt<IcmpEcho> + IcmpIpExt,
    B: BufferMut,
    IcmpEchoReply: for<'a> IcmpMessage<I, &'a [u8], Code = IcmpUnusedCode>,
{
    fn receive_icmp_echo_reply(
        &mut self,
        conn: IcmpConnId<I>,
        src_ip: I::Addr,
        dst_ip: I::Addr,
        id: u16,
        seq_num: u16,
        data: B,
    ) {
        self.ctx.receive_icmp_echo_reply(conn, src_ip, dst_ip, id, seq_num, data)
    }
}

#[derive(Clone)]
/// A netstack context for testing.
pub(crate) struct TestContext {
    ctx: Arc<Mutex<Ctx<TestNonSyncCtx>>>,
    _interfaces_worker: Arc<super::interfaces_watcher::Worker>,
    interfaces_sink: super::interfaces_watcher::WorkerInterfaceSink,
}

impl TestContext {
    fn new() -> Self {
        let (worker, _, interfaces_sink) = super::interfaces_watcher::Worker::new();
        Self {
            ctx: Arc::new(Mutex::new(Ctx::default())),
            _interfaces_worker: Arc::new(worker),
            interfaces_sink,
        }
    }
}

impl super::InterfaceEventProducerFactory for TestContext {
    fn create_interface_event_producer(
        &self,
        id: super::devices::BindingId,
        properties: super::interfaces_watcher::InterfaceProperties,
    ) -> super::interfaces_watcher::InterfaceEventProducer {
        self.interfaces_sink.add_interface(id, properties).expect("interfaces worker not running")
    }
}

impl<'a> Lockable<'a, Ctx<TestNonSyncCtx>> for TestContext {
    type Guard = futures::lock::MutexGuard<'a, Ctx<TestNonSyncCtx>>;
    type Fut = futures::lock::MutexLockFuture<'a, Ctx<TestNonSyncCtx>>;
    fn lock(&'a self) -> Self::Fut {
        self.ctx.lock()
    }
}

impl LockableContext for TestContext {
    type NonSyncCtx = TestNonSyncCtx;
}

/// A holder for a [`TestContext`].
/// `TestStack` is obtained from [`TestSetupBuilder`] and offers utility methods
/// to connect to the FIDL APIs served by [`TestContext`], as well as keeps
/// track of configured interfaces during the setup procedure.
pub(crate) struct TestStack {
    ctx: TestContext,
    endpoint_ids: HashMap<String, u64>,
}

struct InterfaceInfo {
    admin_enabled: bool,
    phy_up: bool,
    addresses: Vec<fidl_net::Subnet>,
}

impl TestStack {
    /// Connects to the `fuchsia.net.stack.Stack` service.
    pub(crate) fn connect_stack(&self) -> Result<fidl_fuchsia_net_stack::StackProxy, Error> {
        let (stack, rs) =
            fidl::endpoints::create_proxy_and_stream::<fidl_fuchsia_net_stack::StackMarker>()?;
        fasync::Task::spawn(rs.serve_with(|rs| {
            crate::bindings::stack_fidl_worker::StackFidlWorker::serve(self.ctx.clone(), rs)
        }))
        .detach();
        Ok(stack)
    }

    /// Connects to the `fuchsia.posix.socket.Provider` service.
    pub(crate) fn connect_socket_provider(
        &self,
    ) -> Result<fidl_fuchsia_posix_socket::ProviderProxy, Error> {
        let (stack, rs) = fidl::endpoints::create_proxy_and_stream::<
            fidl_fuchsia_posix_socket::ProviderMarker,
        >()?;
        fasync::Task::spawn(
            rs.serve_with(|rs| crate::bindings::socket::serve(self.ctx.clone(), rs)),
        )
        .detach();
        Ok(stack)
    }

    fn is_interface_link_up(info: &DeviceInfo) -> bool {
        match info.info() {
            DeviceSpecificInfo::Ethernet(EthernetInfo {
                common_info: CommonInfo { admin_enabled: _, mtu: _, events: _, name: _ },
                client: _,
                mac: _,
                features: _,
                phy_up,
            })
            | DeviceSpecificInfo::Netdevice(NetdeviceInfo {
                common_info: CommonInfo { admin_enabled: _, mtu: _, events: _, name: _ },
                handler: _,
                mac: _,
                phy_up,
            }) => *phy_up,
            DeviceSpecificInfo::Loopback(LoopbackInfo {
                common_info: CommonInfo { admin_enabled: _, mtu: _, events: _, name: _ },
            }) => true,
        }
    }

    /// Waits for interface with given `if_id` to come online.
    pub(crate) async fn wait_for_interface_online(&mut self, if_id: u64) {
        self.wait_for_interface_status(if_id, Self::is_interface_link_up).await;
    }

    /// Waits for interface with given `if_id` to go offline.
    pub(crate) async fn wait_for_interface_offline(&mut self, if_id: u64) {
        self.wait_for_interface_status(if_id, |info| !Self::is_interface_link_up(info)).await;
    }

    async fn wait_for_interface_status<F: Fn(&DeviceInfo) -> bool>(
        &mut self,
        if_id: u64,
        check_status: F,
    ) {
        loop {
            let signal = {
                let mut ctx = self.ctx.lock().await;
                if check_status(
                    ctx.non_sync_ctx
                        .get_device_info(if_id)
                        .expect("Wait for interface status on unknown device"),
                ) {
                    return;
                }
                let (sender, receiver) = futures::channel::oneshot::channel();
                ctx.non_sync_ctx.status_changed_signal = Some(sender);
                receiver
            };
            let () = signal.await.expect("Stream ended before it was signalled");
        }
    }

    /// Gets an installed interface identifier from the configuration endpoint
    /// `index`.
    pub(crate) fn get_endpoint_id(&self, index: usize) -> u64 {
        self.get_named_endpoint_id(test_ep_name(index))
    }

    /// Gets an installed interface identifier from the configuration endpoint
    /// `name`.
    pub(crate) fn get_named_endpoint_id(&self, name: impl Into<String>) -> u64 {
        *self.endpoint_ids.get(&name.into()).unwrap()
    }

    /// Creates a new `TestStack`.
    pub(crate) fn new() -> Self {
        let ctx = TestContext::new();
        TestStack { ctx, endpoint_ids: HashMap::new() }
    }

    /// Helper function to invoke a closure that provides a locked
    /// [`Ctx< BindingsContext>`] provided by this `TestStack`.
    pub(crate) async fn with_ctx<R, F: FnOnce(&mut Ctx<TestNonSyncCtx>) -> R>(
        &mut self,
        f: F,
    ) -> R {
        let mut ctx = self.ctx.lock().await;
        f(ctx.deref_mut())
    }

    /// Acquire a lock on this `TestStack`'s context.
    pub(crate) async fn ctx(&self) -> <TestContext as Lockable<'_, Ctx<TestNonSyncCtx>>>::Guard {
        self.ctx.lock().await
    }

    async fn get_interface_info(&self, id: u64) -> InterfaceInfo {
        let ctx = self.ctx().await;
        let Ctx { sync_ctx, non_sync_ctx } = ctx.deref();
        let device = non_sync_ctx.get_device_info(id).expect("device");
        let addresses = get_all_ip_addr_subnets(sync_ctx, device.core_id())
            .map(|addr| addr.try_into_fidl().expect("convert to FIDL"))
            .collect();

        let (admin_enabled, phy_up) = assert_matches::assert_matches!(
            device.info(),
            DeviceSpecificInfo::Ethernet(EthernetInfo {
                common_info: CommonInfo {
                    admin_enabled,
                    mtu: _,
                    events: _,
                    name: _,
                },
                client: _,
                mac: _,
                features: _,
                phy_up
            }) => (*admin_enabled, *phy_up));
        InterfaceInfo { admin_enabled, phy_up, addresses }
    }
}

/// A test setup that than contain multiple stack instances networked together.
pub(crate) struct TestSetup {
    // Let connection to sandbox be made lazily, so a netemul sandbox is not
    // created for tests that don't need it.
    sandbox: Option<netemul::TestSandbox>,
    // Keep around the handle to the virtual networks and endpoints we create to
    // ensure they're not cleaned up before test execution is complete.
    _network: Option<net::SetupHandleProxy>,
    stacks: Vec<TestStack>,
}

impl TestSetup {
    /// Gets the [`TestStack`] at index `i`.
    pub(crate) fn get(&mut self, i: usize) -> &mut TestStack {
        &mut self.stacks[i]
    }

    /// Acquires a lock on the [`TestContext`] at index `i`.
    pub(crate) async fn ctx(
        &mut self,
        i: usize,
    ) -> <TestContext as Lockable<'_, Ctx<TestNonSyncCtx>>>::Guard {
        self.get(i).ctx.lock().await
    }

    async fn get_endpoint(
        &mut self,
        ep_name: &str,
    ) -> Result<fidl::endpoints::ClientEnd<fidl_fuchsia_hardware_ethernet::DeviceMarker>, Error>
    {
        let epm = self.sandbox().get_endpoint_manager()?;
        let ep = match epm.get_endpoint(ep_name).await? {
            Some(ep) => ep.into_proxy()?,
            None => {
                return Err(format_err!("Failed to retrieve endpoint {}", ep_name));
            }
        };

        match ep.get_device().await? {
            fidl_fuchsia_netemul_network::DeviceConnection::Ethernet(e) => Ok(e),
            fidl_fuchsia_netemul_network::DeviceConnection::NetworkDevice(n) => {
                todo!("(48853) Support NetworkDevice for integration tests.  Got unexpected network device {:?}.", n)
            }
        }
    }

    /// Changes a named endpoint `ep_name` link status to `up`.
    pub(crate) async fn set_endpoint_link_up(
        &mut self,
        ep_name: &str,
        up: bool,
    ) -> Result<(), Error> {
        let epm = self.sandbox().get_endpoint_manager()?;
        if let Some(ep) = epm.get_endpoint(ep_name).await? {
            ep.into_proxy()?.set_link_up(up).await?;
            Ok(())
        } else {
            Err(format_err!("Failed to retrieve endpoint {}", ep_name))
        }
    }

    /// Creates a new empty `TestSetup`.
    fn new() -> Result<Self, Error> {
        set_logger_for_test();
        Ok(Self { sandbox: None, _network: None, stacks: Vec::new() })
    }

    fn sandbox(&mut self) -> &netemul::TestSandbox {
        self.sandbox
            .get_or_insert_with(|| netemul::TestSandbox::new().expect("create netemul sandbox"))
    }

    async fn configure_network(
        &mut self,
        ep_names: impl Iterator<Item = String>,
    ) -> Result<(), Error> {
        let handle = self
            .sandbox()
            .setup_networks(vec![net::NetworkSetup {
                name: "test_net".to_owned(),
                config: net::NetworkConfig::EMPTY,
                endpoints: ep_names.map(|name| new_endpoint_setup(name)).collect(),
            }])
            .await
            .context("create network")?
            .into_proxy();

        self._network = Some(handle);
        Ok(())
    }

    fn add_stack(&mut self, stack: TestStack) {
        self.stacks.push(stack)
    }
}

/// Helper function to retrieve the internal name of an endpoint specified only
/// by an index `i`.
pub(crate) fn test_ep_name(i: usize) -> String {
    format!("test-ep{}", i)
}

fn new_endpoint_setup(name: String) -> net::EndpointSetup {
    net::EndpointSetup { config: None, link_up: true, name }
}

/// A builder structure for [`TestSetup`].
pub(crate) struct TestSetupBuilder {
    endpoints: Vec<String>,
    stacks: Vec<StackSetupBuilder>,
}

impl TestSetupBuilder {
    /// Creates an empty `SetupBuilder`.
    pub(crate) fn new() -> Self {
        Self { endpoints: Vec::new(), stacks: Vec::new() }
    }

    /// Adds an automatically-named endpoint to the setup builder. The automatic
    /// names are taken using [`test_ep_name`] with index starting at 1.
    ///
    /// Multiple calls to `add_endpoint` will result in the creation of multiple
    /// endpoints with sequential indices.
    pub(crate) fn add_endpoint(self) -> Self {
        let id = self.endpoints.len() + 1;
        self.add_named_endpoint(test_ep_name(id))
    }

    /// Ads an endpoint with a given `name`.
    pub(crate) fn add_named_endpoint(mut self, name: impl Into<String>) -> Self {
        self.endpoints.push(name.into());
        self
    }

    /// Adds a stack to create upon building. Stack configuration is provided
    /// by [`StackSetupBuilder`].
    pub(crate) fn add_stack(mut self, stack: StackSetupBuilder) -> Self {
        self.stacks.push(stack);
        self
    }

    /// Adds an empty stack to create upon building. An empty stack contains
    /// no endpoints.
    pub(crate) fn add_empty_stack(mut self) -> Self {
        self.stacks.push(StackSetupBuilder::new());
        self
    }

    /// Attempts to build a [`TestSetup`] with the provided configuration.
    pub(crate) async fn build(self) -> Result<TestSetup, Error> {
        let mut setup = TestSetup::new()?;
        if !self.endpoints.is_empty() {
            let () = setup.configure_network(self.endpoints.into_iter()).await?;
        }

        // configure all the stacks:
        for stack_cfg in self.stacks.into_iter() {
            println!("Adding stack: {:?}", stack_cfg);
            let mut stack = TestStack::new();
            stack
                .with_ctx(|Ctx { sync_ctx, non_sync_ctx }| {
                    let loopback =
                        netstack3_core::add_loopback_device(sync_ctx, DEFAULT_LOOPBACK_MTU)
                            .expect("add loopback device");
                    update_ipv4_configuration(sync_ctx, non_sync_ctx, loopback, |config| {
                        config.ip_config.ip_enabled = true;
                    });
                    update_ipv6_configuration(sync_ctx, non_sync_ctx, loopback, |config| {
                        config.ip_config.ip_enabled = true;
                    });
                })
                .await;

            for (ep_name, addr) in stack_cfg.endpoints.into_iter() {
                // get the endpoint from the sandbox config:
                let endpoint = setup.get_endpoint(&ep_name).await?;
                let cli = stack.connect_stack()?;
                let if_id = add_stack_endpoint(&cli, endpoint).await?;
                // We'll ALWAYS await for the newly created interface to come up
                // online before returning, so users of `TestSetupBuilder` can
                // be 100% sure of the state once the setup is done.
                stack.wait_for_interface_online(if_id).await;
                if let Some(addr) = addr {
                    configure_endpoint_address(&cli, if_id, addr).await?;
                }

                assert_eq!(stack.endpoint_ids.insert(ep_name, if_id), None);
            }

            setup.add_stack(stack)
        }

        Ok(setup)
    }
}

/// Shorthand function to create an IPv4 [`AddrSubnetEither`].
///
/// # Panics
///
/// May panic if `prefix` is longer than the number of bits in this type of IP
/// address (32 for IPv4), or if `ip` is not a unicast address in the resulting
/// subnet (see [`net_types::ip::IpAddress::is_unicast_in_subnet`]).
pub fn new_ipv4_addr_subnet(ip: [u8; 4], prefix: u8) -> AddrSubnetEither {
    AddrSubnetEither::new(IpAddr::V4(Ipv4Addr::from(ip)), prefix).unwrap()
}

/// Shorthand function to create an IPv6 [`AddrSubnetEither`].
///
/// # Panics
///
/// May panic if `prefix` is longer than the number of bits in this type of IP
/// address (128 for IPv6), or if `ip` is not a unicast address in the resulting
/// subnet (see [`net_types::ip::IpAddress::is_unicast_in_subnet`]).
pub fn new_ipv6_addr_subnet(ip: [u8; 16], prefix: u8) -> AddrSubnetEither {
    AddrSubnetEither::new(IpAddr::V6(Ipv6Addr::from(ip)), prefix).unwrap()
}

/// Helper struct to create stack configuration for [`TestSetupBuilder`].
#[derive(Debug)]
pub struct StackSetupBuilder {
    endpoints: Vec<(String, Option<AddrSubnetEither>)>,
}

impl StackSetupBuilder {
    /// Creates a new empty stack (no endpoints) configuration.
    pub(crate) fn new() -> Self {
        Self { endpoints: Vec::new() }
    }

    /// Adds endpoint number  `index` with optional address configuration
    /// `address` to the builder.
    fn add_endpoint(self, index: usize, address: Option<AddrSubnetEither>) -> Self {
        self.add_named_endpoint(test_ep_name(index), address)
    }

    /// Adds named endpoint `name` with optional address configuration `address`
    /// to the builder.
    pub(crate) fn add_named_endpoint(
        mut self,
        name: impl Into<String>,
        address: Option<AddrSubnetEither>,
    ) -> Self {
        self.endpoints.push((name.into(), address));
        self
    }
}

async fn add_stack_endpoint(
    cli: &fidl_fuchsia_net_stack::StackProxy,
    endpoint: fidl::endpoints::ClientEnd<fidl_fuchsia_hardware_ethernet::DeviceMarker>,
) -> Result<u64, Error> {
    // add interface:
    let if_id = cli
        .add_ethernet_interface("fake_topo_path", endpoint)
        .await
        .squash_result()
        .context("Add ethernet interface")?;
    Ok(if_id)
}

async fn configure_endpoint_address(
    cli: &fidl_fuchsia_net_stack::StackProxy,
    if_id: u64,
    addr: AddrSubnetEither,
) -> Result<(), Error> {
    // add address:
    let () = cli
        .add_interface_address_deprecated(if_id, &mut addr.into_fidl())
        .await
        .squash_result()
        .context("Add interface address")?;

    // add route to ensure `addr` is valid, the result can be safely discarded
    let _ =
        AddrSubnetEither::try_from(addr).expect("Invalid test subnet configuration").addr_subnet();

    let () = cli
        .add_forwarding_entry(&mut fidl_fuchsia_net_stack::ForwardingEntry {
            subnet: addr.addr_subnet().1.into_fidl(),
            device_id: if_id,
            next_hop: None,
            metric: 0,
        })
        .await
        .squash_result()
        .context("Add forwarding entry")?;

    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn test_add_remove_interface() {
    let mut t = TestSetupBuilder::new().add_endpoint().add_empty_stack().build().await.unwrap();
    let ep = t.get_endpoint("test-ep1").await.unwrap();
    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = stack
        .add_ethernet_interface("fake_topo_path", ep)
        .await
        .squash_result()
        .expect("Add interface succeeds");

    // remove the interface:
    let () = stack.del_ethernet_interface(if_id).await.squash_result().expect("Remove interface");
    // ensure the interface disappeared from records:
    assert_matches!(test_stack.ctx.lock().await.non_sync_ctx.get_device_info(if_id), None);

    // if we try to remove it again, NotFound should be returned:
    let res =
        stack.del_ethernet_interface(if_id).await.unwrap().expect_err("Failed to remove twice");
    assert_eq!(res, fidl_net_stack::Error::NotFound);
}

#[fasync::run_singlethreaded(test)]
async fn test_ethernet_link_up_down() {
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();
    let ep_name = test_ep_name(1);
    let test_stack = t.get(0);
    let if_id = test_stack.get_endpoint_id(1);

    let () = test_stack.wait_for_interface_online(if_id).await;

    // Get the interface info to confirm status indicators are correct.
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been enabled in the core.
    let core_id = {
        let mut ctx = test_stack.ctx().await;
        let core_id = ctx.non_sync_ctx.get_device_info(if_id).unwrap().core_id();
        check_ip_enabled(ctx.deref_mut(), core_id, true);
        core_id
    };

    // Setting the link down should disable the interface and disable it from
    // the core. The AdministrativeStatus should remain unchanged.
    assert!(t.set_endpoint_link_up(&ep_name, false).await.is_ok());
    let test_stack = t.get(0);
    test_stack.wait_for_interface_offline(if_id).await;

    // Get the interface info to confirm that it is disabled.
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Setting the link down again should cause no effect on the device state,
    // and should be handled gracefully.
    assert!(t.set_endpoint_link_up(&ep_name, false).await.is_ok());

    // Get the interface info to confirm that it is disabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Setting the link up should reenable the interface and enable it in
    // the core.
    assert!(t.set_endpoint_link_up(&ep_name, true).await.is_ok());
    t.get(0).wait_for_interface_online(if_id).await;

    // Get the interface info to confirm that it is reenabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been enabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, true);

    // Setting the link up again should cause no effect on the device state,
    // and should be handled gracefully.
    assert!(t.set_endpoint_link_up(&ep_name, true).await.is_ok());

    // Get the interface info to confirm that there have been no changes.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been enabled in the core.
    let core_id = t
        .get(0)
        .with_ctx(|ctx| {
            let core_id = ctx.non_sync_ctx.get_device_info(if_id).unwrap().core_id();
            check_ip_enabled(ctx, core_id, true);
            core_id
        })
        .await;

    // call directly into core to prove that the device was correctly
    // initialized (core will panic if we try to use the device and initialize
    // hasn't been called)
    let mut ctx = t.ctx(0).await;
    let Ctx { sync_ctx, non_sync_ctx } = ctx.deref_mut();
    netstack3_core::receive_frame(sync_ctx, non_sync_ctx, core_id, Buf::new(&mut [], ..))
        .expect("error receiving frame");
}

fn check_ip_enabled<NonSyncCtx: NonSyncContext>(
    Ctx { sync_ctx, non_sync_ctx: _ }: &mut Ctx<NonSyncCtx>,
    core_id: DeviceId,
    expected: bool,
) {
    let ipv4_enabled = get_ipv4_configuration(sync_ctx, core_id).ip_config.ip_enabled;
    let ipv6_enabled = get_ipv6_configuration(sync_ctx, core_id).ip_config.ip_enabled;

    assert_eq!((ipv4_enabled, ipv6_enabled), (expected, expected));
}

#[fasync::run_singlethreaded(test)]
async fn test_disable_enable_interface() {
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();
    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = test_stack.get_endpoint_id(1);

    // Get the interface info to confirm that it is enabled.
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Disable the interface and test again, physical_status should be
    // unchanged.
    let () = stack
        .disable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Disable interface succeeds");

    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Ensure that the device has been disabled in the core.
    let core_id = {
        let mut ctx = test_stack.ctx().await;
        let core_id = ctx.non_sync_ctx.get_device_info(if_id).unwrap().core_id();
        check_ip_enabled(ctx.deref_mut(), core_id, false);
        core_id
    };

    // Enable the interface and test again.
    let () = stack
        .enable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Enable interface succeeds");

    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Ensure that the device has been enabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, true);

    // Check that we get the correct error for a non-existing interface id.
    assert_eq!(
        stack.enable_interface_deprecated(12345).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::NotFound
    );

    // Check that we get the correct error for a non-existing interface id.
    assert_eq!(
        stack.disable_interface_deprecated(12345).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::NotFound
    );
}

#[fasync::run_singlethreaded(test)]
async fn test_phy_admin_interface_state_interaction() {
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();
    let ep_name = test_ep_name(1);
    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = test_stack.get_endpoint_id(1);

    t.get(0).wait_for_interface_online(if_id).await;

    // Get the interface info to confirm that it is enabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Disable the interface and test again, physical_status should be
    // unchanged.
    let () = stack
        .disable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Disable interface succeeds");

    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Ensure that the device has been disabled in the core.
    let core_id = {
        let mut ctx = test_stack.ctx().await;
        let core_id = ctx.non_sync_ctx.get_device_info(if_id).unwrap().core_id();
        check_ip_enabled(ctx.deref_mut(), core_id, false);
        core_id
    };

    // Setting the link down now that the interface is already down should only
    // change the cached state. Both phy and admin should be down now.
    assert!(t.set_endpoint_link_up(&ep_name, false).await.is_ok());
    t.get(0).wait_for_interface_offline(if_id).await;

    // Get the interface info to confirm that it is disabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.phy_up);
    assert!(!if_info.admin_enabled);

    // Ensure that the device is still disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Enable the interface and test again, only cached status should be changed
    // and core state should still be disabled.
    let () = stack
        .enable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Enable interface succeeds");

    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.admin_enabled);
    assert!(!if_info.phy_up);

    // Ensure that the device is still disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Disable the interface and test again, both should be down now.
    let () = stack
        .disable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Disable interface succeeds");

    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.admin_enabled);
    assert!(!if_info.phy_up);

    // Ensure that the device is still disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Setting the link up should only affect cached state
    assert!(t.set_endpoint_link_up(&ep_name, true).await.is_ok());
    t.get(0).wait_for_interface_online(if_id).await;

    // Get the interface info to confirm that it is reenabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(!if_info.admin_enabled);
    assert!(if_info.phy_up);

    // Ensure that the device is still disabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, false);

    // Finally, setting admin status up should update the cached state and
    // re-add the device to the core.
    let () = stack
        .enable_interface_deprecated(if_id)
        .await
        .squash_result()
        .expect("Enable interface succeeds");

    // Get the interface info to confirm that it is reenabled.
    let test_stack = t.get(0);
    let if_info = test_stack.get_interface_info(if_id).await;
    assert!(if_info.phy_up);
    assert!(if_info.admin_enabled);

    // Ensure that the device has been enabled in the core.
    check_ip_enabled(test_stack.ctx().await.deref_mut(), core_id, true);
}

#[fasync::run_singlethreaded(test)]
async fn test_add_del_interface_address_deprecated() {
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();
    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = test_stack.get_endpoint_id(1);
    for addr in [
        new_ipv4_addr_subnet([192, 168, 0, 1], 24).into_fidl(),
        new_ipv6_addr_subnet([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 64)
            .into_fidl(),
    ]
    .iter_mut()
    {
        // The first IP address added should succeed.
        let () = stack
            .add_interface_address_deprecated(if_id, addr)
            .await
            .squash_result()
            .expect("Add interface address should succeed");
        let if_info = test_stack.get_interface_info(if_id).await;
        assert!(if_info.addresses.contains(&addr));

        // Adding the same IP address again should fail with already exists.
        let err = stack
            .add_interface_address_deprecated(if_id, addr)
            .await
            .expect("Add interface address FIDL call should succeed")
            .expect_err("Adding same address should fail");
        assert_eq!(err, fidl_net_stack::Error::AlreadyExists);

        // Deleting an IP address that exists should succeed.
        let () = stack
            .del_interface_address_deprecated(if_id, addr)
            .await
            .squash_result()
            .expect("Delete interface address succeeds");
        let if_info = test_stack.get_interface_info(if_id).await;
        assert!(!if_info.addresses.contains(&addr));

        // Deleting an IP address that doesn't exist should fail with not found.
        let err = stack
            .del_interface_address_deprecated(if_id, addr)
            .await
            .expect("Delete interface address FIDL call should succeed")
            .expect_err("Deleting non-existent address should fail");
        assert_eq!(err, fidl_net_stack::Error::NotFound);
    }
}

#[fasync::run_singlethreaded(test)]
async fn test_add_device_routes() {
    // create a stack and add a single endpoint to it so we have the interface
    // id:
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();
    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = test_stack.get_endpoint_id(1);

    let mut fwd_entry1 = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            prefix_len: 24,
        },
        device_id: if_id,
        next_hop: None,
        metric: 0,
    };
    let mut fwd_entry2 = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [10, 0, 0, 0] }),
            prefix_len: 24,
        },
        device_id: if_id,
        next_hop: None,
        metric: 0,
    };

    let () = stack
        .add_forwarding_entry(&mut fwd_entry1)
        .await
        .squash_result()
        .expect("Add forwarding entry succeeds");
    let () = stack
        .add_forwarding_entry(&mut fwd_entry2)
        .await
        .squash_result()
        .expect("Add forwarding entry succeeds");

    // finally, check that bad routes will fail:
    // a duplicate entry should fail with AlreadyExists:
    let mut bad_entry = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [192, 168, 0, 0] }),
            prefix_len: 24,
        },
        device_id: if_id,
        next_hop: None,
        metric: 0,
    };
    assert_eq!(
        stack.add_forwarding_entry(&mut bad_entry).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::AlreadyExists
    );
    // an entry with an invalid subnet should fail with Invalidargs:
    let mut bad_entry = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [10, 0, 0, 0] }),
            prefix_len: 64,
        },
        device_id: if_id,
        next_hop: None,
        metric: 0,
    };
    assert_eq!(
        stack.add_forwarding_entry(&mut bad_entry).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::InvalidArgs
    );
    // an entry with a bad devidce id should fail with NotFound:
    let mut bad_entry = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [10, 0, 0, 0] }),
            prefix_len: 24,
        },
        device_id: 10,
        next_hop: None,
        metric: 0,
    };
    assert_eq!(
        stack.add_forwarding_entry(&mut bad_entry).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::NotFound
    );
}

#[fasync::run_singlethreaded(test)]
async fn test_list_del_routes() {
    // create a stack and add a single endpoint to it so we have the interface
    // id:
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();

    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let if_id = test_stack.get_endpoint_id(1);
    let device = test_stack.ctx().await.non_sync_ctx.get_core_id(if_id);
    let route1_subnet_bytes = [192, 168, 0, 0];
    let route1_subnet_prefix = 24;
    let route1 = AddableEntryEither::new(
        SubnetEither::new(Ipv4Addr::from(route1_subnet_bytes).into(), route1_subnet_prefix)
            .unwrap(),
        device,
        None,
    )
    .unwrap();
    let sub10 = SubnetEither::new(Ipv4Addr::from([10, 0, 0, 0]).into(), 24).unwrap();
    let route2 = AddableEntryEither::new(sub10, device, None).unwrap();
    let sub10_gateway = SpecifiedAddr::new(Ipv4Addr::from([10, 0, 0, 1])).map(Into::into);
    let route3 = AddableEntryEither::new(sub10, None, sub10_gateway).unwrap();

    let () = test_stack
        .with_ctx(|Ctx { sync_ctx, non_sync_ctx }| {
            // add a couple of routes directly into core:
            netstack3_core::add_route(sync_ctx, non_sync_ctx, route1).unwrap();
            netstack3_core::add_route(sync_ctx, non_sync_ctx, route2).unwrap();
            netstack3_core::add_route(sync_ctx, non_sync_ctx, route3).unwrap();
        })
        .await;

    let routes = stack.get_forwarding_table().await.expect("Can get forwarding table");
    let route3_with_device = AddableEntryEither::new(sub10, device, sub10_gateway).unwrap();
    // Link local route is added automatically by core.
    let link_local_route =
        AddableEntryEither::new(net_declare::net_subnet_v6!("fe80::/64").into(), device, None)
            .unwrap();
    assert_eq!(
        test_stack
            .with_ctx(|ctx| {
                routes
                    .into_iter()
                    .map(|e| {
                        AddableEntryEither::try_from_fidl_with_ctx(&ctx.non_sync_ctx, e).unwrap()
                    })
                    .collect::<HashSet<_>>()
            })
            .await,
        HashSet::from([route1, route2, route3_with_device, link_local_route])
    );

    // delete route1:
    let mut fwd_entry = fidl_net_stack::ForwardingEntry {
        subnet: fidl_net::Subnet {
            addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: route1_subnet_bytes }),
            prefix_len: route1_subnet_prefix,
        },
        device_id: 0,
        next_hop: None,
        metric: 0,
    };
    let () = stack
        .del_forwarding_entry(&mut fwd_entry)
        .await
        .squash_result()
        .expect("can delete device forwarding entry");
    // can't delete again:
    assert_eq!(
        stack.del_forwarding_entry(&mut fwd_entry).await.unwrap().unwrap_err(),
        fidl_net_stack::Error::NotFound
    );

    // check that route was deleted (should've disappeared from core)
    let routes = stack.get_forwarding_table().await.expect("Can get forwarding table");
    assert_eq!(
        test_stack
            .with_ctx(|ctx| {
                routes
                    .into_iter()
                    .map(|e| {
                        AddableEntryEither::try_from_fidl_with_ctx(&ctx.non_sync_ctx, e).unwrap()
                    })
                    .collect::<HashSet<_>>()
            })
            .await,
        HashSet::from([route2, route3_with_device, link_local_route])
    );
}

#[fasync::run_singlethreaded(test)]
async fn test_add_remote_routes() {
    let mut t = TestSetupBuilder::new()
        .add_endpoint()
        .add_stack(StackSetupBuilder::new().add_endpoint(1, None))
        .build()
        .await
        .unwrap();

    let test_stack = t.get(0);
    let stack = test_stack.connect_stack().unwrap();
    let device_id = test_stack.get_endpoint_id(1);

    let subnet = fidl_net::Subnet {
        addr: fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address { addr: [192, 168, 0, 0] }),
        prefix_len: 24,
    };
    let mut fwd_entry = fidl_net_stack::ForwardingEntry {
        subnet,
        device_id: 0,
        next_hop: Some(Box::new(fidl_net::IpAddress::Ipv4(fidl_net::Ipv4Address {
            addr: [192, 168, 0, 1],
        }))),
        metric: 0,
    };

    // Cannot add gateway route without device set or on-link route to gateway.
    assert_eq!(
        stack.add_forwarding_entry(&mut fwd_entry).await.unwrap(),
        Err(fidl_net_stack::Error::BadState)
    );
    let mut device_fwd_entry = fidl_net_stack::ForwardingEntry {
        subnet: fwd_entry.subnet,
        device_id,
        next_hop: None,
        metric: 0,
    };
    let () = stack
        .add_forwarding_entry(&mut device_fwd_entry)
        .await
        .squash_result()
        .expect("add device route");

    let () =
        stack.add_forwarding_entry(&mut fwd_entry).await.squash_result().expect("add device route");

    // finally, check that bad routes will fail:
    // a duplicate entry should fail with AlreadyExists:
    assert_eq!(
        stack.add_forwarding_entry(&mut fwd_entry).await.unwrap(),
        Err(fidl_net_stack::Error::AlreadyExists)
    );
}
