// Copyright 2018 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.

//! Testing-related utilities.

use std::collections::{BinaryHeap, HashMap};
use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
use std::num::NonZeroU16;
use std::ops;
use std::sync::Once;
use std::time::Duration;

use byteorder::{ByteOrder, NativeEndian};
use log::{debug, trace};
use net_types::ethernet::Mac;
use net_types::ip::{
    AddrSubnet, Ip, IpAddr, IpAddress, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr, Subnet, SubnetEither,
};
use net_types::{SpecifiedAddr, Witness};
use packet::{Buf, BufferMut, ParsablePacket, ParseBuffer, Serializer};
use rand::{self, CryptoRng, RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use crate::device::ethernet::EtherType;
use crate::device::{DeviceId, DeviceLayerEventDispatcher};
use crate::error::{IpParseResult, NoRouteError, ParseError, ParseResult};
use crate::ip::icmp::{BufferIcmpEventDispatcher, IcmpConnId, IcmpEventDispatcher, IcmpIpExt};
use crate::ip::{IpExtByteSlice, IpLayerEventDispatcher, IpProto};
use crate::transport::tcp::TcpOption;
use crate::transport::udp::UdpEventDispatcher;
use crate::transport::TransportLayerEventDispatcher;
use crate::wire::ethernet::{EthernetFrame, EthernetFrameLengthCheck};
use crate::wire::icmp::{self as wire_icmp, IcmpMessage, IcmpPacket, IcmpParseArgs};
use crate::wire::ipv4::Ipv4Packet;
use crate::wire::ipv6::Ipv6Packet;
use crate::wire::tcp::TcpSegment;
use crate::wire::udp::UdpPacket;
use crate::{handle_timeout, Context, EventDispatcher, Instant, StackStateBuilder, TimerId};

/// Utilities to allow running benchmarks as tests.
///
/// Our benchmarks rely on the unstable `test` feature, which is disallowed in
/// Fuchsia's build system. In order to ensure that our benchmarks are always
/// compiled and tested, this module provides mocks that allow us to run our
/// benchmarks as normal tests when the `benchmark` feature is disabled.
///
/// See the `bench!` macro for details on how this module is used.
pub(crate) mod benchmarks {
    /// A trait to allow mocking of the `test::Bencher` type.
    pub(crate) trait Bencher {
        fn iter<T, F: FnMut() -> T>(&mut self, inner: F);
    }

    #[cfg(feature = "benchmark")]
    impl Bencher for test::Bencher {
        fn iter<T, F: FnMut() -> T>(&mut self, inner: F) {
            test::Bencher::iter(self, inner)
        }
    }

    /// A `Bencher` whose `iter` method runs the provided argument once.
    #[cfg(not(feature = "benchmark"))]
    pub(crate) struct TestBencher;

    #[cfg(not(feature = "benchmark"))]
    impl Bencher for TestBencher {
        fn iter<T, F: FnMut() -> T>(&mut self, mut inner: F) {
            super::set_logger_for_test();
            inner();
        }
    }

    #[inline(always)]
    pub(crate) fn black_box<T>(dummy: T) -> T {
        #[cfg(feature = "benchmark")]
        return test::black_box(dummy);
        #[cfg(not(feature = "benchmark"))]
        return dummy;
    }
}

/// A wrapper which implements `RngCore` and `CryptoRng` for any `RngCore`.
///
/// This is used to satisfy [`EventDispatcher`]'s requirement that the
/// associated `Rng` type implements `CryptoRng`.
///
/// # Security
///
/// This is obviously insecure. Don't use it except in testing!
pub(crate) struct FakeCryptoRng<R>(R);

impl Default for FakeCryptoRng<XorShiftRng> {
    fn default() -> FakeCryptoRng<XorShiftRng> {
        FakeCryptoRng::new_xorshift(12957992561116578403)
    }
}

impl FakeCryptoRng<XorShiftRng> {
    /// Creates a new [`FakeCryptoRng<XorShiftRng>`] from a seed.
    pub(crate) fn new_xorshift(seed: u64) -> FakeCryptoRng<XorShiftRng> {
        FakeCryptoRng(new_rng(seed))
    }
}

impl<R: RngCore> RngCore for FakeCryptoRng<R> {
    fn next_u32(&mut self) -> u32 {
        self.0.next_u32()
    }
    fn next_u64(&mut self) -> u64 {
        self.0.next_u64()
    }
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.0.fill_bytes(dest)
    }
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
        self.0.try_fill_bytes(dest)
    }
}

impl<R: RngCore> CryptoRng for FakeCryptoRng<R> {}

impl<R: RngCore> crate::context::RngContext for FakeCryptoRng<R> {
    type Rng = Self;

    fn rng(&mut self) -> &mut Self::Rng {
        self
    }
}

/// Create a new deterministic RNG from a seed.
pub(crate) fn new_rng(mut seed: u64) -> XorShiftRng {
    if seed == 0 {
        // XorShiftRng can't take 0 seeds
        seed = 1;
    }
    let mut bytes = [0; 16];
    NativeEndian::write_u32(&mut bytes[0..4], seed as u32);
    NativeEndian::write_u32(&mut bytes[4..8], (seed >> 32) as u32);
    NativeEndian::write_u32(&mut bytes[8..12], seed as u32);
    NativeEndian::write_u32(&mut bytes[12..16], (seed >> 32) as u32);
    XorShiftRng::from_seed(bytes)
}

/// Creates `iterations` fake RNGs.
///
/// `with_fake_rngs` will create `iterations` different [`FakeCryptoRng`]s and
/// call the function `f` for each one of them.
///
/// This function can be used for tests that weed out weirdnesses that can
/// happen with certain random number sequences.
pub(crate) fn with_fake_rngs<F: Fn(FakeCryptoRng<XorShiftRng>)>(iterations: u64, f: F) {
    for seed in 0..iterations {
        f(FakeCryptoRng::new_xorshift(seed))
    }
}

#[derive(Default, Debug)]
pub(crate) struct TestCounters {
    data: HashMap<String, usize>,
}

impl TestCounters {
    pub(crate) fn increment(&mut self, key: &str) {
        *(self.data.entry(key.to_string()).or_insert(0)) += 1;
    }

    pub(crate) fn get(&self, key: &str) -> &usize {
        self.data.get(key).unwrap_or(&0)
    }
}

/// 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.args())
    }

    fn flush(&self) {}
}

static LOGGER: Logger = Logger;

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

/// Install a logger for tests.
///
/// Call this method at the beginning of the test for which logging is desired.
/// This function sets global program state, so all tests that run after this
/// function is called will use the logger.
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);
    })
}

/// Skip current time forward to trigger the next timer event.
///
/// Returns true if a timer was triggered, false if there were no timers waiting
/// to be triggered.
pub(crate) fn trigger_next_timer(ctx: &mut Context<DummyEventDispatcher>) -> bool {
    match ctx.dispatcher.timer_events.pop() {
        Some(InstantAndData(t, id)) => {
            ctx.dispatcher.current_time = t;
            handle_timeout(ctx, id);
            true
        }
        None => false,
    }
}

/// Skip current time forward by `duration`, triggering all timer events until then,
/// inclusive.
///
/// Returns the number of timer events triggered.
pub(crate) fn run_for(ctx: &mut Context<DummyEventDispatcher>, duration: Duration) -> usize {
    let end_time = ctx.dispatcher.now() + duration;
    let mut timers_fired = 0;

    while let Some(tmr) = ctx.dispatcher.timer_events.peek() {
        if tmr.0 > end_time {
            break;
        }

        assert!(trigger_next_timer(ctx));
        timers_fired += 1;
    }

    assert!(ctx.dispatcher.now() <= end_time);
    ctx.dispatcher.current_time = end_time;

    timers_fired
}

/// Trigger timer events until`f` callback returns true or passes the max
/// number of iterations.
///
/// `trigger_timers_until` always calls `f` on the first timer event, as the
/// timer_events is dynamically updated. As soon as `f` returns true or
/// 1,000,000 timer events have been triggered, `trigger_timers_until` will
/// exit.
///
/// Please note, the caller is expected to pass in an `f` which could return
/// true to exit `trigger_timer_until`. 1,000,000 limit is set to avoid an
/// endless loop.
pub(crate) fn trigger_timers_until<F: Fn(&TimerId) -> bool>(
    ctx: &mut Context<DummyEventDispatcher>,
    f: F,
) {
    for _ in 0..1_000_000 {
        let InstantAndData(t, id) = if let Some(t) = ctx.dispatcher.timer_events.pop() {
            t
        } else {
            return;
        };

        ctx.dispatcher.current_time = t;
        handle_timeout(ctx, id);
        if f(&id) {
            break;
        }
    }
}

/// Metadata of an Ethernet frame.
pub(crate) struct EthernetFrameMetadata {
    pub(crate) src_mac: Mac,
    pub(crate) dst_mac: Mac,
    pub(crate) ethertype: Option<EtherType>,
}

/// Metadata of an IPv4 packet.
pub(crate) struct Ipv4PacketMetadata {
    pub(crate) dscp: u8,
    pub(crate) ecn: u8,
    pub(crate) id: u16,
    pub(crate) dont_fragment: bool,
    pub(crate) more_fragments: bool,
    pub(crate) fragment_offset: u16,
    pub(crate) ttl: u8,
    pub(crate) proto: IpProto,
    pub(crate) src_ip: Ipv4Addr,
    pub(crate) dst_ip: Ipv4Addr,
}

