summaryrefslogtreecommitdiffstats
path: root/src/tests/fakes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/fakes.rs')
-rw-r--r--src/tests/fakes.rs329
1 files changed, 0 insertions, 329 deletions
diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs
deleted file mode 100644
index 8d11458b9..000000000
--- a/src/tests/fakes.rs
+++ /dev/null
@@ -1,329 +0,0 @@
-use std::collections::{HashMap, VecDeque};
-use std::io::Write;
-use std::os::unix::io::RawFd;
-use std::path::PathBuf;
-use std::sync::{Arc, Condvar, Mutex};
-use std::time::{Duration, Instant};
-
-use zellij_utils::{nix, zellij_tile};
-
-use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
-use crate::tests::utils::commands::{QUIT, SLEEP};
-use zellij_client::os_input_output::ClientOsApi;
-use zellij_server::os_input_output::{async_trait, AsyncReader, Pid, ServerOsApi};
-use zellij_tile::data::Palette;
-use zellij_utils::{
- async_std,
- channels::{self, ChannelWithContext, SenderWithContext},
- errors::ErrorContext,
- interprocess::local_socket::LocalSocketStream,
- ipc::{ClientToServerMsg, ServerToClientMsg},
- pane_size::PositionAndSize,
- shared::default_palette,
-};
-
-const MIN_TIME_BETWEEN_SNAPSHOTS: Duration = Duration::from_millis(150);
-
-#[derive(Clone)]
-pub enum IoEvent {
- Kill(Pid),
- SetTerminalSizeUsingFd(RawFd, u16, u16),
- IntoRawMode(RawFd),
- UnsetRawMode(RawFd),
- TcDrain(RawFd),
-}
-
-#[derive(Clone)]
-pub struct FakeStdoutWriter {
- output_buffer: Arc<Mutex<Vec<u8>>>,
- pub output_frames: Arc<Mutex<Vec<Vec<u8>>>>,
- last_snapshot_time: Arc<Mutex<Instant>>,
-}
-
-impl FakeStdoutWriter {
- pub fn new(last_snapshot_time: Arc<Mutex<Instant>>) -> Self {
- FakeStdoutWriter {
- output_buffer: Arc::new(Mutex::new(Vec::new())),
- output_frames: Arc::new(Mutex::new(Vec::new())),
- last_snapshot_time,
- }
- }
-}
-
-impl Write for FakeStdoutWriter {
- fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
- let mut output_buffer = self.output_buffer.lock().unwrap();
- output_buffer.extend_from_slice(buf);
- Ok(buf.len())
- }
- fn flush(&mut self) -> Result<(), std::io::Error> {
- let mut output_buffer = self.output_buffer.lock().unwrap();
- let mut output_frames = self.output_frames.lock().unwrap();
- let new_frame = output_buffer.drain(..).collect();
- output_frames.push(new_frame);
- let mut last_snapshot_time = self.last_snapshot_time.lock().unwrap();
- *last_snapshot_time = Instant::now();
- Ok(())
- }
-}
-
-#[derive(Clone)]
-pub struct FakeInputOutput {
- read_buffers: Arc<Mutex<HashMap<RawFd, Bytes>>>,
- input_to_add: Arc<Mutex<Option<Vec<[u8; 10]>>>>,
- stdin_commands: Arc<Mutex<VecDeque<Vec<u8>>>>,
- stdin_writes: Arc<Mutex<HashMap<RawFd, Vec<u8>>>>,
- pub stdout_writer: FakeStdoutWriter, // stdout_writer.output is already an arc/mutex
- io_events: Arc<Mutex<Vec<IoEvent>>>,
- win_sizes: Arc<Mutex<HashMap<RawFd, PositionAndSize>>>,
- possible_tty_inputs: HashMap<u16, Bytes>,
- last_snapshot_time: Arc<Mutex<Instant>>,
- send_instructions_to_client: SenderWithContext<ServerToClientMsg>,
- receive_instructions_from_server:
- Arc<Mutex<channels::Receiver<(ServerToClientMsg, ErrorContext)>>>,
- send_instructions_to_server: SenderWithContext<ClientToServerMsg>,
- receive_instructions_from_client:
- Arc<Mutex<channels::Receiver<(ClientToServerMsg, ErrorContext)>>>,
- should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
- sigwinch_event: Option<PositionAndSize>,
-}
-
-impl FakeInputOutput {
- pub fn new(winsize: PositionAndSize) -> Self {
- let mut win_sizes = HashMap::new();
- let last_snapshot_time = Arc::new(Mutex::new(Instant::now()));
- let stdout_writer = FakeStdoutWriter::new(last_snapshot_time.clone());
- let (client_sender, client_receiver): ChannelWithContext<ServerToClientMsg> =
- channels::unbounded();
- let send_instructions_to_client = SenderWithContext::new(client_sender);
- let (server_sender, server_receiver): ChannelWithContext<ClientToServerMsg> =
- channels::unbounded();
- let send_instructions_to_server = SenderWithContext::new(server_sender);
- win_sizes.insert(0, winsize); // 0 is the current terminal
- FakeInputOutput {
- read_buffers: Arc::new(Mutex::new(HashMap::new())),
- stdin_writes: Arc::new(Mutex::new(HashMap::new())),
- input_to_add: Arc::new(Mutex::new(None)),
- stdin_commands: Arc::new(Mutex::new(VecDeque::new())),
- stdout_writer,
- last_snapshot_time,
- io_events: Arc::new(Mutex::new(vec![])),
- win_sizes: Arc::new(Mutex::new(win_sizes)),
- possible_tty_inputs: get_possible_tty_inputs(),
- receive_instructions_from_client: Arc::new(Mutex::new(server_receiver)),
- send_instructions_to_server,
- receive_instructions_from_server: Arc::new(Mutex::new(client_receiver)),
- send_instructions_to_client,
- should_trigger_sigwinch: Arc::new((Mutex::new(false), Condvar::new())),
- sigwinch_event: None,
- }
- }
- pub fn with_tty_inputs(mut self, tty_inputs: HashMap<u16, Bytes>) -> Self {
- self.possible_tty_inputs = tty_inputs;
- self
- }
- pub fn add_terminal_input(&mut self, input: &[&[u8]]) {
- let stdin_commands = input.iter().map(|i| i.to_vec()).collect();
- self.stdin_commands = Arc::new(Mutex::new(stdin_commands));
- }
- pub fn add_terminal(&self, fd: RawFd) {
- self.stdin_writes.lock().unwrap().insert(fd, vec![]);
- }
- pub fn add_sigwinch_event(&mut self, new_position_and_size: PositionAndSize) {
- self.sigwinch_event = Some(new_position_and_size);
- }
-}
-
-impl ClientOsApi for FakeInputOutput {
- fn get_terminal_size_using_fd(&self, pid: RawFd) -> PositionAndSize {
- if let Some(new_position_and_size) = self.sigwinch_event {
- let (lock, _cvar) = &*self.should_trigger_sigwinch;
- let should_trigger_sigwinch = lock.lock().unwrap();
- if *should_trigger_sigwinch && pid == 0 {
- return new_position_and_size;
- }
- }
- let win_sizes = self.win_sizes.lock().unwrap();
- let winsize = win_sizes.get(&pid).unwrap();
- *winsize
- }
- fn set_raw_mode(&mut self, pid: RawFd) {
- self.io_events
- .lock()
- .unwrap()
- .push(IoEvent::IntoRawMode(pid));
- }
- fn unset_raw_mode(&self, pid: RawFd) {
- self.io_events
- .lock()
- .unwrap()
- .push(IoEvent::UnsetRawMode(pid));
- }
- fn box_clone(&self) -> Box<dyn ClientOsApi> {
- Box::new((*self).clone())
- }
- fn read_from_stdin(&self) -> Vec<u8> {
- loop {
- let last_snapshot_time = { *self.last_snapshot_time.lock().unwrap() };
- if last_snapshot_time.elapsed() > MIN_TIME_BETWEEN_SNAPSHOTS {
- break;
- } else {
- ::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS - last_snapshot_time.elapsed());
- }
- }
- let command = self
- .stdin_commands
- .lock()
- .unwrap()
- .pop_front()
- .unwrap_or(vec![]);
- if command == SLEEP {
- std::thread::sleep(std::time::Duration::from_millis(200));
- } else if command == QUIT && self.sigwinch_event.is_some() {
- let (lock, cvar) = &*self.should_trigger_sigwinch;
- {
- let mut should_trigger_sigwinch = lock.lock().unwrap();
- *should_trigger_sigwinch = true;
- }
- cvar.notify_one();
- ::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS); // give some time for the app to resize before quitting
- } else if command == QUIT {
- ::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS);
- }
- command
- }
- fn get_stdout_writer(&self) -> Box<dyn Write> {
- Box::new(self.stdout_writer.clone())
- }
- fn send_to_server(&self, msg: ClientToServerMsg) {
- self.send_instructions_to_server.send(msg).unwrap();
- }
- fn recv_from_server(&self) -> (ServerToClientMsg, ErrorContext) {
- self.receive_instructions_from_server
- .lock()
- .unwrap()
- .recv()
- .unwrap()
- }
- fn handle_signals(&self, sigwinch_cb: Box<dyn Fn()>, _quit_cb: Box<dyn Fn()>) {
- if self.sigwinch_event.is_some() {
- let (lock, cvar) = &*self.should_trigger_sigwinch;
- {
- let mut should_trigger_sigwinch = lock.lock().unwrap();
- while !*should_trigger_sigwinch {
- should_trigger_sigwinch = cvar.wait(should_trigger_sigwinch).unwrap();
- }
- }
- sigwinch_cb();
- }
- }
- fn connect_to_server(&self, _path: &std::path::Path) {}
- fn load_palette(&self) -> Palette {
- default_palette()
- }
-}
-
-struct FakeAsyncReader {
- fd: RawFd,
- os_api: Box<dyn ServerOsApi>,
-}
-
-#[async_trait]
-impl AsyncReader for FakeAsyncReader {
- async fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
- // simulates async semantics: EAGAIN is not propagated to caller
- loop {
- let res = self.os_api.read_from_tty_stdout(self.fd, buf);
- match res {
- Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)) => {
- async_std::task::sleep(Duration::from_millis(10)).await;
- continue;
- }
- Err(e) => {
- break Err(std::io::Error::from_raw_os_error(
- e.as_errno().unwrap() as i32
- ))
- }
- Ok(n_bytes) => break Ok(n_bytes),
- }
- }
- }
-}
-
-impl ServerOsApi for FakeInputOutput {
- fn set_terminal_size_using_fd(&self, pid: RawFd, cols: u16, rows: u16) {
- let terminal_input = self
- .possible_tty_inputs
- .get(&cols)
- .expect(&format!("could not find input for size {:?}", cols));
- self.read_buffers
- .lock()
- .unwrap()
- .insert(pid, terminal_input.clone());
- self.io_events
- .lock()
- .unwrap()
- .push(IoEvent::SetTerminalSizeUsingFd(pid, cols, rows));
- }
- fn spawn_terminal(&self, _file_to_open: Option<PathBuf>) -> (RawFd, Pid) {
- let next_terminal_id = self.stdin_writes.lock().unwrap().keys().len() as RawFd + 1;
- self.add_terminal(next_terminal_id);
- (
- next_terminal_id as i32,
- Pid::from_raw(next_terminal_id + 1000),
- ) // secondary number is arbitrary here
- }
- fn write_to_tty_stdin(&self, pid: RawFd, buf: &[u8]) -> Result<usize, nix::Error> {
- let mut stdin_writes = self.stdin_writes.lock().unwrap();
- let write_buffer = stdin_writes.get_mut(&pid).unwrap();
- Ok(write_buffer.write(buf).unwrap())
- }
- fn read_from_tty_stdout(&self, pid: RawFd, mut buf: &mut [u8]) -> Result<usize, nix::Error> {
- let mut read_buffers = self.read_buffers.lock().unwrap();
- match read_buffers.get_mut(&pid) {
- Some(bytes) => {
- let available_range = bytes.read_position..bytes.content.len();
- let len = buf.write(&bytes.content[available_range]).unwrap();
- if len > bytes.read_position {
- bytes.set_read_position(len);
- }
- return Ok(len);
- }
- None => Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)),
- }
- }
- fn async_file_reader(&self, fd: RawFd) -> Box<dyn AsyncReader> {
- Box::new(FakeAsyncReader {
- fd,
- os_api: ServerOsApi::box_clone(self),
- })
- }
- fn tcdrain(&self, pid: RawFd) -> Result<(), nix::Error> {
- self.io_events.lock().unwrap().push(IoEvent::TcDrain(pid));
- Ok(())
- }
- fn box_clone(&self) -> Box<dyn ServerOsApi> {
- Box::new((*self).clone())
- }
- fn kill(&self, pid: Pid) -> Result<(), nix::Error> {
- self.io_events.lock().unwrap().push(IoEvent::Kill(pid));
- Ok(())
- }
- fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext) {
- self.receive_instructions_from_client
- .lock()
- .unwrap()
- .recv()
- .unwrap()
- }
- fn send_to_client(&self, msg: ServerToClientMsg) {
- self.send_instructions_to_client.send(msg).unwrap();
- }
- fn add_client_sender(&self) {}
- fn remove_client_sender(&self) {}
- fn send_to_temp_client(&self, _msg: ServerToClientMsg) {}
- fn update_receiver(&mut self, _stream: LocalSocketStream) {}
- fn load_palette(&self) -> Palette {
- default_palette()
- }
-}