use cuddle_please_misc::{DynUi, Ui}; use std::{ io::Write, path::PathBuf, sync::{Arc, Mutex}, }; #[derive(Default)] struct BufferInner { pub stdout: Vec, pub stderr: Vec, } impl BufferInner { fn write_str(&mut self, content: &str) { write!(&mut self.stdout, "{}", content).unwrap(); } fn write_err_str(&mut self, content: &str) { write!(&mut self.stderr, "{}", content).unwrap(); } fn write_str_ln(&mut self, content: &str) { writeln!(&mut self.stdout, "{}", content).unwrap(); } fn write_err_str_ln(&mut self, content: &str) { writeln!(&mut self.stderr, "{}", content).unwrap(); } } #[derive(Clone)] pub struct BufferUi { inner: Arc>, } impl BufferUi { pub fn get_stdout(&self) -> String { let inner = self.inner.lock().unwrap(); let output = std::str::from_utf8(&inner.stdout).unwrap(); output.to_string() } pub fn get_stderr(&self) -> String { let inner = self.inner.lock().unwrap(); let output = std::str::from_utf8(&inner.stderr).unwrap(); output.to_string() } pub fn get_output(&self) -> (String, String) { let inner = self.inner.lock().unwrap(); let stdout = std::str::from_utf8(&inner.stdout).unwrap(); let stderr = std::str::from_utf8(&inner.stderr).unwrap(); (stdout.to_string(), stderr.to_string()) } } impl Ui for BufferUi { fn write_str(&self, content: &str) { let mut inner = self.inner.lock().unwrap(); print!("{}", content); inner.write_str(content) } fn write_err_str(&self, content: &str) { let mut inner = self.inner.lock().unwrap(); eprint!("{}", content); inner.write_err_str(content) } fn write_str_ln(&self, content: &str) { let mut inner = self.inner.lock().unwrap(); println!("{}", content); inner.write_str_ln(content) } fn write_err_str_ln(&self, content: &str) { let mut inner = self.inner.lock().unwrap(); eprintln!("{}", content); inner.write_err_str_ln(content) } } impl Default for BufferUi { fn default() -> Self { Self { inner: Arc::new(Mutex::new(BufferInner::default())), } } } impl From for DynUi { fn from(value: BufferUi) -> Self { Box::new(value) } } impl From<&BufferUi> for DynUi { fn from(value: &BufferUi) -> Self { value.clone().into() } } pub fn assert_output(ui: &BufferUi, expected_stdout: &str, expected_stderr: &str) { let (stdout, stderr) = ui.get_output(); pretty_assertions::assert_eq!(expected_stdout, &stdout); pretty_assertions::assert_eq!(expected_stderr, &stderr); } pub fn get_test_data_path(item: &str) -> PathBuf { std::env::current_dir() .ok() .map(|p| p.join("testdata").join(item)) .unwrap() }