/// Metadata of an IPv6 packet.
pub(crate) struct Ipv6PacketMetadata {
    pub(crate) ds: u8,
    pub(crate) ecn: u8,
    pub(crate) flowlabel: u32,
    pub(crate) hop_limit: u8,
    pub(crate) src_ip: Ipv6Addr,
    pub(crate) dst_ip: Ipv6Addr,
}

/// Metadata of a TCP segment.
pub(crate) struct TcpSegmentMetadata {
    pub(crate) src_port: u16,
    pub(crate) dst_port: u16,
    pub(crate) seq_num: u32,
    pub(crate) ack_num: Option<u32>,
    pub(crate) _flags: u16,
    pub(crate) _psh: bool,
    pub(crate) rst: bool,
    pub(crate) syn: bool,
    pub(crate) fin: bool,
    pub(crate) window_size: u16,
    pub(crate) options: &'static [TcpOption<'static>],
}

/// Metadata of a UDP packet.
pub(crate) struct UdpPacketMetadata {
    pub(crate) src_port: u16,
    pub(crate) dst_port: u16,
}

/// Represents a packet (usually from a live capture) used for testing.
///
/// Includes the raw bytes, metadata of the packet (currently just fields from the packet header)
/// and the range which indicates where the body is.
pub(crate) struct TestPacket<M> {
    pub(crate) bytes: &'static [u8],
    pub(crate) metadata: M,
    pub(crate) body_range: ops::Range<usize>,
}

/// Verify that a parsed Ethernet frame is as expected.
///
/// Ensures the parsed packet's header fields and body are equal to those in the test packet.
pub(crate) fn verify_ethernet_frame(
    frame: &EthernetFrame<&[u8]>,
    expected: TestPacket<EthernetFrameMetadata>,
) {
    assert_eq!(frame.src_mac(), expected.metadata.src_mac);
    assert_eq!(frame.dst_mac(), expected.metadata.dst_mac);
    assert_eq!(frame.ethertype(), expected.metadata.ethertype);
    assert_eq!(frame.body(), &expected.bytes[expected.body_range]);
}

/// Verify that a parsed IPv4 packet is as expected.
///
/// Ensures the parsed packet's header fields and body are equal to those in the test packet.
pub(crate) fn verify_ipv4_packet(
    packet: &Ipv4Packet<&[u8]>,
    expected: TestPacket<Ipv4PacketMetadata>,
) {
    use crate::wire::ipv4::Ipv4Header;

    assert_eq!(packet.dscp(), expected.metadata.dscp);
    assert_eq!(packet.ecn(), expected.metadata.ecn);
    assert_eq!(packet.id(), expected.metadata.id);
    assert_eq!(packet.df_flag(), expected.metadata.dont_fragment);
    assert_eq!(packet.mf_flag(), expected.metadata.more_fragments);
    assert_eq!(packet.fragment_offset(), expected.metadata.fragment_offset);
    assert_eq!(packet.ttl(), expected.metadata.ttl);
    assert_eq!(packet.proto(), expected.metadata.proto);
    assert_eq!(packet.src_ip(), expected.metadata.src_ip);
    assert_eq!(packet.dst_ip(), expected.metadata.dst_ip);
    assert_eq!(packet.body(), &expected.bytes[expected.body_range]);
}

/// Verify that a parsed IPv6 packet is as expected.
///
/// Ensures the parsed packet's header fields and body are equal to those in the test packet.
pub(crate) fn verify_ipv6_packet(
    packet: &Ipv6Packet<&[u8]>,
    expected: TestPacket<Ipv6PacketMetadata>,
) {
    assert_eq!(packet.ds(), expected.metadata.ds);
    assert_eq!(packet.ecn(), expected.metadata.ecn);
    assert_eq!(packet.flowlabel(), expected.metadata.flowlabel);
    assert_eq!(packet.hop_limit(), expected.metadata.hop_limit);
    assert_eq!(packet.src_ip(), expected.metadata.src_ip);
    assert_eq!(packet.dst_ip(), expected.metadata.dst_ip);
    assert_eq!(packet.body(), &expected.bytes[expected.body_range]);
}

/// Verify that a parsed UDP packet is as expected.
///
/// Ensures the parsed packet's header fields and body are equal to those in the test packet.
pub(crate) fn verify_udp_packet(
    packet: &UdpPacket<&[u8]>,
    expected: TestPacket<UdpPacketMetadata>,
) {
    assert_eq!(packet.src_port().map(NonZeroU16::get).unwrap_or(0), expected.metadata.src_port);
    assert_eq!(packet.dst_port().get(), expected.metadata.dst_port);
    assert_eq!(packet.body(), &expected.bytes[expected.body_range]);
}

/// Verify that a parsed TCP segment is as expected.
///
/// Ensures the parsed packet's header fields and body are equal to those in the test packet.
pub(crate) fn verify_tcp_segment(
    segment: &TcpSegment<&[u8]>,
    expected: TestPacket<TcpSegmentMetadata>,
) {
    assert_eq!(segment.src_port().get(), expected.metadata.src_port);
    assert_eq!(segment.dst_port().get(), expected.metadata.dst_port);
    assert_eq!(segment.seq_num(), expected.metadata.seq_num);
    assert_eq!(segment.ack_num(), expected.metadata.ack_num);
    assert_eq!(segment.rst(), expected.metadata.rst);
    assert_eq!(segment.syn(), expected.metadata.syn);
    assert_eq!(segment.fin(), expected.metadata.fin);
    assert_eq!(segment.window_size(), expected.metadata.window_size);
    assert_eq!(segment.iter_options().collect::<Vec<_>>().as_slice(), expected.metadata.options);
    assert_eq!(segment.body(), &expected.bytes[expected.body_range]);
}

/// Parse an ethernet frame.
///
/// `parse_ethernet_frame` parses an ethernet frame, returning the body along
/// with some important header fields.
pub(crate) fn parse_ethernet_frame(
    mut buf: &[u8],
) -> ParseResult<(&[u8], Mac, Mac, Option<EtherType>)> {
    let frame = (&mut buf).parse_with::<_, EthernetFrame<_>>(EthernetFrameLengthCheck::Check)?;
    let src_mac = frame.src_mac();
    let dst_mac = frame.dst_mac();
    let ethertype = frame.ethertype();
    Ok((buf, src_mac, dst_mac, ethertype))
}

/// Parse an IP packet.
///
/// `parse_ip_packet` parses an IP packet, returning the body along with some
/// important header fields.
#[allow(clippy::type_complexity)]
pub(crate) fn parse_ip_packet<I: Ip>(
    mut buf: &[u8],
) -> IpParseResult<I, (&[u8], I::Addr, I::Addr, IpProto, u8)> {
    use crate::ip::IpPacket;

    let packet = (&mut buf).parse::<<I as IpExtByteSlice<_>>::Packet>()?;
    let src_ip = packet.src_ip();
    let dst_ip = packet.dst_ip();
    let proto = packet.proto();
    let ttl = packet.ttl();
    // Because the packet type here is generic, Rust doesn't know that it
    // doesn't implement Drop, and so it doesn't know that it's safe to drop as
    // soon as it's no longer used and allow buf to no longer be borrowed on the
    // next line. It works fine in parse_ethernet_frame because EthernetFrame is
    // a concrete type which Rust knows doesn't implement Drop.
    std::mem::drop(packet);
    Ok((buf, src_ip, dst_ip, proto, ttl))
}

/// Parse an ICMP packet.
///
/// `parse_icmp_packet` parses an ICMP packet, returning the body along with
/// some important fields. Before returning, it invokes the callback `f` on the
/// parsed packet.
pub(crate) fn parse_icmp_packet<
    I: wire_icmp::IcmpIpExt,
    C,
    M: for<'a> IcmpMessage<I, &'a [u8], Code = C>,
    F: for<'a> FnOnce(&IcmpPacket<I, &'a [u8], M>),
>(
    mut buf: &[u8],
    src_ip: I::Addr,
    dst_ip: I::Addr,
    f: F,
) -> ParseResult<(M, C)>
where
    for<'a> IcmpPacket<I, &'a [u8], M>:
        ParsablePacket<&'a [u8], IcmpParseArgs<I::Addr>, Error = ParseError>,
{
    let packet =
        (&mut buf).parse_with::<_, IcmpPacket<I, _, M>>(IcmpParseArgs::new(src_ip, dst_ip))?;
    let message = *packet.message();
    let code = packet.code();
    f(&packet);
    Ok((message, code))
}

/// Parse an IP packet in an Ethernet frame.
///
/// `parse_ip_packet_in_ethernet_frame` parses an IP packet in an Ethernet
/// frame, returning the body of the IP packet along with some important fields
/// from both the IP and Ethernet headers.
#[allow(clippy::type_complexity)]
pub(crate) fn parse_ip_packet_in_ethernet_frame<I: Ip>(
    buf: &[u8],
) -> IpParseResult<I, (&[u8], Mac, Mac, I::Addr, I::Addr, IpProto, u8)> {
    use crate::device::ethernet::EthernetIpExt;
    let (body, src_mac, dst_mac, ethertype) = parse_ethernet_frame(buf)?;
    if ethertype != Some(I::ETHER_TYPE) {
        debug!("unexpected ethertype: {:?}", ethertype);
        return Err(ParseError::NotExpected.into());
    }

    let (body, src_ip, dst_ip, proto, ttl) = parse_ip_packet::<I>(body)?;
    Ok((body, src_mac, dst_mac, src_ip, dst_ip, proto, ttl))
}

