use std::path::PathBuf;
use crate::util::utils::util_path_to_string;
pub struct TempState {
new_temp_file: PathBuf,
master_record_file: PathBuf,
temprs_dir: PathBuf,
temp_file_stack: Vec<PathBuf>,
arg_file: Option<PathBuf>,
insert_idx: Option<String>,
output_buffer: String,
holding_buffer: String,
input_temp_file: Option<String>,
output_temp_file: Option<String>,
silent: bool,
verbose: u32,
}
impl TempState {
#[cfg(test)]
pub fn set_new_temp_file(&mut self, new_temp_file: PathBuf) {
self.new_temp_file = new_temp_file;
}
#[cfg(test)]
pub fn set_master_record_file(&mut self, master_record_file: PathBuf) {
self.master_record_file = master_record_file;
}
#[cfg(test)]
pub fn set_temprs_dir(&mut self, temprs_dir: PathBuf) {
self.temprs_dir = temprs_dir;
}
#[cfg(test)]
pub fn set_temp_file_stack(&mut self, temp_file_stack: Vec<PathBuf>) {
self.temp_file_stack = temp_file_stack;
}
pub fn set_arg_file(&mut self, arg_file: Option<PathBuf>) {
self.arg_file = arg_file;
}
pub fn set_insert_idx(&mut self, insert_idx: Option<String>) {
self.insert_idx = insert_idx;
}
pub fn set_holding_buffer(&mut self, holding_buffer: String) {
self.holding_buffer = holding_buffer;
}
pub fn set_output_buffer(&mut self, output_buffer: String) {
self.output_buffer = output_buffer;
}
pub fn set_input_temp_file(&mut self, input_temp_file: Option<String>) {
self.input_temp_file = input_temp_file;
}
pub fn set_output_temp_file(&mut self, output_temp_file: Option<String>) {
self.output_temp_file = output_temp_file;
}
pub fn set_silent(&mut self, silent: bool) {
self.silent = silent;
}
pub fn set_verbose(&mut self, verbose: u32) {
self.verbose = verbose;
}
}
impl TempState {
pub fn new_temp_file(&self) -> &PathBuf {
&self.new_temp_file
}
pub fn master_record_file(&self) -> &PathBuf {
&self.master_record_file
}
pub fn temprs_dir(&self) -> &PathBuf {
&self.temprs_dir
}
pub fn temp_file_stack(&self) -> &Vec<PathBuf> {
&self.temp_file_stack
}
pub fn arg_file(&self) -> &Option<PathBuf> {
&self.arg_file
}
pub fn insert_idx(&self) -> &Option<String> {
&self.insert_idx
}
pub fn holding_buffer(&self) -> &str {
&self.holding_buffer
}
pub fn output_buffer(&self) -> &str {
&self.output_buffer
}
pub fn input_temp_file(&self) -> &Option<String> {
&self.input_temp_file
}
pub fn output_temp_file(&self) -> &Option<String> {
&self.output_temp_file
}
#[cfg(test)]
pub fn silent(&self) -> bool {
self.silent
}
pub fn verbose(&self) -> u32 {
self.verbose
}
}
impl TempState {
pub fn new(
out_file: PathBuf,
master_record_file: PathBuf,
home_dir: PathBuf,
temp_file_stack: Vec<PathBuf>,
arg_file: Option<PathBuf>,
output_buffer: String,
) -> Self {
Self {
new_temp_file: out_file,
master_record_file,
temprs_dir: home_dir,
temp_file_stack,
arg_file,
insert_idx: None,
output_buffer,
holding_buffer: String::new(),
input_temp_file: None,
output_temp_file: None,
silent: false,
verbose: 0,
}
}
}
impl TempState {
pub fn out_file_path_str(&self) -> String {
util_path_to_string(self.new_temp_file())
}
#[cfg(test)]
pub fn master_file_path_str(&self) -> String {
util_path_to_string(self.master_record_file())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_state() -> TempState {
TempState::new(
PathBuf::from("/tmp/temprs/tempfile123"),
PathBuf::from("/tmp/temprs/temprs-stack"),
PathBuf::from("/tmp/temprs"),
vec![
PathBuf::from("/tmp/temprs/f1"),
PathBuf::from("/tmp/temprs/f2"),
],
None,
String::new(),
)
}
#[test]
fn new_state_defaults() {
let s = make_state();
assert_eq!(s.verbose(), 0);
assert!(!s.silent());
assert!(s.holding_buffer().is_empty());
assert!(s.output_buffer().is_empty());
assert!(s.input_temp_file().is_none());
assert!(s.output_temp_file().is_none());
assert!(s.insert_idx().is_none());
assert!(s.arg_file().is_none());
}
#[test]
fn new_temp_file_getter() {
let s = make_state();
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/temprs/tempfile123"));
}
#[test]
fn master_record_file_getter() {
let s = make_state();
assert_eq!(
s.master_record_file(),
&PathBuf::from("/tmp/temprs/temprs-stack")
);
}
#[test]
fn temprs_dir_getter() {
let s = make_state();
assert_eq!(s.temprs_dir(), &PathBuf::from("/tmp/temprs"));
}
#[test]
fn temp_file_stack_getter() {
let s = make_state();
assert_eq!(s.temp_file_stack().len(), 2);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/tmp/temprs/f1"));
assert_eq!(s.temp_file_stack()[1], PathBuf::from("/tmp/temprs/f2"));
}
#[test]
fn set_verbose() {
let mut s = make_state();
s.set_verbose(3);
assert_eq!(s.verbose(), 3);
}
#[test]
fn set_silent() {
let mut s = make_state();
s.set_silent(true);
assert!(s.silent());
}
#[test]
fn set_holding_buffer() {
let mut s = make_state();
s.set_holding_buffer("data".to_string());
assert_eq!(s.holding_buffer(), "data");
}
#[test]
fn set_output_buffer() {
let mut s = make_state();
s.set_output_buffer("out".to_string());
assert_eq!(s.output_buffer(), "out");
}
#[test]
fn set_input_temp_file() {
let mut s = make_state();
s.set_input_temp_file(Some("1".to_string()));
assert_eq!(s.input_temp_file(), &Some("1".to_string()));
}
#[test]
fn set_output_temp_file() {
let mut s = make_state();
s.set_output_temp_file(Some("2".to_string()));
assert_eq!(s.output_temp_file(), &Some("2".to_string()));
}
#[test]
fn set_insert_idx() {
let mut s = make_state();
s.set_insert_idx(Some("3".to_string()));
assert_eq!(s.insert_idx(), &Some("3".to_string()));
}
#[test]
fn set_arg_file() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/input.txt")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/input.txt")));
}
#[test]
fn set_new_temp_file() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("/tmp/new"));
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/new"));
}
#[test]
fn set_master_record_file() {
let mut s = make_state();
s.set_master_record_file(PathBuf::from("/tmp/master2"));
assert_eq!(s.master_record_file(), &PathBuf::from("/tmp/master2"));
}
#[test]
fn set_temprs_dir() {
let mut s = make_state();
s.set_temprs_dir(PathBuf::from("/tmp/other"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/tmp/other"));
}
#[test]
fn set_temp_file_stack() {
let mut s = make_state();
s.set_temp_file_stack(vec![PathBuf::from("/tmp/x")]);
assert_eq!(s.temp_file_stack().len(), 1);
}
#[test]
fn out_file_path_str_matches() {
let s = make_state();
assert_eq!(s.out_file_path_str(), "/tmp/temprs/tempfile123");
}
#[test]
fn master_file_path_str_matches() {
let s = make_state();
assert_eq!(s.master_file_path_str(), "/tmp/temprs/temprs-stack");
}
#[test]
fn new_with_output_buffer() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::from("preset output"),
);
assert_eq!(s.output_buffer(), "preset output");
}
#[test]
fn new_with_arg_file() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
Some(PathBuf::from("/tmp/input.txt")),
String::new(),
);
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/input.txt")));
}
#[test]
fn new_with_empty_stack() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::new(),
);
assert!(s.temp_file_stack().is_empty());
}
#[test]
fn new_with_large_stack() {
let stack: Vec<PathBuf> = (0..50)
.map(|i| PathBuf::from(format!("/tmp/temprs/f{}", i)))
.collect();
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
stack.clone(),
None,
String::new(),
);
assert_eq!(s.temp_file_stack().len(), 50);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/tmp/temprs/f0"));
assert_eq!(s.temp_file_stack()[49], PathBuf::from("/tmp/temprs/f49"));
}
#[test]
fn set_verbose_multiple_times() {
let mut s = make_state();
s.set_verbose(1);
assert_eq!(s.verbose(), 1);
s.set_verbose(5);
assert_eq!(s.verbose(), 5);
s.set_verbose(0);
assert_eq!(s.verbose(), 0);
}
#[test]
fn set_silent_toggle() {
let mut s = make_state();
s.set_silent(true);
assert!(s.silent());
s.set_silent(false);
assert!(!s.silent());
s.set_silent(true);
assert!(s.silent());
}
#[test]
fn set_holding_buffer_overwrite() {
let mut s = make_state();
s.set_holding_buffer("first".to_string());
assert_eq!(s.holding_buffer(), "first");
s.set_holding_buffer("second".to_string());
assert_eq!(s.holding_buffer(), "second");
}
#[test]
fn set_output_buffer_overwrite() {
let mut s = make_state();
s.set_output_buffer("out1".to_string());
s.set_output_buffer("out2".to_string());
assert_eq!(s.output_buffer(), "out2");
}
#[test]
fn set_insert_idx_to_none() {
let mut s = make_state();
s.set_insert_idx(Some("5".to_string()));
assert!(s.insert_idx().is_some());
s.set_insert_idx(None);
assert!(s.insert_idx().is_none());
}
#[test]
fn set_input_temp_file_to_none() {
let mut s = make_state();
s.set_input_temp_file(Some("1".to_string()));
assert!(s.input_temp_file().is_some());
s.set_input_temp_file(None);
assert!(s.input_temp_file().is_none());
}
#[test]
fn set_output_temp_file_to_none() {
let mut s = make_state();
s.set_output_temp_file(Some("2".to_string()));
assert!(s.output_temp_file().is_some());
s.set_output_temp_file(None);
assert!(s.output_temp_file().is_none());
}
#[test]
fn set_arg_file_to_none() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/f")));
assert!(s.arg_file().is_some());
s.set_arg_file(None);
assert!(s.arg_file().is_none());
}
#[test]
fn set_temp_file_stack_empty() {
let mut s = make_state();
assert_eq!(s.temp_file_stack().len(), 2);
s.set_temp_file_stack(vec![]);
assert!(s.temp_file_stack().is_empty());
}
#[test]
fn set_temp_file_stack_larger() {
let mut s = make_state();
let big: Vec<PathBuf> = (0..10).map(|i| PathBuf::from(format!("/f{}", i))).collect();
s.set_temp_file_stack(big);
assert_eq!(s.temp_file_stack().len(), 10);
}
#[test]
fn out_file_path_str_with_spaces() {
let s = TempState::new(
PathBuf::from("/tmp/my dir/file"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::new(),
);
assert_eq!(s.out_file_path_str(), "/tmp/my dir/file");
}
#[test]
fn master_file_path_str_deep_path() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/a/b/c/d/e/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::new(),
);
assert_eq!(s.master_file_path_str(), "/a/b/c/d/e/master");
}
#[test]
fn holding_buffer_unicode() {
let mut s = make_state();
s.set_holding_buffer("日本語 🎉".to_string());
assert_eq!(s.holding_buffer(), "日本語 🎉");
}
#[test]
fn output_buffer_multiline() {
let mut s = make_state();
s.set_output_buffer("line1\nline2\nline3".to_string());
assert_eq!(s.output_buffer(), "line1\nline2\nline3");
}
#[test]
fn holding_buffer_empty() {
let mut s = make_state();
s.set_holding_buffer(String::new());
assert!(s.holding_buffer().is_empty());
}
#[test]
fn verbose_max_value() {
let mut s = make_state();
s.set_verbose(u32::MAX);
assert_eq!(s.verbose(), u32::MAX);
}
#[test]
fn verbose_zero() {
let mut s = make_state();
s.set_verbose(0);
assert_eq!(s.verbose(), 0);
}
#[test]
fn verbose_one() {
let mut s = make_state();
s.set_verbose(1);
assert_eq!(s.verbose(), 1);
}
#[test]
fn holding_buffer_large() {
let mut s = make_state();
let large = "x".repeat(10_000);
s.set_holding_buffer(large.clone());
assert_eq!(s.holding_buffer(), large);
assert_eq!(s.holding_buffer().len(), 10_000);
}
#[test]
fn output_buffer_large() {
let mut s = make_state();
let large = "y".repeat(10_000);
s.set_output_buffer(large.clone());
assert_eq!(s.output_buffer(), large);
assert_eq!(s.output_buffer().len(), 10_000);
}
#[test]
fn holding_buffer_tabs_and_newlines() {
let mut s = make_state();
s.set_holding_buffer("col1\tcol2\nrow2col1\trow2col2".to_string());
assert_eq!(s.holding_buffer(), "col1\tcol2\nrow2col1\trow2col2");
}
#[test]
fn output_buffer_special_chars() {
let mut s = make_state();
s.set_output_buffer("quotes: \"hello\" 'world'\nbackslash: \\".to_string());
assert_eq!(s.output_buffer(), "quotes: \"hello\" 'world'\nbackslash: \\");
}
#[test]
fn output_buffer_empty_string() {
let mut s = make_state();
s.set_output_buffer("data".to_string());
s.set_output_buffer(String::new());
assert!(s.output_buffer().is_empty());
}
#[test]
fn input_temp_file_negative_index() {
let mut s = make_state();
s.set_input_temp_file(Some("-1".to_string()));
assert_eq!(s.input_temp_file(), &Some("-1".to_string()));
}
#[test]
fn output_temp_file_negative_index() {
let mut s = make_state();
s.set_output_temp_file(Some("-3".to_string()));
assert_eq!(s.output_temp_file(), &Some("-3".to_string()));
}
#[test]
fn input_temp_file_large_index() {
let mut s = make_state();
s.set_input_temp_file(Some("999".to_string()));
assert_eq!(s.input_temp_file(), &Some("999".to_string()));
}
#[test]
fn output_temp_file_large_index() {
let mut s = make_state();
s.set_output_temp_file(Some("1000".to_string()));
assert_eq!(s.output_temp_file(), &Some("1000".to_string()));
}
#[test]
fn insert_idx_negative() {
let mut s = make_state();
s.set_insert_idx(Some("-2".to_string()));
assert_eq!(s.insert_idx(), &Some("-2".to_string()));
}
#[test]
fn insert_idx_large() {
let mut s = make_state();
s.set_insert_idx(Some("100".to_string()));
assert_eq!(s.insert_idx(), &Some("100".to_string()));
}
#[test]
fn insert_idx_overwrite() {
let mut s = make_state();
s.set_insert_idx(Some("1".to_string()));
s.set_insert_idx(Some("5".to_string()));
assert_eq!(s.insert_idx(), &Some("5".to_string()));
}
#[test]
fn arg_file_with_spaces() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/my dir/file.txt")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/my dir/file.txt")));
}
#[test]
fn arg_file_deep_path() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/a/b/c/d/e/f/g.txt")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/a/b/c/d/e/f/g.txt")));
}
#[test]
fn arg_file_overwrite() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/first")));
s.set_arg_file(Some(PathBuf::from("/second")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/second")));
}
#[test]
fn stack_replace_then_check_elements() {
let mut s = make_state();
let stack = vec![
PathBuf::from("/a"),
PathBuf::from("/b"),
PathBuf::from("/c"),
];
s.set_temp_file_stack(stack);
assert_eq!(s.temp_file_stack().len(), 3);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/a"));
assert_eq!(s.temp_file_stack()[1], PathBuf::from("/b"));
assert_eq!(s.temp_file_stack()[2], PathBuf::from("/c"));
}
#[test]
fn stack_replace_multiple_times() {
let mut s = make_state();
s.set_temp_file_stack(vec![PathBuf::from("/x")]);
assert_eq!(s.temp_file_stack().len(), 1);
s.set_temp_file_stack(vec![PathBuf::from("/y"), PathBuf::from("/z")]);
assert_eq!(s.temp_file_stack().len(), 2);
s.set_temp_file_stack(vec![]);
assert!(s.temp_file_stack().is_empty());
}
#[test]
fn new_temp_file_with_unicode() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("/tmp/日本語/tempfile"));
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/日本語/tempfile"));
}
#[test]
fn new_temp_file_overwrite() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("/tmp/first"));
s.set_new_temp_file(PathBuf::from("/tmp/second"));
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/second"));
}
#[test]
fn master_record_file_overwrite() {
let mut s = make_state();
s.set_master_record_file(PathBuf::from("/first"));
s.set_master_record_file(PathBuf::from("/second"));
assert_eq!(s.master_record_file(), &PathBuf::from("/second"));
}
#[test]
fn temprs_dir_overwrite() {
let mut s = make_state();
s.set_temprs_dir(PathBuf::from("/dir1"));
s.set_temprs_dir(PathBuf::from("/dir2"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/dir2"));
}
#[test]
fn temprs_dir_with_spaces() {
let mut s = make_state();
s.set_temprs_dir(PathBuf::from("/tmp/my dir"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/tmp/my dir"));
}
#[test]
fn out_file_path_str_after_set() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("/new/path/file"));
assert_eq!(s.out_file_path_str(), "/new/path/file");
}
#[test]
fn master_file_path_str_after_set() {
let mut s = make_state();
s.set_master_record_file(PathBuf::from("/new/master"));
assert_eq!(s.master_file_path_str(), "/new/master");
}
#[test]
fn new_all_fields_non_default() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp/dir"),
vec![PathBuf::from("/tmp/f1"), PathBuf::from("/tmp/f2"), PathBuf::from("/tmp/f3")],
Some(PathBuf::from("/tmp/argfile")),
String::from("initial output"),
);
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/out"));
assert_eq!(s.master_record_file(), &PathBuf::from("/tmp/master"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/tmp/dir"));
assert_eq!(s.temp_file_stack().len(), 3);
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/argfile")));
assert_eq!(s.output_buffer(), "initial output");
assert!(s.holding_buffer().is_empty());
assert!(s.insert_idx().is_none());
assert!(s.input_temp_file().is_none());
assert!(s.output_temp_file().is_none());
assert!(!s.silent());
assert_eq!(s.verbose(), 0);
}
#[test]
fn set_all_fields_then_verify() {
let mut s = make_state();
s.set_verbose(2);
s.set_silent(true);
s.set_holding_buffer("hold".to_string());
s.set_output_buffer("out".to_string());
s.set_input_temp_file(Some("3".to_string()));
s.set_output_temp_file(Some("4".to_string()));
s.set_insert_idx(Some("2".to_string()));
s.set_arg_file(Some(PathBuf::from("/tmp/arg")));
s.set_new_temp_file(PathBuf::from("/tmp/new"));
s.set_master_record_file(PathBuf::from("/tmp/master2"));
s.set_temprs_dir(PathBuf::from("/tmp/dir2"));
s.set_temp_file_stack(vec![PathBuf::from("/tmp/only")]);
assert_eq!(s.verbose(), 2);
assert!(s.silent());
assert_eq!(s.holding_buffer(), "hold");
assert_eq!(s.output_buffer(), "out");
assert_eq!(s.input_temp_file(), &Some("3".to_string()));
assert_eq!(s.output_temp_file(), &Some("4".to_string()));
assert_eq!(s.insert_idx(), &Some("2".to_string()));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/arg")));
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/new"));
assert_eq!(s.master_record_file(), &PathBuf::from("/tmp/master2"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/tmp/dir2"));
assert_eq!(s.temp_file_stack().len(), 1);
}
#[test]
fn set_verbose_doesnt_change_silent() {
let mut s = make_state();
s.set_silent(true);
s.set_verbose(5);
assert!(s.silent());
}
#[test]
fn set_holding_doesnt_change_output() {
let mut s = make_state();
s.set_output_buffer("original".to_string());
s.set_holding_buffer("changed".to_string());
assert_eq!(s.output_buffer(), "original");
}
#[test]
fn set_input_doesnt_change_output_temp() {
let mut s = make_state();
s.set_output_temp_file(Some("5".to_string()));
s.set_input_temp_file(Some("3".to_string()));
assert_eq!(s.output_temp_file(), &Some("5".to_string()));
}
#[test]
fn set_stack_doesnt_change_dir() {
let mut s = make_state();
let orig_dir = s.temprs_dir().clone();
s.set_temp_file_stack(vec![]);
assert_eq!(s.temprs_dir(), &orig_dir);
}
#[test]
fn set_arg_file_doesnt_change_new_temp_file() {
let mut s = make_state();
let orig = s.new_temp_file().clone();
s.set_arg_file(Some(PathBuf::from("/tmp/other")));
assert_eq!(s.new_temp_file(), &orig);
}
#[test]
fn new_with_single_stack_item() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![PathBuf::from("/tmp/only_one")],
None,
String::new(),
);
assert_eq!(s.temp_file_stack().len(), 1);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/tmp/only_one"));
}
#[test]
fn new_with_very_large_stack() {
let stack: Vec<PathBuf> = (0..200)
.map(|i| PathBuf::from(format!("/tmp/temprs/f{}", i)))
.collect();
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
stack,
None,
String::new(),
);
assert_eq!(s.temp_file_stack().len(), 200);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/tmp/temprs/f0"));
assert_eq!(s.temp_file_stack()[199], PathBuf::from("/tmp/temprs/f199"));
}
#[test]
fn new_preserves_output_buffer_with_newlines() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::from("a\nb\nc"),
);
assert_eq!(s.output_buffer(), "a\nb\nc");
}
#[test]
fn new_preserves_output_buffer_with_unicode() {
let s = TempState::new(
PathBuf::from("/tmp/out"),
PathBuf::from("/tmp/master"),
PathBuf::from("/tmp"),
vec![],
None,
String::from("日本語 🚀"),
);
assert_eq!(s.output_buffer(), "日本語 🚀");
}
#[test]
fn new_with_deeply_nested_paths() {
let deep = PathBuf::from("/a/b/c/d/e/f/g/h");
let s = TempState::new(
deep.clone(),
deep.clone(),
deep.clone(),
vec![deep.clone()],
Some(deep.clone()),
String::new(),
);
assert_eq!(s.new_temp_file(), &deep);
assert_eq!(s.master_record_file(), &deep);
assert_eq!(s.temprs_dir(), &deep);
assert_eq!(s.temp_file_stack()[0], deep);
assert_eq!(s.arg_file(), &Some(deep));
}
#[test]
fn set_all_then_reset_all_to_defaults() {
let mut s = make_state();
s.set_verbose(10);
s.set_silent(true);
s.set_holding_buffer("hold".to_string());
s.set_output_buffer("out".to_string());
s.set_input_temp_file(Some("1".to_string()));
s.set_output_temp_file(Some("2".to_string()));
s.set_insert_idx(Some("3".to_string()));
s.set_arg_file(Some(PathBuf::from("/tmp/arg")));
s.set_verbose(0);
s.set_silent(false);
s.set_holding_buffer(String::new());
s.set_output_buffer(String::new());
s.set_input_temp_file(None);
s.set_output_temp_file(None);
s.set_insert_idx(None);
s.set_arg_file(None);
assert_eq!(s.verbose(), 0);
assert!(!s.silent());
assert!(s.holding_buffer().is_empty());
assert!(s.output_buffer().is_empty());
assert!(s.input_temp_file().is_none());
assert!(s.output_temp_file().is_none());
assert!(s.insert_idx().is_none());
assert!(s.arg_file().is_none());
}
#[test]
fn set_holding_then_output_independent() {
let mut s = make_state();
s.set_holding_buffer("A".to_string());
s.set_output_buffer("B".to_string());
assert_eq!(s.holding_buffer(), "A");
assert_eq!(s.output_buffer(), "B");
}
#[test]
fn set_verbose_doesnt_affect_output_buffer() {
let mut s = make_state();
s.set_output_buffer("original".to_string());
s.set_verbose(42);
assert_eq!(s.output_buffer(), "original");
}
#[test]
fn set_silent_doesnt_affect_holding_buffer() {
let mut s = make_state();
s.set_holding_buffer("keep_me".to_string());
s.set_silent(true);
assert_eq!(s.holding_buffer(), "keep_me");
}
#[test]
fn set_insert_idx_doesnt_affect_input_temp_file() {
let mut s = make_state();
s.set_input_temp_file(Some("99".to_string()));
s.set_insert_idx(Some("5".to_string()));
assert_eq!(s.input_temp_file(), &Some("99".to_string()));
}
#[test]
fn set_output_temp_file_doesnt_affect_insert_idx() {
let mut s = make_state();
s.set_insert_idx(Some("7".to_string()));
s.set_output_temp_file(Some("88".to_string()));
assert_eq!(s.insert_idx(), &Some("7".to_string()));
}
#[test]
fn set_new_temp_file_multiple_times() {
let mut s = make_state();
for i in 0..5 {
s.set_new_temp_file(PathBuf::from(format!("/tmp/path{}", i)));
}
assert_eq!(s.new_temp_file(), &PathBuf::from("/tmp/path4"));
}
#[test]
fn set_master_record_file_with_unicode() {
let mut s = make_state();
s.set_master_record_file(PathBuf::from("/tmp/日本語/マスター"));
assert_eq!(
s.master_record_file(),
&PathBuf::from("/tmp/日本語/マスター")
);
}
#[test]
fn set_temprs_dir_deeply_nested() {
let mut s = make_state();
s.set_temprs_dir(PathBuf::from("/a/b/c/d/e/f"));
assert_eq!(s.temprs_dir(), &PathBuf::from("/a/b/c/d/e/f"));
}
#[test]
fn set_temp_file_stack_grow_and_shrink() {
let mut s = make_state();
s.set_temp_file_stack(vec![
PathBuf::from("/a"),
PathBuf::from("/b"),
PathBuf::from("/c"),
]);
assert_eq!(s.temp_file_stack().len(), 3);
let big: Vec<PathBuf> = (0..10).map(|i| PathBuf::from(format!("/f{}", i))).collect();
s.set_temp_file_stack(big);
assert_eq!(s.temp_file_stack().len(), 10);
s.set_temp_file_stack(vec![PathBuf::from("/only")]);
assert_eq!(s.temp_file_stack().len(), 1);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/only"));
}
#[test]
fn holding_buffer_with_null_bytes() {
let mut s = make_state();
s.set_holding_buffer("data\0more".to_string());
assert_eq!(s.holding_buffer(), "data\0more");
}
#[test]
fn output_buffer_with_carriage_returns() {
let mut s = make_state();
s.set_output_buffer("line1\r\nline2\r\n".to_string());
assert_eq!(s.output_buffer(), "line1\r\nline2\r\n");
}
#[test]
fn holding_buffer_only_whitespace() {
let mut s = make_state();
s.set_holding_buffer(" \t\n ".to_string());
assert_eq!(s.holding_buffer(), " \t\n ");
assert!(!s.holding_buffer().is_empty());
}
#[test]
fn output_buffer_very_long() {
let mut s = make_state();
let long = "x".repeat(100_000);
s.set_output_buffer(long.clone());
assert_eq!(s.output_buffer(), long);
assert_eq!(s.output_buffer().len(), 100_000);
}
#[test]
fn holding_buffer_repeated_set_and_check() {
let mut s = make_state();
for i in 0..20 {
s.set_holding_buffer(format!("val_{}", i));
}
assert_eq!(s.holding_buffer(), "val_19");
}
#[test]
fn insert_idx_zero_string() {
let mut s = make_state();
s.set_insert_idx(Some("0".to_string()));
assert_eq!(s.insert_idx(), &Some("0".to_string()));
}
#[test]
fn input_temp_file_zero_string() {
let mut s = make_state();
s.set_input_temp_file(Some("0".to_string()));
assert_eq!(s.input_temp_file(), &Some("0".to_string()));
}
#[test]
fn output_temp_file_zero_string() {
let mut s = make_state();
s.set_output_temp_file(Some("0".to_string()));
assert_eq!(s.output_temp_file(), &Some("0".to_string()));
}
#[test]
fn insert_idx_non_numeric() {
let mut s = make_state();
s.set_insert_idx(Some("abc".to_string()));
assert_eq!(s.insert_idx(), &Some("abc".to_string()));
}
#[test]
fn input_temp_file_non_numeric() {
let mut s = make_state();
s.set_input_temp_file(Some("xyz".to_string()));
assert_eq!(s.input_temp_file(), &Some("xyz".to_string()));
}
#[test]
fn output_temp_file_non_numeric() {
let mut s = make_state();
s.set_output_temp_file(Some("not_a_number".to_string()));
assert_eq!(s.output_temp_file(), &Some("not_a_number".to_string()));
}
#[test]
fn out_file_path_str_with_unicode() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("/tmp/日本語/ファイル"));
assert_eq!(s.out_file_path_str(), "/tmp/日本語/ファイル");
}
#[test]
fn out_file_path_str_relative_path() {
let mut s = make_state();
s.set_new_temp_file(PathBuf::from("foo/bar"));
assert_eq!(s.out_file_path_str(), "foo/bar");
}
#[test]
fn master_file_path_str_with_spaces() {
let mut s = make_state();
s.set_master_record_file(PathBuf::from("/tmp/my dir/master file"));
assert_eq!(s.master_file_path_str(), "/tmp/my dir/master file");
}
#[test]
fn out_file_path_str_very_long_path() {
let mut s = make_state();
let long_path = format!("/tmp/{}", "a".repeat(500));
s.set_new_temp_file(PathBuf::from(&long_path));
assert_eq!(s.out_file_path_str(), long_path);
}
#[test]
fn arg_file_relative_path() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("relative/path.txt")));
assert_eq!(
s.arg_file(),
&Some(PathBuf::from("relative/path.txt"))
);
}
#[test]
fn arg_file_root_path() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/")));
}
#[test]
fn arg_file_with_unicode() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/日本語/file")));
assert_eq!(
s.arg_file(),
&Some(PathBuf::from("/tmp/日本語/file"))
);
}
#[test]
fn arg_file_set_check_set_none_check() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/present")));
assert_eq!(s.arg_file(), &Some(PathBuf::from("/tmp/present")));
s.set_arg_file(None);
assert!(s.arg_file().is_none());
}
#[test]
fn temp_file_stack_paths_preserved_exactly() {
let mut s = make_state();
let paths: Vec<PathBuf> = vec![
PathBuf::from("/alpha"),
PathBuf::from("/beta"),
PathBuf::from("/gamma"),
PathBuf::from("/delta"),
PathBuf::from("/epsilon"),
];
s.set_temp_file_stack(paths.clone());
for (i, p) in paths.iter().enumerate() {
assert_eq!(&s.temp_file_stack()[i], p);
}
}
#[test]
fn temp_file_stack_with_unicode_paths() {
let mut s = make_state();
s.set_temp_file_stack(vec![
PathBuf::from("/tmp/日本語"),
PathBuf::from("/tmp/中文"),
PathBuf::from("/tmp/한국어"),
]);
assert_eq!(s.temp_file_stack().len(), 3);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("/tmp/日本語"));
assert_eq!(s.temp_file_stack()[1], PathBuf::from("/tmp/中文"));
assert_eq!(s.temp_file_stack()[2], PathBuf::from("/tmp/한국어"));
}
#[test]
fn temp_file_stack_with_duplicate_paths() {
let mut s = make_state();
let dup = PathBuf::from("/tmp/same");
s.set_temp_file_stack(vec![dup.clone(), dup.clone()]);
assert_eq!(s.temp_file_stack().len(), 2);
assert_eq!(s.temp_file_stack()[0], dup);
assert_eq!(s.temp_file_stack()[1], dup);
}
#[test]
fn temp_file_stack_with_relative_paths() {
let mut s = make_state();
s.set_temp_file_stack(vec![
PathBuf::from("relative/one"),
PathBuf::from("relative/two"),
]);
assert_eq!(s.temp_file_stack()[0], PathBuf::from("relative/one"));
assert_eq!(s.temp_file_stack()[1], PathBuf::from("relative/two"));
}
#[test]
fn rapid_mutation_cycle() {
let mut s = make_state();
for i in 0..50u32 {
s.set_verbose(i);
s.set_holding_buffer(format!("h{}", i));
s.set_output_buffer(format!("o{}", i));
}
assert_eq!(s.verbose(), 49);
assert_eq!(s.holding_buffer(), "h49");
assert_eq!(s.output_buffer(), "o49");
}
#[test]
fn all_optional_fields_some_then_none() {
let mut s = make_state();
s.set_arg_file(Some(PathBuf::from("/tmp/arg")));
s.set_insert_idx(Some("5".to_string()));
s.set_input_temp_file(Some("10".to_string()));
s.set_output_temp_file(Some("20".to_string()));
assert!(s.arg_file().is_some());
assert!(s.insert_idx().is_some());
assert!(s.input_temp_file().is_some());
assert!(s.output_temp_file().is_some());
s.set_arg_file(None);
s.set_insert_idx(None);
s.set_input_temp_file(None);
s.set_output_temp_file(None);
assert!(s.arg_file().is_none());
assert!(s.insert_idx().is_none());
assert!(s.input_temp_file().is_none());
assert!(s.output_temp_file().is_none());
}
}