diff options
Diffstat (limited to 'src/tests')
27 files changed, 2324 insertions, 0 deletions
diff --git a/src/tests/fakes/fake_input.rs b/src/tests/fakes/fake_input.rs new file mode 100644 index 0000000..6007b71 --- /dev/null +++ b/src/tests/fakes/fake_input.rs @@ -0,0 +1,153 @@ +use ::ipnetwork::IpNetwork; +use ::pnet::datalink::DataLinkReceiver; +use ::pnet::datalink::NetworkInterface; +use ::std::collections::HashMap; +use ::std::net::{IpAddr, Ipv4Addr, SocketAddr}; +use ::std::{thread, time}; +use ::termion::event::Event; + +use crate::network::{Connection, Protocol}; + +pub struct KeyboardEvents { + pub events: Vec<Option<Event>>, +} + +impl KeyboardEvents { + pub fn new(mut events: Vec<Option<Event>>) -> Self { + events.reverse(); // this is so that we do not have to shift the array + KeyboardEvents { events } + } +} +impl Iterator for KeyboardEvents { + type Item = Event; + fn next(&mut self) -> Option<Event> { + match self.events.pop() { + Some(ev) => { + match ev { + Some(ev) => Some(ev), // TODO: better + None => { + thread::sleep(time::Duration::from_secs(1)); + self.next() + } + } + } + None => None, + } + } +} + +pub struct NetworkFrames { + pub packets: Vec<Option<Vec<u8>>>, + pub current_index: usize, +} + +impl NetworkFrames { + pub fn new(packets: Vec<Option<Vec<u8>>>) -> Box<Self> { + Box::new(NetworkFrames { + packets, + current_index: 0, + }) + } + fn next_packet(&mut self) -> &Option<Vec<u8>> { + let next_index = self.current_index; + self.current_index += 1; + &self.packets[next_index] + } +} +impl DataLinkReceiver for NetworkFrames { + fn next(&mut self) -> Result<&[u8], std::io::Error> { + if self.current_index == 0 { + // make it less likely to have a race condition with the display loop + // this is so the tests pass consistently + thread::sleep(time::Duration::from_millis(500)); + } + match self.current_index < self.packets.len() { + true => { + let action = self.next_packet(); + match action { + Some(packet) => { + Ok(&packet[..]) // TODO: better + } + None => { + thread::sleep(time::Duration::from_secs(1)); + Ok(&[][..]) + } + } + } + false => { + thread::sleep(time::Duration::from_secs(1)); + Ok(&[][..]) + } + } + } +} + +pub fn get_open_sockets() -> HashMap<Connection, String> { + let mut open_sockets = HashMap::new(); + open_sockets.insert( + Connection::new( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)), 443), + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 12345), + Protocol::Tcp, + ) + .unwrap(), + String::from("1"), + ); + open_sockets.insert( + Connection::new( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)), 443), + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(2, 2, 2, 2)), 54321), + Protocol::Tcp, + ) + .unwrap(), + String::from("4"), + ); + open_sockets.insert( + Connection::new( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)), 443), + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(3, 3, 3, 3)), 1337), + Protocol::Tcp, + ) + .unwrap(), + String::from("5"), + ); + open_sockets.insert( + Connection::new( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)), 443), + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(4, 4, 4, 4)), 1337), + Protocol::Tcp, + ) + .unwrap(), + String::from("2"), + ); + open_sockets.insert( + Connection::new( + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)), 443), + SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 12346), + Protocol::Tcp, + ) + .unwrap(), + String::from("3"), + ); + open_sockets +} + +pub fn get_interface() -> NetworkInterface { + let interface = NetworkInterface { + name: String::from("foo"), + index: 42, + mac: None, + ips: vec![IpNetwork::V4("10.0.0.2".parse().unwrap())], + flags: 42, + }; + interface +} + +pub fn create_fake_lookup_addr( + ips_to_hosts: HashMap<IpAddr, String>, +) -> Box<Fn(&IpAddr) -> Option<String> + Send + Sync + 'static> { + Box::new(move |ip| match ips_to_hosts.get(ip) { + Some(host) => Some(host.clone()), + None => None, + }) +} diff --git a/src/tests/fakes/fake_output.rs b/src/tests/fakes/fake_output.rs new file mode 100644 index 0000000..6fb356c --- /dev/null +++ b/src/tests/fakes/fake_output.rs @@ -0,0 +1,108 @@ +use ::std::collections::HashMap; +use ::std::io; +use ::std::sync::{Arc, Mutex}; +use ::tui::backend::Backend; +use ::tui::buffer::Cell; +use ::tui::layout::Rect; + +#[derive(Hash, Debug, PartialEq)] +pub enum TerminalEvent { + Clear, + HideCursor, + ShowCursor, + GetCursor, + Flush, + Draw, +} + +pub struct TestBackend { + pub events: Arc<Mutex<Vec<TerminalEvent>>>, + pub draw_events: Arc<Mutex<Vec<String>>>, + terminal_width: u16, + terminal_height: u16, +} + +impl TestBackend { + pub fn new( + log: Arc<Mutex<Vec<TerminalEvent>>>, + draw_log: Arc<Mutex<Vec<String>>>, + ) -> TestBackend { + TestBackend { + events: log, + draw_events: draw_log, + terminal_width: 190, + terminal_height: 50, + } + } +} + +#[derive(Hash, Eq, PartialEq)] +struct Point { + x: u16, + y: u16, +} + +impl Backend for TestBackend { + fn clear(&mut self) -> io::Result<()> { + self.events.lock().unwrap().push(TerminalEvent::Clear); + Ok(()) + } + + fn hide_cursor(&mut self) -> io::Result<()> { + self.events.lock().unwrap().push(TerminalEvent::HideCursor); + Ok(()) + } + + fn show_cursor(&mut self) -> io::Result<()> { + self.events.lock().unwrap().push(TerminalEvent::ShowCursor); + Ok(()) + } + + fn get_cursor(&mut self) -> io::Result<(u16, u16)> { + self.events.lock().unwrap().push(TerminalEvent::GetCursor); + Ok((0, 0)) + } + + fn set_cursor(&mut self, _x: u16, _y: u16) -> io::Result<()> { + Ok(()) + } + + fn draw<'a, I>(&mut self, content: I) -> io::Result<()> + where + I: Iterator<Item = (u16, u16, &'a Cell)>, + { + // use std::fmt::Write; + self.events.lock().unwrap().push(TerminalEvent::Draw); + let mut string = String::with_capacity(content.size_hint().0 * 3); + let mut coordinates = HashMap::new(); + for (x, y, cell) in content { + coordinates.insert(Point { x, y }, cell); + } + for y in 0..self.terminal_height { + for x in 0..self.terminal_width { + match coordinates.get(&Point { x, y }) { + Some(cell) => { + // this will contain no style information at all + // should be good enough for testing + string.push_str(&cell.symbol); + } + None => { + string.push_str(" "); + } + } + } + string.push_str("\n"); + } + self.draw_events.lock().unwrap().push(string); + Ok(()) + } + + fn size(&self) -> io::Result<Rect> { + Ok(Rect::new(0, 0, self.terminal_width, self.terminal_height)) + } + + fn flush(&mut self) -> io::Result<()> { + self.events.lock().unwrap().push(TerminalEvent::Flush); + Ok(()) + } +} diff --git a/src/tests/fakes/mod.rs b/src/tests/fakes/mod.rs new file mode 100644 index 0000000..dcd441b --- /dev/null +++ b/src/tests/fakes/mod.rs @@ -0,0 +1,5 @@ +mod fake_input; +mod fake_output; + +pub use fake_input::*; +pub use fake_output::*; diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..b3a5d9d --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,793 @@ +mod fakes; + +use fakes::TerminalEvent::*; +use fakes::{ + create_fake_lookup_addr, get_interface, get_open_sockets, KeyboardEvents, NetworkFrames, + TestBackend, +}; + +use ::insta::assert_snapshot; +use ::std::sync::{Arc, Mutex}; +use ::termion::event::{Event, Key}; + +use ::std::collections::HashMap; +use ::std::net::IpAddr; + +use packet_builder::payload::PayloadData; +use packet_builder::*; +use pnet::packet::Packet; +use pnet_base::MacAddr; + +fn build_tcp_packet( + source_ip: &str, + destination_ip: &str, + source_port: u16, + destination_port: u16, + payload: &'static [u8], +) -> Vec<u8> { + let mut pkt_buf = [0u8; 1500]; + let pkt = packet_builder!( + pkt_buf, + ether({set_destination => MacAddr(0,0,0,0,0,0), set_source => MacAddr(0,0,0,0,0,0)}) / + ipv4({set_source => ipv4addr!(source_ip), set_destination => ipv4addr!(destination_ip) }) / + tcp({set_source => source_port, set_destination => destination_port }) / + payload(payload) + ); + pkt.packet().to_vec() +} + +struct LogWithMirror<T> { + pub write: Arc<Mutex<T>>, + pub mirror: Arc<Mutex<T>>, +} + +impl<T> LogWithMirror<T> { + pub fn new(log: T) -> Self { + let write = Arc::new(Mutex::new(log)); + let mirror = write.clone(); + LogWithMirror { write, mirror } + } +} + +#[test] +fn basic_startup() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + None, // sleep + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![Clear, HideCursor, Draw, Flush, Clear, ShowCursor]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 1); + assert_snapshot!(&terminal_draw_events_mirror[0]); +} + +#[test] +fn one_packet_of_traffic() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![Some(build_tcp_packet( + "10.0.0.2", + "1.1.1.1", + 443, + 12345, + b"I am a fake tcp packet", + ))]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn bi_directional_traffic() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "10.0.0.2", + "1.1.1.1", + 443, + 12345, + b"I am a fake tcp upload packet", + )), + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I am a fake tcp download packet", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn multiple_packets_of_traffic_from_different_connections() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "2.2.2.2", + "10.0.0.2", + 54321, + 443, + b"I come from 2.2.2.2", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn multiple_packets_of_traffic_from_single_connection() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I've come from 1.1.1.1 too!", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn one_process_with_multiple_connections() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "3.3.3.3", + "10.0.0.2", + 1337, + 443, + b"Funny that, I'm from 3.3.3.3", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn multiple_processes_with_multiple_connections() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "3.3.3.3", + "10.0.0.2", + 1337, + 443, + b"Awesome, I'm from 3.3.3.3", + )), + Some(build_tcp_packet( + "2.2.2.2", + "10.0.0.2", + 54321, + 443, + b"You know, 2.2.2.2 is really nice!", + )), + Some(build_tcp_packet( + "4.4.4.4", + "10.0.0.2", + 1337, + 443, + b"I'm partial to 4.4.4.4", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn multiple_connections_from_remote_ip() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12346, + 443, + b"Me too, but on a different port", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 2); + assert_snapshot!(&terminal_draw_events_mirror[0]); + assert_snapshot!(&terminal_draw_events_mirror[1]); +} + +#[test] +fn sustained_traffic_from_one_process() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + None, // sleep + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"Same here, but one second later", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]); + + assert_eq!(terminal_draw_events_mirror.len(), 3); + assert_snapshot!(&terminal_draw_events_mirror[1]); + assert_snapshot!(&terminal_draw_events_mirror[2]); +} + +#[test] +fn sustained_traffic_from_multiple_processes() { + let keyboard_events = Box::new(KeyboardEvents::new(vec![ + None, // sleep + None, // sleep + None, // sleep + Some(Event::Key(Key::Ctrl('c'))), + ])); + let network_frames = NetworkFrames::new(vec![ + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1", + )), + Some(build_tcp_packet( + "3.3.3.3", + "10.0.0.2", + 1337, + 443, + b"I come from 3.3.3.3", + )), + None, // sleep + Some(build_tcp_packet( + "1.1.1.1", + "10.0.0.2", + 12345, + 443, + b"I have come from 1.1.1.1 one second later", + )), + Some(build_tcp_packet( + "3.3.3.3", + "10.0.0.2", + 1337, + 443, + b"I come 3.3.3.3 one second later", + )), + ]); + + let terminal_events = LogWithMirror::new(Vec::new()); + let terminal_draw_events = LogWithMirror::new(Vec::new()); + + let backend = TestBackend::new(terminal_events.write, terminal_draw_events.write); + let network_interface = get_interface(); + let lookup_addr = create_fake_lookup_addr(HashMap::new()); + + let os_input = crate::OsInput { + network_interface, + network_frames, + get_open_sockets, + keyboard_events, + lookup_addr, + }; + crate::start(backend, os_input); + + let terminal_events_mirror = terminal_events.mirror.lock().unwrap(); + let terminal_draw_events_mirror = terminal_draw_events.mirror.lock().unwrap(); + + let expected_terminal_events = vec![ + Clear, HideCursor, Draw, Flush, Draw, Flush, Draw, Flush, Clear, ShowCursor, + ]; + assert_eq!(&terminal_events_mirror[..], &expected_terminal_events[..]) |