/// Parse an ICMP packet in an IP packet in an Ethernet frame.
///
/// `parse_icmp_packet_in_ip_packet_in_ethernet_frame` parses an ICMP packet in
/// an IP packet in an Ethernet frame, returning the message and code from the
/// ICMP packet along with some important fields from both the IP and Ethernet
/// headers. Before returning, it invokes the callback `f` on the parsed packet.
#[allow(clippy::type_complexity)]
pub(crate) fn parse_icmp_packet_in_ip_packet_in_ethernet_frame<
    I: wire_icmp::IcmpIpExt,
    C,
    M: for<'a> IcmpMessage<I, &'a [u8], Code = C>,
    F: for<'a> FnOnce(&IcmpPacket<I, &'a [u8], M>),
>(
    buf: &[u8],
    f: F,
) -> IpParseResult<I, (Mac, Mac, I::Addr, I::Addr, u8, M, C)>
where
    for<'a> IcmpPacket<I, &'a [u8], M>:
        ParsablePacket<&'a [u8], IcmpParseArgs<I::Addr>, Error = ParseError>,
{
    let (body, src_mac, dst_mac, src_ip, dst_ip, proto, ttl) =
        parse_ip_packet_in_ethernet_frame::<I>(buf)?;
    if proto != I::ICMP_IP_PROTO {
        debug!("unexpected IP protocol: {} (wanted {})", proto, I::ICMP_IP_PROTO);
        return Err(ParseError::NotExpected.into());
    }
    let (message, code) = parse_icmp_packet(body, src_ip, dst_ip, f)?;
    Ok((src_mac, dst_mac, src_ip, dst_ip, ttl, message, code))
}

/// Get the counter value for a `key`.
pub(crate) fn get_counter_val(ctx: &mut Context<DummyEventDispatcher>, key: &str) -> usize {
    *ctx.state.test_counters.get(key)
}

/// An extension trait for `Ip` providing test-related functionality.
pub(crate) trait TestIpExt: Ip {
    /// Either [`DUMMY_CONFIG_V4`] or [`DUMMY_CONFIG_V6`].
    const DUMMY_CONFIG: DummyEventDispatcherConfig<Self::Addr>;

    /// Get an IP address in the same subnet as `Self::DUMMY_CONFIG`.
    ///
    /// `last` is the value to be put in the last octet of the IP address.
    fn get_other_ip_address(last: u8) -> SpecifiedAddr<Self::Addr>;

    /// Get an IP address in a different subnet from `Self::DUMMY_CONFIG`.
    ///
    /// `last` is the value to be put in the last octet of the IP address.
    fn get_other_remote_ip_address(last: u8) -> SpecifiedAddr<Self::Addr>;
}

impl TestIpExt for Ipv4 {
    const DUMMY_CONFIG: DummyEventDispatcherConfig<Ipv4Addr> = DUMMY_CONFIG_V4;

    fn get_other_ip_address(last: u8) -> SpecifiedAddr<Ipv4Addr> {
        let mut bytes = Self::DUMMY_CONFIG.local_ip.get().ipv4_bytes();
        bytes[bytes.len() - 1] = last;
        SpecifiedAddr::new(Ipv4Addr::new(bytes)).unwrap()
    }

    fn get_other_remote_ip_address(last: u8) -> SpecifiedAddr<Self::Addr> {
        let mut bytes = Self::DUMMY_CONFIG.local_ip.get().ipv4_bytes();
        bytes[bytes.len() - 3] += 1;
        bytes[bytes.len() - 1] = last;
        SpecifiedAddr::new(Ipv4Addr::new(bytes)).unwrap()
    }
}

impl TestIpExt for Ipv6 {
    const DUMMY_CONFIG: DummyEventDispatcherConfig<Ipv6Addr> = DUMMY_CONFIG_V6;

    fn get_other_ip_address(last: u8) -> SpecifiedAddr<Ipv6Addr> {
        let mut bytes = Self::DUMMY_CONFIG.local_ip.get().ipv6_bytes();
        bytes[bytes.len() - 1] = last;
        SpecifiedAddr::new(Ipv6Addr::new(bytes)).unwrap()
    }

    fn get_other_remote_ip_address(last: u8) -> SpecifiedAddr<Self::Addr> {
        let mut bytes = Self::DUMMY_CONFIG.local_ip.get().ipv6_bytes();
        bytes[bytes.len() - 3] += 1;
        bytes[bytes.len() - 1] = last;
        SpecifiedAddr::new(Ipv6Addr::new(bytes)).unwrap()
    }
}

/// A configuration for a simple network.
///
/// `DummyEventDispatcherConfig` describes a simple network with two IP hosts
/// - one remote and one local - both on the same Ethernet network.
#[derive(Clone)]
pub(crate) struct DummyEventDispatcherConfig<A: IpAddress> {
    /// The subnet of the local Ethernet network.
    pub(crate) subnet: Subnet<A>,
    /// The IP address of our interface to the local network (must be in
    /// subnet).
    pub(crate) local_ip: SpecifiedAddr<A>,
    /// The MAC address of our interface to the local network.
    pub(crate) local_mac: Mac,
    /// The remote host's IP address (must be in subnet if provided).
    pub(crate) remote_ip: SpecifiedAddr<A>,
    /// The remote host's MAC address.
    pub(crate) remote_mac: Mac,
}

/// A `DummyEventDispatcherConfig` with reasonable values for an IPv4 network.
pub(crate) const DUMMY_CONFIG_V4: DummyEventDispatcherConfig<Ipv4Addr> = unsafe {
    DummyEventDispatcherConfig {
        subnet: Subnet::new_unchecked(Ipv4Addr::new([192, 168, 0, 0]), 16),
        local_ip: SpecifiedAddr::new_unchecked(Ipv4Addr::new([192, 168, 0, 1])),
        local_mac: Mac::new([0, 1, 2, 3, 4, 5]),
        remote_ip: SpecifiedAddr::new_unchecked(Ipv4Addr::new([192, 168, 0, 2])),
        remote_mac: Mac::new([6, 7, 8, 9, 10, 11]),
    }
};

/// A `DummyEventDispatcherConfig` with reasonable values for an IPv6 network.
pub(crate) const DUMMY_CONFIG_V6: DummyEventDispatcherConfig<Ipv6Addr> = unsafe {
    DummyEventDispatcherConfig {
        subnet: Subnet::new_unchecked(
            Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 0]),
            112,
        ),
        local_ip: SpecifiedAddr::new_unchecked(Ipv6Addr::new([
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 1,
        ])),
        local_mac: Mac::new([0, 1, 2, 3, 4, 5]),
        remote_ip: SpecifiedAddr::new_unchecked(Ipv6Addr::new([
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, 2,
        ])),
        remote_mac: Mac::new([6, 7, 8, 9, 10, 11]),
    }
};

impl<A: IpAddress> DummyEventDispatcherConfig<A> {
    /// Creates a copy of `self` with all the remote and local fields reversed.
    pub(crate) fn swap(&self) -> Self {
        Self {
            subnet: self.subnet,
            local_ip: self.remote_ip,
            local_mac: self.remote_mac,
            remote_ip: self.local_ip,
            remote_mac: self.local_mac,
        }
    }
}

/// A builder for `DummyEventDispatcher`s.
///
/// A `DummyEventDispatcherBuilder` is capable of storing the configuration of a
/// network stack including forwarding table entries, devices and their assigned
/// IP addresses, ARP table entries, etc. It can be built using `build`,
/// producing a `Context<DummyEventDispatcher>` with all of the appropriate
/// state configured.
#[derive(Clone, Default)]
pub(crate) struct DummyEventDispatcherBuilder {
    devices: Vec<(Mac, Option<(IpAddr, SubnetEither)>)>,
    arp_table_entries: Vec<(usize, Ipv4Addr, Mac)>,
    ndp_table_entries: Vec<(usize, Ipv6Addr, Mac)>,
    // usize refers to index into devices Vec
    device_routes: Vec<(SubnetEither, usize)>,
    routes: Vec<(SubnetEither, SpecifiedAddr<IpAddr>)>,
}

impl DummyEventDispatcherBuilder {
    /// Construct a `DummyEventDispatcherBuilder` from a `DummyEventDispatcherConfig`.
    pub(crate) fn from_config<A: IpAddress>(
        cfg: DummyEventDispatcherConfig<A>,
    ) -> DummyEventDispatcherBuilder {
        assert!(cfg.subnet.contains(&cfg.local_ip));
        assert!(cfg.subnet.contains(&cfg.remote_ip));

        let mut builder = DummyEventDispatcherBuilder::default();
        builder.devices.push((cfg.local_mac, Some((cfg.local_ip.get().into(), cfg.subnet.into()))));

        // NOTE: We use two separate calls here rather than a single call to
        // `.with` because both closures mutably borrow `builder`, and so they
        // can't exist at the same time, which would be required in order to
        // pass them both to `.with`.
        cfg.remote_ip
            .get()
            .with_v4(|ip| builder.arp_table_entries.push((0, ip, cfg.remote_mac)), ());
        cfg.remote_ip
            .get()
            .with_v6(|ip| builder.ndp_table_entries.push((0, ip, cfg.remote_mac)), ());

        // even with fixed ipv4 address we can have ipv6 link local addresses
        // pre-cached.
        builder.ndp_table_entries.push((
            0,
            cfg.remote_mac.to_ipv6_link_local().addr().get(),
            cfg.remote_mac,
        ));

        builder.device_routes.push((cfg.subnet.into(), 0));
        builder
    }

