better-commands-rs/src/tests.rs
2025-01-01 21:05:47 -06:00

137 lines
3.8 KiB
Rust

#[cfg(test)]
use crate::*;
use std::{
fs::remove_file,
hash::{BuildHasher, Hasher, RandomState},
};
use std::{fs::File, os::unix::fs::FileExt, thread::sleep};
use std::process::Command;
/// Tests what stdout prints
#[test]
fn stdout_content() {
let expected = "[\"helloooooooooo\", \"hiiiiiiiiiiiii\"]";
assert_eq!(
expected,
format!(
"{:?}",
run(&mut Command::new("echo")
.arg("-n")
.arg("helloooooooooo\nhiiiiiiiiiiiii"))
.stdout()
.unwrap()
.into_iter()
.map(|line| { line.content })
.collect::<Vec<String>>()
)
);
}
/// Tests what stderr prints
#[test]
fn stderr_content() {
let expected = vec!["helloooooooooo", "hiiiiiiiiiiiii"];
// `>&2` redirects to stderr
assert_eq!(
expected,
run(&mut Command::new("bash")
.arg("-c")
.arg("echo -n 'helloooooooooo\nhiiiiiiiiiiiii' >&2"))
.stderr()
.unwrap()
.into_iter()
.map(|line| { line.content })
.collect::<Vec<String>>()
);
}
/// Tests what stderr prints
#[test]
fn test_exit_code() {
let expected = 10;
// `>&2` redirects to stderr
assert_eq!(
expected,
run(&mut Command::new("bash").arg("-c").arg("exit 10"))
.status_code()
.unwrap()
);
}
/// Tests that the output is sorted by default
#[test]
fn test_output_is_sorted_sort_works() {
let cmd = run(&mut Command::new("bash")
.arg("-c")
.arg("echo hi; echo hi; echo hi; echo hi; echo hi"))
.stdout()
.unwrap();
let mut sorted = cmd.clone();
// To avoid an accidental bogosort
while sorted.is_sorted() {
shuffle_vec(&mut sorted);
}
sorted.sort();
assert_eq!(sorted, cmd);
}
// https://stackoverflow.com/a/78840539/16432246
// with rand::seq::SliceRandom you can shuffle a Vec, but doing this to avoid introducing a ton of dependencies for one little test
fn shuffle_vec<T>(vec: &mut [T]) {
let n: usize = vec.len();
for i in 0..(n - 1) {
// Generate random index j, such that: i <= j < n
// The remainder (`%`) after division is always less than the divisor.
let j = (RandomState::new().build_hasher().finish() as usize) % (n - i) + i;
vec.swap(i, j);
}
}
#[test]
fn test_run_with_funcs() {
let _ = thread::spawn(|| {
let _ = run_with_funcs(
Command::new("bash")
.arg("-c")
.arg("echo hi; sleep 0.5; >&2 echo hello"),
{
|stdout_lines| {
sleep(Duration::from_secs(1));
for _ in stdout_lines {
Command::new("bash")
.arg("-c")
.arg("echo stdout >> ./tmp")
.output()
.unwrap();
}
}
},
{
|stderr_lines| {
sleep(Duration::from_secs(3));
for _ in stderr_lines {
Command::new("bash")
.arg("-c")
.arg("echo stderr >> ./tmp")
.output()
.unwrap();
}
}
},
);
});
sleep(Duration::from_secs(2));
let f = File::open("./tmp").unwrap();
let mut buf: [u8; 14] = [0u8; 14];
f.read_at(&mut buf, 0).unwrap();
assert_eq!(buf, [115, 116, 100, 111, 117, 116, 10, 0, 0, 0, 0, 0, 0, 0]);
sleep(Duration::from_secs(2));
f.read_at(&mut buf, 0).unwrap();
assert_eq!(
buf,
[115, 116, 100, 111, 117, 116, 10, 115, 116, 100, 101, 114, 114, 10]
);
remove_file("./tmp").unwrap();
}