    /// Add a device.
    ///
    /// `add_device` returns a key which can be used to refer to the device in
    /// future calls to `add_arp_table_entry` and `add_device_route`.
    pub(crate) fn add_device(&mut self, mac: Mac) -> usize {
        let idx = self.devices.len();
        self.devices.push((mac, None));
        idx
    }

    /// Add a device with an associated IP address.
    ///
    /// `add_device_with_ip` is like `add_device`, except that it takes an
    /// associated IP address and subnet to assign to the device.
    pub(crate) fn add_device_with_ip<A: IpAddress>(
        &mut self,
        mac: Mac,
        ip: A,
        subnet: Subnet<A>,
    ) -> usize {
        let idx = self.devices.len();
        self.devices.push((mac, Some((ip.into(), subnet.into()))));
        idx
    }

    /// Add an ARP table entry for a device's ARP table.
    pub(crate) fn add_arp_table_entry(&mut self, device: usize, ip: Ipv4Addr, mac: Mac) {
        self.arp_table_entries.push((device, ip, mac));
    }

    /// Add an NDP table entry for a device's NDP table.
    pub(crate) fn add_ndp_table_entry(&mut self, device: usize, ip: Ipv6Addr, mac: Mac) {
        self.ndp_table_entries.push((device, ip, mac));
    }

    /// Build a `Context` from the present configuration with a default
    /// dispatcher, and stack state set to disable NDP's Duplicate Address
    /// Detection by default.
    pub(crate) fn build<D: EventDispatcher + Default>(self) -> Context<D> {
        self.build_with_modifications(|_| {})
    }

    /// `build_with_modifications` is equivalent to `build`, except that after
    /// the `StackStateBuilder` is initialized, it is passed to `f` for further
    /// modification before the `Context` is constructed.
    pub(crate) fn build_with_modifications<
        D: EventDispatcher + Default,
        F: FnOnce(&mut StackStateBuilder),
    >(
        self,
        f: F,
    ) -> Context<D> {
        let mut stack_builder = StackStateBuilder::default();

        // Most tests do not need NDP's DAD or router solicitation so disable it here.
        let mut ndp_configs = crate::device::ndp::NdpConfigurations::default();
        ndp_configs.set_dup_addr_detect_transmits(None);
        ndp_configs.set_max_router_solicitations(None);
        stack_builder.device_builder().set_default_ndp_configs(ndp_configs);

        f(&mut stack_builder);
        self.build_with(stack_builder, D::default())
    }

    /// Build a `Context` from the present configuration with a caller-provided
    /// dispatcher and `StackStateBuilder`.
    pub(crate) fn build_with<D: EventDispatcher>(
        self,
        state_builder: StackStateBuilder,
        dispatcher: D,
    ) -> Context<D> {
        let mut ctx = Context::new(state_builder.build(), dispatcher);

        let DummyEventDispatcherBuilder {
            devices,
            arp_table_entries,
            ndp_table_entries,
            device_routes,
            routes,
        } = self;
        let mut idx_to_device_id =
            HashMap::<_, _, std::collections::hash_map::RandomState>::default();
        for (idx, (mac, ip_subnet)) in devices.into_iter().enumerate() {
            let id = ctx.state.add_ethernet_device(mac, Ipv6::MINIMUM_LINK_MTU.into());
            idx_to_device_id.insert(idx, id);
            crate::device::initialize_device(&mut ctx, id);
            match ip_subnet {
                Some((IpAddr::V4(ip), SubnetEither::V4(subnet))) => {
                    let addr_sub = AddrSubnet::new(ip, subnet.prefix()).unwrap();
                    crate::device::add_ip_addr_subnet(&mut ctx, id, addr_sub).unwrap();
                }
                Some((IpAddr::V6(ip), SubnetEither::V6(subnet))) => {
                    let addr_sub = AddrSubnet::new(ip, subnet.prefix()).unwrap();
                    crate::device::add_ip_addr_subnet(&mut ctx, id, addr_sub).unwrap();
                }
                None => {}
                _ => unreachable!(),
            }
        }
        for (idx, ip, mac) in arp_table_entries {
            let device = *idx_to_device_id.get(&idx).unwrap();
            crate::device::insert_static_arp_table_entry(&mut ctx, device, ip, mac);
        }
        for (idx, ip, mac) in ndp_table_entries {
            let device = *idx_to_device_id.get(&idx).unwrap();
            crate::device::insert_ndp_table_entry(&mut ctx, device, ip, mac);
        }
        for (subnet, idx) in device_routes {
            let device = *idx_to_device_id.get(&idx).unwrap();
            match subnet {
                SubnetEither::V4(subnet) => {
                    crate::ip::add_device_route(&mut ctx, subnet, device).unwrap()
                }
                SubnetEither::V6(subnet) => {
                    crate::ip::add_device_route(&mut ctx, subnet, device).unwrap()
                }
            };
        }
        for (subnet, next_hop) in routes {
            match (subnet, next_hop.into()) {
                (SubnetEither::V4(subnet), IpAddr::V4(next_hop)) => {
                    crate::ip::add_route(&mut ctx, subnet, next_hop).unwrap()
                }
                (SubnetEither::V6(subnet), IpAddr::V6(next_hop)) => {
                    crate::ip::add_route(&mut ctx, subnet, next_hop).unwrap()
                }
                _ => unreachable!(),
            };
        }

        ctx
    }
}

/// Add either an NDP entry (if IPv6) or ARP entry (if IPv4) to a `DummyEventDispatcherBuilder`.
pub(crate) fn add_arp_or_ndp_table_entry<A: IpAddress>(
    builder: &mut DummyEventDispatcherBuilder,
    device: usize,
    ip: A,
    mac: Mac,
) {
    // NOTE: We use two separate calls here rather than a single call to `.with`
    // because both closures mutably borrow `builder`, and so they can't exist
    // at the same time, which would be required in order to pass them both to
    // `.with`.
    ip.with_v4(|ip| builder.add_arp_table_entry(device, ip, mac), ());
    ip.with_v6(|ip| builder.add_ndp_table_entry(device, ip, mac), ());
}

impl Instant for std::time::Instant {
    fn duration_since(&self, earlier: std::time::Instant) -> Duration {
        std::time::Instant::duration_since(self, earlier)
    }

    fn checked_add(&self, duration: Duration) -> Option<Self> {
        std::time::Instant::checked_add(self, duration)
    }

    fn checked_sub(&self, duration: Duration) -> Option<Self> {
        std::time::Instant::checked_sub(self, duration)
    }
}

/// A dummy implementation of `Instant` for use in testing.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub(crate) struct DummyInstant {
    // A DummyInstant is just an offset from some arbitrary epoch.
    offset: Duration,
}

impl Instant for DummyInstant {
    fn duration_since(&self, earlier: DummyInstant) -> Duration {
        self.offset.checked_sub(earlier.offset).unwrap()
    }

    fn checked_add(&self, duration: Duration) -> Option<DummyInstant> {
        self.offset.checked_add(duration).map(|offset| DummyInstant { offset })
    }

    fn checked_sub(&self, duration: Duration) -> Option<DummyInstant> {
        self.offset.checked_sub(duration).map(|offset| DummyInstant { offset })
    }
}

impl ops::Add<Duration> for DummyInstant {
    type Output = DummyInstant;

    fn add(self, other: Duration) -> DummyInstant {
        DummyInstant { offset: self.offset + other }
    }
}

impl ops::Sub<DummyInstant> for DummyInstant {
    type Output = Duration;

    fn sub(self, other: DummyInstant) -> Duration {
        self.offset - other.offset
    }
}

impl ops::Sub<Duration> for DummyInstant {
    type Output = DummyInstant;

    fn sub(self, other: Duration) -> DummyInstant {
        DummyInstant { offset: self.offset - other }
    }
}

impl Debug for DummyInstant {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self.offset)
    }
}

/// Represents arbitrary data of type `D` attached to a `DummyInstant`.
///
/// `InstantAndData` implements `Ord` and `Eq` to be used in a `BinaryHeap` and
/// ordered by `DummyInstant`.
struct InstantAndData<D>(DummyInstant, D);

impl<D> InstantAndData<D> {
    fn new(time: DummyInstant, data: D) -> Self {
        Self(time, data)
    }
}

impl<D> Eq for InstantAndData<D> {}

impl<D> PartialEq for InstantAndData<D> {
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0
    }
}

impl<D> Ord for InstantAndData<D> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        other.0.cmp(&self.0)
    }
}

impl<D> PartialOrd for InstantAndData<D> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

type PendingTimer = InstantAndData<TimerId>;

/// A dummy `EventDispatcher` used for testing.
///
/// A `DummyEventDispatcher` implements the `EventDispatcher` interface for
/// testing purposes. It provides facilities to inspect the history of what
/// events have been emitted to the system.
pub(crate) struct DummyEventDispatcher {
    frames_sent: Vec<(DeviceId, Vec<u8>)>,
    timer_events: BinaryHeap<PendingTimer>,
    current_time: DummyInstant,
    rng: FakeCryptoRng<XorShiftRng>,
    icmpv4_replies: HashMap<IcmpConnId<Ipv4>, Vec<(u16, Vec<u8>)>>,
    icmpv6_replies: HashMap<IcmpConnId<Ipv6>, Vec<(u16, Vec<u8>)>>,
}

impl Default for DummyEventDispatcher {
    fn default() -> DummyEventDispatcher {
        DummyEventDispatcher {
            frames_sent: Default::default(),
            timer_events: Default::default(),
            current_time: Default::default(),
            rng: FakeCryptoRng(new_rng(0)),
            icmpv4_replies: Default::default(),
            icmpv6_replies: Default::default(),
        }
    }
}

pub(crate) trait TestutilIpExt: Ip {
    fn icmp_replies(
        evt: &mut DummyEventDispatcher,
    ) -> &mut HashMap<IcmpConnId<Self>, Vec<(u16, Vec<u8>)>>;
}

impl TestutilIpExt for Ipv4 {
    fn icmp_replies(
        evt: &mut DummyEventDispatcher,
    ) -> &mut HashMap<IcmpConnId<Ipv4>, Vec<(u16, Vec<u8>)>> {
        &mut evt.icmpv4_replies
    }
}

impl TestutilIpExt for Ipv6 {
    fn icmp_replies(
        evt: &mut DummyEventDispatcher,
    ) -> &mut HashMap<IcmpConnId<Ipv6>, Vec<(u16, Vec<u8>)>> {
        &mut evt.icmpv6_replies
    }
}

impl DummyEventDispatcher {
    pub(crate) fn frames_sent(&self) -> &[(DeviceId, Vec<u8>)] {
        &self.frames_sent
    }

    /// Get an ordered list of all scheduled timer events
    pub(crate) fn timer_events(&self) -> impl Iterator<Item = (&'_ DummyInstant, &'_ TimerId)> {
        // TODO(joshlf): `iter` doesn't actually guarantee an ordering, so this
        // is a bug. We plan on removing this soon once we migrate to using the
        // utilities in the `context` module, so this is left as-is.
        self.timer_events.iter().map(|t| (&t.0, &t.1))
    }

    /// Takes all the received ICMP replies for a given `conn`.
    pub(crate) fn take_icmp_replies<I: TestutilIpExt>(
        &mut self,
        conn: IcmpConnId<I>,
    ) -> Vec<(u16, Vec<u8>)> {
        I::icmp_replies(self).remove(&conn).unwrap_or_else(Vec::default)
    }
}

impl<I: IcmpIpExt> UdpEventDispatcher<I> for DummyEventDispatcher {}

impl<I: IcmpIpExt> TransportLayerEventDispatcher<I> for DummyEventDispatcher {}

impl<I: IcmpIpExt> IcmpEventDispatcher<I> for DummyEventDispatcher {
    fn receive_icmp_error(&mut self, _conn: IcmpConnId<I>, _seq_num: u16, _err: I::ErrorCode) {
        unimplemented!()
    }

    fn close_icmp_connection(&mut self, _conn: IcmpConnId<I>, _err: NoRouteError) {
        unimplemented!()
    }
}

impl<B: BufferMut> BufferIcmpEventDispatcher<Ipv4, B> for DummyEventDispatcher {
    fn receive_icmp_echo_reply(&mut self, conn: IcmpConnId<Ipv4>, seq_num: u16, data: B) {
        let replies = self.icmpv4_replies.entry(conn).or_insert_with(Vec::default);
        replies.push((seq_num, data.as_ref().to_owned()))
    }
}

impl<B: BufferMut> BufferIcmpEventDispatcher<Ipv6, B> for DummyEventDispatcher {
    fn receive_icmp_echo_reply(&mut self, conn: IcmpConnId<Ipv6>, seq_num: u16, data: B) {
        let replies = self.icmpv6_replies.entry(conn).or_insert_with(Vec::default);
        replies.push((seq_num, data.as_ref().to_owned()))
    }
}

impl<B: BufferMut> IpLayerEventDispatcher<B> for DummyEventDispatcher {}

impl<B: BufferMut> DeviceLayerEventDispatcher<B> for DummyEventDispatcher {
    fn send_frame<S: Serializer<Buffer = B>>(
        &mut self,
        device: DeviceId,
        frame: S,
    ) -> Result<(), S> {
        let frame = frame.serialize_vec_outer().map_err(|(_, ser)| ser)?;
        self.frames_sent.push((device, frame.as_ref().to_vec()));
        Ok(())
    }
}

impl EventDispatcher for DummyEventDispatcher {
    type Instant = DummyInstant;

    fn now(&self) -> DummyInstant {
        self.current_time
    }

    fn schedule_timeout(&mut self, duration: Duration, id: TimerId) -> Option<DummyInstant> {
        self.schedule_timeout_instant(self.current_time + duration, id)
    }

    fn schedule_timeout_instant(
        &mut self,
        time: DummyInstant,
        id: TimerId,
    ) -> Option<DummyInstant> {
        let ret = self.cancel_timeout(id);
        self.timer_events.push(PendingTimer::new(time, id));
        ret
    }

    fn cancel_timeout(&mut self, id: TimerId) -> Option<DummyInstant> {
        let mut r: Option<DummyInstant> = None;
        // NOTE(brunodalbo): cancelling timeouts can be made a faster than this
        //  if we kept two data structures and TimerId was Hashable.
        self.timer_events = self
            .timer_events
            .drain()
            .filter(|t| {
                if t.1 == id {
                    r = Some(t.0);
                    false
                } else {
                    true
                }
            })
            .collect::<Vec<_>>()
            .into();
        r
    }

    fn cancel_timeouts_with<F: FnMut(&TimerId) -> bool>(&mut self, mut f: F) {
        self.timer_events =
            self.timer_events.drain().filter(|t| !f(&t.1)).collect::<Vec<_>>().into();
    }

    fn scheduled_instant(&self, id: TimerId) -> Option<DummyInstant> {
        self.timer_events.iter().find_map(|x| if x.1 == id { Some(x.0) } else { None })
    }

    type Rng = FakeCryptoRng<XorShiftRng>;

    fn rng(&self) -> &FakeCryptoRng<XorShiftRng> {
        &self.rng
    }

    fn rng_mut(&mut self) -> &mut FakeCryptoRng<XorShiftRng> {
        &mut self.rng
    }
}

#[derive(Debug)]
struct PendingFrameData<N> {
    data: Vec<u8>,
    dst_context: N,
    dst_device: DeviceId,
}

type PendingFrame<N> = InstantAndData<PendingFrameData<N>>;

/// A dummy network, composed of many `Context`s backed by
/// `DummyEventDispatcher`s.
///
/// Provides a quick utility to have many contexts keyed by `N` that can
/// exchange frames between their interfaces, which are mapped by `mapper`.
/// `mapper` also provides the option to return a `Duration` parameter that is
/// interpreted as a delivery latency for a given packet.
pub(crate) struct DummyNetwork<
    N: Eq + Hash + Clone,
    F: Fn(&N, DeviceId) -> Vec<(N, DeviceId, Option<Duration>)>,
> {
    contexts: HashMap<N, Context<DummyEventDispatcher>>,
    mapper: F,
    current_time: DummyInstant,
    pending_frames: BinaryHeap<PendingFrame<N>>,
}

/// The result of a single step in a `DummyNetwork`
#[derive(Debug)]
pub(crate) struct StepResult {
    time_delta: Duration,
    timers_fired: usize,
    frames_sent: usize,
}

impl StepResult {
    fn new(time_delta: Duration, timers_fired: usize, frames_sent: usize) -> Self {
        Self { time_delta, timers_fired, frames_sent }
    }

    fn new_idle() -> Self {
        Self::new(Duration::from_millis(0), 0, 0)
    }

    /// Returns `true` if the last step did not perform any operations.
    pub(crate) fn is_idle(&self) -> bool {
        return self.timers_fired == 0 && self.frames_sent == 0;
    }

    /// Returns the number of frames dispatched to their destinations in the
    /// last step.
    pub(crate) fn frames_sent(&self) -> usize {
        self.frames_sent
    }

    /// Returns the number of timers fired in the last step.
    pub(crate) fn timers_fired(&self) -> usize {
        self.timers_fired
    }
}

/// Error type that marks that one of the `run_until` family of functions
/// reached a maximum number of iterations.
#[derive(Debug)]
pub(crate) struct LoopLimitReachedError;

impl<N, F> DummyNetwork<N, F>
where
    N: Eq + Hash + Clone + std::fmt::Debug,
    F: Fn(&N, DeviceId) -> Vec<(N, DeviceId, Option<Duration>)>,
{
    /// Creates a new `DummyNetwork`.
    ///
    /// Creates a new `DummyNetwork` with the collection of `Context`s in
    /// `contexts`. `Context`s are named by type parameter `N`. `mapper` is used
    /// to route frames from one pair of (named `Context`, `DeviceId`) to
    /// another.
    ///
    /// # Panics
    ///
    /// `mapper` must map to a valid name, otherwise calls to `step` will panic.
    ///
    /// Calls to `new` will panic if given a `Context` with timer events.
    /// `Context`s given to `DummyNetwork` **must not** have any timer events
    /// already attached to them, because `DummyNetwork` maintains all the
    /// internal timers in dispatchers in sync to enable synchronous simulation
    /// steps.
    pub(crate) fn new<I: Iterator<Item = (N, Context<DummyEventDispatcher>)>>(
        contexts: I,
        mapper: F,
    ) -> Self {
        let mut ret = Self {
            contexts: contexts.collect(),
            mapper,
            current_time: DummyInstant::default(),
            pending_frames: BinaryHeap::new(),
        };

        // We can't guarantee that all contexts are safely running their timers
        // together if we receive a context with any timers already set.
        assert!(
            !ret.contexts.iter().any(|(_n, ctx)| { !ctx.dispatcher.timer_events.is_empty() }),
            "can't start network with contexts that already have timers set"
        );

        // synchronize all dispatchers' current time to the same value:
        for (_, ctx) in ret.contexts.iter_mut() {
            ctx.dispatcher.current_time = ret.current_time;
        }

        ret
    }

    /// Retrieves a `Context` named `context`.
    pub(crate) fn context<K: Into<N>>(&mut self, context: K) -> &mut Context<DummyEventDispatcher> {
        self.contexts.get_mut(&context.into()).unwrap()
    }

    /// Performs a single step in network simulation.
    ///
    /// `step` performs a single logical step in the collection of `Context`s
    /// held by this `DummyNetwork`. A single step consists of the following
    /// operations:
    ///
    /// - All pending frames, kept in `frames_sent` of `DummyEventDispatcher`
    /// are mapped to their destination `Context`/`DeviceId` pairs and moved to
    /// an internal collection of pending frames.
    /// - The collection of pending timers and scheduled frames is inspected and
    /// a simulation time step is retrieved, which will cause a next event
    /// to trigger. The simulation time is updated to the new time.
    /// - All scheduled frames whose deadline is less than or equal to the new
    /// simulation time are sent to their destinations.
    /// - All timer events whose deadline is less than or equal to the new
    /// simulation time are fired.
    ///
    /// If any new events are created during the operation of frames or timers,
    /// they **will not** be taken into account in the current `step`. That is,
    /// `step` collects all the pending events before dispatching them, ensuring
    /// that an infinite loop can't be created as a side effect of calling
    /// `step`.
    ///
    /// The return value of `step` indicates which of the operations were
    /// performed.
    ///
    /// # Panics
    ///
    /// If `DummyNetwork` was set up with a bad `mapper`, calls to `step` may
    /// panic when trying to route frames to their `Context`/`DeviceId`
    /// destinations.
    pub(crate) fn step(&mut self) -> StepResult {
        self.collect_frames();

        let next_step = if let Some(t) = self.next_step() {
            t
        } else {
            return StepResult::new_idle();
        };

        // this assertion holds the contract that `next_step` does not return
        // a time in the past.
        assert!(next_step >= self.current_time);
        let mut ret = StepResult::new(next_step.duration_since(self.current_time), 0, 0);

        // move time forward:
        trace!("testutil::DummyNetwork::step: current time = {:?}", next_step);
        self.current_time = next_step;
        for (_, ctx) in self.contexts.iter_mut() {
            ctx.dispatcher.current_time = next_step;
        }

        // dispatch all pending frames:
        while let Some(InstantAndData(t, _)) = self.pending_frames.peek() {
            // TODO(brunodalbo): remove this break once let_chains is stable
            if *t > self.current_time {
                break;
            }

            // we can unwrap because we just peeked.
            let mut frame = self.pending_frames.pop().unwrap().1;
            crate::receive_frame(
                self.context(frame.dst_context),
                frame.dst_device,
                Buf::new(&mut frame.data, ..),
            );
            ret.frames_sent += 1;
        }

        // dispatch all pending timers.
        for (_n, ctx) in self.contexts.iter_mut() {
            // We have to collect the timers before dispatching them, to avoid
            // an infinite loop in case handle_timeout schedules another timer
            // for the same or older DummyInstant.
            let mut timers = Vec::<TimerId>::new();
            while let Some(InstantAndData(t, id)) = ctx.dispatcher.timer_events.peek() {
                // TODO(brunodalbo): remove this break once let_chains is stable
                if *t > self.current_time {
                    break;
                }
                timers.push(*id);
                ctx.dispatcher.timer_events.pop();
            }

            for t in timers {
                crate::handle_timeout(ctx, t);
                ret.timers_fired += 1;
            }
        }

        ret
    }

    /// Collects all queued frames.
    ///
    /// Collects all pending frames and schedules them for delivery to the
    /// destination `Context`/`DeviceId` based on the result of `mapper`. The
    /// collected frames are queued for dispatching in the `DummyNetwork`,
    /// ordered by their scheduled delivery time given by the latency result
    /// provided by `mapper`.
    fn collect_frames(&mut self) {
        let all_frames: Vec<(N, Vec<(DeviceId, Vec<u8>)>)> = self
            .contexts
            .iter_mut()
            .filter_map(|(n, ctx)| {
                if ctx.dispatcher.frames_sent.is_empty() {
                    None
                } else {
                    Some((n.clone(), ctx.dispatcher.frames_sent.drain(..).collect()))
                }
            })
            .collect();

        for (n, frames) in all_frames.into_iter() {
            for (device_id, frame) in frames.into_iter() {
                for (dst_context, dst_device, latency) in (self.mapper)(&n, device_id) {
                    self.pending_frames.push(PendingFrame::new(
                        self.current_time + latency.unwrap_or(Duration::from_millis(0)),
                        PendingFrameData::<N> { data: frame.clone(), dst_context, dst_device },
                    ));
                }
            }
        }
    }

    /// Calculates the next `DummyInstant` when events are available.
    ///
    /// Returns the smallest `DummyInstant` greater than or equal to
    /// `current_time` for which an event is available. If no events are
    /// available, returns `None`.
    fn next_step(&mut self) -> Option<DummyInstant> {
        self.collect_frames();

        // get earliest timer in all contexts:
        let next_timer = self
            .contexts
            .iter()
            .filter_map(|(_n, ctx)| match ctx.dispatcher.timer_events.peek() {
                Some(tmr) => Some(tmr.0),
                None => None,
            })
            .min();
        // get the instant for the next packet
        let next_packet_due = self.pending_frames.peek().map(|t| t.0);

        // Return the earliest of them both, and protect against returning a
        // time in the past.
        match next_timer {
            Some(t) if next_packet_due.is_some() => Some(t).min(next_packet_due),
            Some(t) => Some(t),
            None => next_packet_due,
        }
        .map(|t| t.max(self.current_time))
    }

    /// Runs the dummy network for `duration` time.
    ///
    /// Runs `step` until `duration` time has passed since the call of `run_for`.
    pub(crate) fn run_for(&mut self, duration: Duration) {
        let start_time = self.current_time;
        let end_time = start_time + duration;

        while let Some(next_step) = self.next_step() {
            if next_step <= end_time {
                assert!(!self.step().is_idle());
                assert!(self.current_time <= end_time);
            } else {
                break;
            }
        }

        // Move time to the end time.
        self.current_time = end_time;
        for (_, ctx) in self.contexts.iter_mut() {
            ctx.dispatcher.current_time = end_time;
        }
    }

    /// Runs the dummy network simulation until it is starved of events.
    ///
    /// Runs `step` until it returns a `StepResult` where `is_idle` is `true` or
    /// a total of 1,000,000 steps is performed. The imposed limit in steps is
    /// there to prevent the call from blocking; reaching that limit should be
    /// considered a logic error.
    ///
    /// # Panics
    ///
    /// See [`step`] for possible panic conditions.
    pub(crate) fn run_until_idle(&mut self) -> Result<(), LoopLimitReachedError> {
        for _ in 0..1_000_000 {
            if self.step().is_idle() {
                return Ok(());
            }
        }
        debug!("DummyNetwork seems to have gotten stuck in a loop.");
        Err(LoopLimitReachedError)
    }

    /// Runs the dummy network simulation until it is starved of events or
    /// `stop` returns `true`.
    ///
    /// Runs `step` until it returns a `StepResult` where `is_idle` is `true` or
    /// the provided function `stop` returns `true`, or a total of 1,000,000
    /// steps is performed. The imposed limit in steps is there to prevent the
    /// call from blocking; reaching that limit should be considered a logic
    /// error.
    ///
    /// # Panics
    ///
    /// See [`step`] for possible panic conditions.
    pub(crate) fn run_until_idle_or<S: Fn(&mut Self) -> bool>(
        &mut self,
        stop: S,
    ) -> Result<(), LoopLimitReachedError> {
        for _ in 0..1_000_000 {
            if self.step().is_idle() {
                return Ok(());
            } else if stop(self) {
                return Ok(());
            }
        }
        debug!("DummyNetwork seems to have gotten stuck in a loop.");
        Err(LoopLimitReachedError)
    }
}

/// Convenience function to create `DummyNetwork`s
///
/// `new_dummy_network_from_config` creates a `DummyNetwork` with two `Context`s
/// named `a` and `b`. `Context` `a` is created from the configuration provided
/// in `cfg`, and `Context` `b` is created from the symmetric configuration
/// generated by `DummyEventDispatcherConfig::swap`. A default `mapper` function
/// is provided that maps all frames from (`a`, ethernet device `1`) to
/// (`b`, ethernet device `1`) and vice-versa.
pub(crate) fn new_dummy_network_from_config_with_latency<A: IpAddress, N>(
    a: N,
    b: N,
    cfg: DummyEventDispatcherConfig<A>,
    latency: Option<Duration>,
) -> DummyNetwork<N, impl Fn(&N, DeviceId) -> Vec<(N, DeviceId, Option<Duration>)>>
where
    N: Eq + Hash + Clone + std::fmt::Debug,
{
    let bob = DummyEventDispatcherBuilder::from_config(cfg.swap()).build();
    let alice = DummyEventDispatcherBuilder::from_config(cfg).build();
    let contexts = vec![(a.clone(), alice), (b.clone(), bob)].into_iter();
    DummyNetwork::<N, _>::new(contexts, move |net, _device_id| {
        if *net == a {
            vec![(b.clone(), DeviceId::new_ethernet(0), latency)]
        } else {
            vec![(a.clone(), DeviceId::new_ethernet(0), latency)]
        }
    })
}

/// Convenience function to create `DummyNetwork`s with no latency
///
/// Creates a `DummyNetwork` by calling
/// [`new_dummy_network_from_config_with_latency`] with `latency` set to `None`.
pub(crate) fn new_dummy_network_from_config<A: IpAddress, N>(
    a: N,
    b: N,
    cfg: DummyEventDispatcherConfig<A>,
) -> DummyNetwork<N, impl Fn(&N, DeviceId) -> Vec<(N, DeviceId, Option<Duration>)>>
where
    N: Eq + Hash + Clone + std::fmt::Debug,
{
    new_dummy_network_from_config_with_latency(a, b, cfg, None)
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use net_types::ip::{Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
    use packet::{Buf, Serializer};
    use specialize_ip_macro::ip_test;

    use super::*;
    use crate::ip;
    use crate::wire::icmp::{
        IcmpDestUnreachable, IcmpEchoReply, IcmpEchoRequest, IcmpPacketBuilder, IcmpUnusedCode,
        Icmpv4DestUnreachableCode,
    };
    use crate::TimerIdInner;

    #[test]
    fn test_parse_ethernet_frame() {
        use crate::wire::testdata::arp_request::*;
        let (body, src_mac, dst_mac, ethertype) =
            parse_ethernet_frame(ETHERNET_FRAME.bytes).unwrap();
        assert_eq!(body, &ETHERNET_FRAME.bytes[14..]);
        assert_eq!(src_mac, ETHERNET_FRAME.metadata.src_mac);
        assert_eq!(dst_mac, ETHERNET_FRAME.metadata.dst_mac);
        assert_eq!(ethertype, ETHERNET_FRAME.metadata.ethertype);
    }

    #[test]
    fn test_parse_ip_packet() {
        use crate::wire::testdata::icmp_redirect::IP_PACKET_BYTES;
        let (body, src_ip, dst_ip, proto, ttl) = parse_ip_packet::<Ipv4>(IP_PACKET_BYTES).unwrap();
        assert_eq!(body, &IP_PACKET_BYTES[20..]);
        assert_eq!(src_ip, Ipv4Addr::new([10, 123, 0, 2]));
        assert_eq!(dst_ip, Ipv4Addr::new([10, 123, 0, 1]));
        assert_eq!(proto, IpProto::Icmp);
        assert_eq!(ttl, 255);

        use crate::wire::testdata::icmp_echo_v6::REQUEST_IP_PACKET_BYTES;
        let (body, src_ip, dst_ip, proto, ttl) =
            parse_ip_packet::<Ipv6>(REQUEST_IP_PACKET_BYTES).unwrap();
        assert_eq!(body, &REQUEST_IP_PACKET_BYTES[40..]);
        assert_eq!(src_ip, Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]));
        assert_eq!(dst_ip, Ipv6Addr::new([0xFE, 0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));
        assert_eq!(proto, IpProto::Icmpv6);
        assert_eq!(ttl, 64);
    }

    #[test]
    fn test_parse_ip_packet_in_ethernet_frame() {
        use crate::wire::testdata::tls_client_hello_v4::*;
        let (body, src_mac, dst_mac, src_ip, dst_ip, proto, ttl) =
            parse_ip_packet_in_ethernet_frame::<Ipv4>(ETHERNET_FRAME.bytes).unwrap();
        assert_eq!(body, &IPV4_PACKET.bytes[IPV4_PACKET.body_range]);
        assert_eq!(src_mac, ETHERNET_FRAME.metadata.src_mac);
        assert_eq!(dst_mac, ETHERNET_FRAME.metadata.dst_mac);
        assert_eq!(src_ip, IPV4_PACKET.metadata.src_ip);
        assert_eq!(dst_ip, IPV4_PACKET.metadata.dst_ip);
        assert_eq!(proto, IPV4_PACKET.metadata.proto);
        assert_eq!(ttl, IPV4_PACKET.metadata.ttl);
    }

    #[test]
    fn test_parse_icmp_packet() {
        set_logger_for_test();
        use crate::wire::testdata::icmp_dest_unreachable::*;
        let (body, ..) = parse_ip_packet::<Ipv4>(&IP_PACKET_BYTES).unwrap();
        let (_, code) = parse_icmp_packet::<Ipv4, _, IcmpDestUnreachable, _>(
            body,
            Ipv4Addr::new([172, 217, 6, 46]),
            Ipv4Addr::new([192, 168, 0, 105]),
            |_| {},
        )
        .unwrap();
        assert_eq!(code, Icmpv4DestUnreachableCode::DestHostUnreachable);
    }

    #[test]
    fn test_parse_icmp_packet_in_ip_packet_in_ethernet_frame() {
        set_logger_for_test();
        use crate::wire::testdata::icmp_echo_ethernet::*;
        let (src_mac, dst_mac, src_ip, dst_ip, _, _, _) =
            parse_icmp_packet_in_ip_packet_in_ethernet_frame::<Ipv4, _, IcmpEchoReply, _>(
                &REPLY_ETHERNET_FRAME_BYTES,
                |_| {},
            )
            .unwrap();
        assert_eq!(src_mac, Mac::new([0x50, 0xc7, 0xbf, 0x1d, 0xf4, 0xd2]));
        assert_eq!(dst_mac, Mac::new([0x8c, 0x85, 0x90, 0xc9, 0xc9, 0x00]));
        assert_eq!(src_ip, Ipv4Addr::new([172, 217, 6, 46]));
        assert_eq!(dst_ip, Ipv4Addr::new([192, 168, 0, 105]));
    }

    #[test]
    fn test_dummy_network_transmits_packets() {
        set_logger_for_test();
        let mut net = new_dummy_network_from_config("alice", "bob", DUMMY_CONFIG_V4);

        // alice sends bob a ping:
        ip::send_ipv4_packet(
            net.context("alice"),
            DUMMY_CONFIG_V4.remote_ip,
            ip::IpProto::Icmp,
            |_| {
                let req = IcmpEchoRequest::new(0, 0);
                let req_body = &[1, 2, 3, 4];
                Buf::new(req_body.to_vec(), ..).encapsulate(
                    IcmpPacketBuilder::<Ipv4, &[u8], _>::new(
                        DUMMY_CONFIG_V4.local_ip,
                        DUMMY_CONFIG_V4.remote_ip,
                        IcmpUnusedCode,
                        req,
                    ),
                )
            },
        )
        .unwrap();

        // send from alice to bob
        assert_eq!(net.step().frames_sent(), 1);
        // respond from bob to alice
        assert_eq!(net.step().frames_sent(), 1);
        // should've starved all events:
        assert!(net.step().is_idle());
    }

    #[test]
    fn test_dummy_network_timers() {
        set_logger_for_test();
        let mut net = new_dummy_network_from_config(1, 2, DUMMY_CONFIG_V4);

        net.context(1)
            .dispatcher
            .schedule_timeout(Duration::from_secs(1), TimerId(TimerIdInner::Nop(1)));
        net.context(2)
            .dispatcher
            .schedule_timeout(Duration::from_secs(2), TimerId(TimerIdInner::Nop(2)));
        net.context(2)
            .dispatcher
            .schedule_timeout(Duration::from_secs(3), TimerId(TimerIdInner::Nop(3)));
        net.context(1)
            .dispatcher
            .schedule_timeout(Duration::from_secs(4), TimerId(TimerIdInner::Nop(4)));

        net.context(1)
            .dispatcher
            .schedule_timeout(Duration::from_secs(5), TimerId(TimerIdInner::Nop(5)));
        net.context(2)
            .dispatcher
            .schedule_timeout(Duration::from_secs(5), TimerId(TimerIdInner::Nop(6)));

        // no timers fired before:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 0);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 0);
        assert_eq!(net.step().timers_fired(), 1);
        // only timer in context 1 should have fired:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 1);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 0);
        assert_eq!(net.step().timers_fired(), 1);
        // only timer in context 2 should have fired:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 1);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 1);
        assert_eq!(net.step().timers_fired(), 1);
        // only timer in context 2 should have fired:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 1);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 2);
        assert_eq!(net.step().timers_fired(), 1);
        // only timer in context 1 should have fired:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 2);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 2);
        assert_eq!(net.step().timers_fired(), 2);
        // both timers have fired at the same time:
        assert_eq!(*net.context(1).state.test_counters.get("timer::nop"), 3);
        assert_eq!(*net.context(2).state.test_counters.get("timer::nop"), 3);

        assert!(net.step().is_idle());
        // check that current time on contexts tick together:
        let t1 = net.context(1).dispatcher.current_time;
        let t2 = net.context(2).dispatcher.current_time;
        assert_eq!(t1, t2);
    }

    #[test]
    fn test_dummy_network_until_idle() {
        set_logger_for_test();
        let mut net = new_dummy_network_from_config(1, 2, DUMMY_CONFIG_V4);
        net.context(1)
            .dispatcher
            .schedule_timeout(Duration::from_secs(1), TimerId(TimerIdInner::Nop(1)));
        net.context(2)
            .dispatcher
            .schedule_timeout(Duration::from_secs(2), TimerId(TimerIdInner::Nop(2)));
        net.context(2)
            .dispatcher
            .schedule_timeout(Duration::from_secs(3), TimerId(TimerIdInner::Nop(3)));

        net.run_until_idle_or(|net| {
            *net.context(1).state.test_counters.get("timer::nop") == 1
                && *net.context(2).state.test_counters.get("timer::nop") == 1
        })
        .unwrap();
        // assert that we stopped before all times were fired, meaning we can
        // step again:
        assert_eq!(net.step().timers_fired(), 1);
    }

    #[test]
    fn test_instant_and_data() {
        // verify implementation of InstantAndData to be used as a complex type
        // in a BinaryHeap:
        let mut heap = BinaryHeap::<InstantAndData<usize>>::new();
        let now = DummyInstant::default();

        fn new_data(time: DummyInstant, id: usize) -> InstantAndData<usize> {
            InstantAndData::new(time, id)
        }

        heap.push(new_data(now + Duration::from_secs(1), 1));
        heap.push(new_data(now + Duration::from_secs(2), 2));

        // earlier timer is popped first
        assert!(heap.pop().unwrap().1 == 1);
        assert!(heap.pop().unwrap().1 == 2);
        assert!(heap.pop().is_none());

        heap.push(new_data(now + Duration::from_secs(1), 1));
        heap.push(new_data(now + Duration::from_secs(1), 1));

        // can pop twice with identical data:
        assert!(heap.pop().unwrap().1 == 1);
        assert!(heap.pop().unwrap().1 == 1);
        assert!(heap.pop().is_none());
    }

    #[test]
    fn test_delayed_packets() {
        set_logger_for_test();
        // create a network that takes 5ms to get any packet to go through:
        let mut net = new_dummy_network_from_config_with_latency(
            "alice",
            "bob",
            DUMMY_CONFIG_V4,
            Some(Duration::from_millis(5)),
        );

        // alice sends bob a ping:
        ip::send_ipv4_packet(
            net.context("alice"),
            DUMMY_CONFIG_V4.remote_ip,
            ip::IpProto::Icmp,
            |_| {
                let req = IcmpEchoRequest::new(0, 0);
                let req_body = &[1, 2, 3, 4];
                Buf::new(req_body.to_vec(), ..).encapsulate(
                    IcmpPacketBuilder::<Ipv4, &[u8], _>::new(
                        DUMMY_CONFIG_V4.local_ip,
                        DUMMY_CONFIG_V4.remote_ip,
                        IcmpUnusedCode,
                        req,
                    ),
                )
            },
        )
        .unwrap();

        net.context("alice")
            .dispatcher
            .schedule_timeout(Duration::from_millis(3), TimerId(TimerIdInner::Nop(1)));
        net.context("bob")
            .dispatcher
            .schedule_timeout(Duration::from_millis(7), TimerId(TimerIdInner::Nop(2)));
        net.context("bob")
            .dispatcher
            .schedule_timeout(Duration::from_millis(10), TimerId(TimerIdInner::Nop(1)));

        // order of expected events is as follows:
        // - Alice's timer expires at t = 3
        // - Bob receives Alice's packet at t = 5
        // - Bob's timer expires at t = 7
        // - Alice receives Bob's response and Bob's last timer fires at t = 10

        fn assert_full_state<F>(
            net: &mut DummyNetwork<&'static str, F>,
            alice_nop: usize,
            bob_nop: usize,
            bob_echo_request: usize,
            alice_echo_response: usize,
        ) where
            F: Fn(&&'static str, DeviceId) -> Vec<(&'static str, DeviceId, Option<Duration>)>,
        {
            let alice = net.context("alice");
            assert_eq!(*alice.state.test_counters.get("timer::nop"), alice_nop);
            assert_eq!(
                *alice.state.test_counters.get("<IcmpIpTransportContext as BufferIpTransportContext<Ipv4>>::receive_ip_packet::echo_reply"),
                alice_echo_response
            );

            let bob = net.context("bob");
            assert_eq!(*bob.state.test_counters.get("timer::nop"), bob_nop);
            assert_eq!(
                *bob.state.test_counters.get("<IcmpIpTransportContext as BufferIpTransportContext<Ipv4>>::receive_ip_packet::echo_request"),
                bob_echo_request
            );
        }

        assert_eq!(net.step().timers_fired(), 1);
        assert_full_state(&mut net, 1, 0, 0, 0);
        assert_eq!(net.step().frames_sent(), 1);
        assert_full_state(&mut net, 1, 0, 1, 0);
        assert_eq!(net.step().timers_fired(), 1);
        assert_full_state(&mut net, 1, 1, 1, 0);
        let step = net.step();
        assert_eq!(step.frames_sent(), 1);
        assert_eq!(step.timers_fired(), 1);
        assert_full_state(&mut net, 1, 2, 1, 1);

        // should've starved all events:
        assert!(net.step().is_idle());
    }

    #[ip_test]
    fn test_send_to_many<I: Ip + TestIpExt>() {
        fn send_packet<A: IpAddress>(
            ctx: &mut Context<DummyEventDispatcher>,
            src_ip: SpecifiedAddr<A>,
            dst_ip: SpecifiedAddr<A>,
            device: DeviceId,
        ) {
            crate::ip::send_ip_packet_from_device(
                ctx,
                device,
                src_ip.get(),
                dst_ip.get(),
                dst_ip,
                crate::ip::IpProto::Udp,
                Buf::new(vec![1, 2, 3, 4], ..),
                None,
            )
            .unwrap();
        }

        let device = DeviceId::new_ethernet(0);
        let a = "alice";
        let b = "bob";
        let c = "calvin";
        let mac_a = Mac::new([1, 2, 3, 4, 5, 6]);
        let mac_b = Mac::new([1, 2, 3, 4, 5, 7]);
        let mac_c = Mac::new([1, 2, 3, 4, 5, 8]);
        let ip_a = I::get_other_ip_address(1);
        let ip_b = I::get_other_ip_address(2);
        let ip_c = I::get_other_ip_address(3);
        let subnet = Subnet::new(I::get_other_ip_address(0).get(), I::Addr::BYTES * 8 - 8).unwrap();
        let mut alice = DummyEventDispatcherBuilder::default();
        alice.add_device_with_ip(mac_a, ip_a.get(), subnet);
        let mut bob = DummyEventDispatcherBuilder::default();
        bob.add_device_with_ip(mac_b, ip_b.get(), subnet);
        let mut calvin = DummyEventDispatcherBuilder::default();
        calvin.add_device_with_ip(mac_c, ip_c.get(), subnet);
        add_arp_or_ndp_table_entry(&mut alice, device.id(), ip_b.get(), mac_b);
        add_arp_or_ndp_table_entry(&mut alice, device.id(), ip_c.get(), mac_c);
        add_arp_or_ndp_table_entry(&mut bob, device.id(), ip_a.get(), mac_a);
        add_arp_or_ndp_table_entry(&mut bob, device.id(), ip_c.get(), mac_c);
        add_arp_or_ndp_table_entry(&mut calvin, device.id(), ip_a.get(), mac_a);
        add_arp_or_ndp_table_entry(&mut calvin, device.id(), ip_b.get(), mac_b);
        let contexts =
            vec![(a.clone(), alice.build()), (b.clone(), bob.build()), (c.clone(), calvin.build())]
                .into_iter();
        let mut net = DummyNetwork::new(contexts, move |net, _| {
            let ret = match *net {
                "alice" => vec![(b.clone(), device, None), (c.clone(), device, None)],
                "bob" => vec![(a.clone(), device, None)],
                "calvin" => Vec::new(),
                _ => unreachable!(),
            };

            println!("{:?}", ret);
            ret
        });

        net.collect_frames();
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 0);

        //
        // bob and calvin should get any packet sent by alice.
        //

        send_packet(net.context("alice"), ip_a, ip_b, device);
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 1);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 0);
        net.collect_frames();
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 2);
        assert!(net
            .pending_frames
            .iter()
            .any(|InstantAndData(_, x)| (x.dst_context == b) && (x.dst_device == device)));
        assert!(net
            .pending_frames
            .iter()
            .any(|InstantAndData(_, x)| (x.dst_context == c) && (x.dst_device == device)));

        //
        // Only alice should get packets sent by bob.
        //

        net.pending_frames = BinaryHeap::new();
        send_packet(net.context("bob"), ip_b, ip_a, device);
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 1);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 0);
        net.collect_frames();
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 1);
        assert!(net
            .pending_frames
            .iter()
            .any(|InstantAndData(_, x)| (x.dst_context == a) && (x.dst_device == device)));

        //
        // No one gets packets sent by calvin.
        //

        net.pending_frames = BinaryHeap::new();
        send_packet(net.context("calvin"), ip_c, ip_a, device);
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 1);
        assert_eq!(net.pending_frames.len(), 0);
        net.collect_frames();
        assert_eq!(net.context("alice").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("bob").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.context("calvin").dispatcher().frames_sent().len(), 0);
        assert_eq!(net.pending_frames.len(), 0);
    }
}
