add ui snapshot tests
[ouch.git] / tests / utils.rs
blob3682e99bfae2d5af9f370142cb18de882d8d0177
1 // This warning is unavoidable when reusing testing utils.
2 #![allow(dead_code)]
4 use std::{
5     env,
6     ffi::OsStr,
7     io,
8     io::Write,
9     path::{Path, PathBuf},
10     process::Output,
13 use assert_cmd::Command;
14 use fs_err as fs;
15 use rand::{Rng, RngCore};
17 // Run ouch with the provided arguments, returns `assert_cmd::Output`
18 #[macro_export]
19 macro_rules! ouch {
20     ($($e:expr),*) => {
21         $crate::utils::cargo_bin()
22             $(.arg($e))*
23             .arg("--yes")
24             .unwrap()
25     }
28 pub fn cargo_bin() -> Command {
29     env::vars()
30         .find_map(|(k, v)| {
31             (k.starts_with("CARGO_TARGET_") && k.ends_with("_RUNNER")).then(|| {
32                 let mut runner = v.split_whitespace();
33                 let mut cmd = Command::new(runner.next().unwrap());
34                 cmd.args(runner).arg(assert_cmd::cargo::cargo_bin("ouch"));
35                 cmd
36             })
37         })
38         .unwrap_or_else(|| Command::cargo_bin("ouch").expect("Failed to find ouch executable"))
41 /// Run a command inside of another folder.
42 ///
43 /// example: `run_in("/tmp", "touch", "a b c")`
44 pub fn run_in(folder: impl AsRef<Path>, bin: impl AsRef<OsStr>, args: &str) -> io::Result<Output> {
45     Command::new(bin)
46         .args(args.split_whitespace())
47         .current_dir(folder)
48         .output()
51 // write random content to a file
52 pub fn write_random_content(file: &mut impl Write, rng: &mut impl RngCore) {
53     let mut data = Vec::new();
54     data.resize(rng.gen_range(0..4096), 0);
55     rng.fill_bytes(&mut data);
56     file.write_all(&data).unwrap();
59 // check that two directories have the exact same content recursively
60 // checks equility of file types if preserve_permissions is true, ignored on non-unix
61 pub fn assert_same_directory(x: impl Into<PathBuf>, y: impl Into<PathBuf>, preserve_permissions: bool) {
62     fn read_dir(dir: impl Into<PathBuf>) -> impl Iterator<Item = fs::DirEntry> {
63         let mut dir: Vec<_> = fs::read_dir(dir).unwrap().map(|entry| entry.unwrap()).collect();
64         dir.sort_by_key(|x| x.file_name());
65         dir.into_iter()
66     }
68     let mut x = read_dir(x);
69     let mut y = read_dir(y);
71     loop {
72         match (x.next(), y.next()) {
73             (Some(x), Some(y)) => {
74                 assert_eq!(x.file_name(), y.file_name());
76                 let meta_x = x.metadata().unwrap();
77                 let meta_y = y.metadata().unwrap();
78                 let ft_x = meta_x.file_type();
79                 let ft_y = meta_y.file_type();
81                 #[cfg(unix)]
82                 if preserve_permissions {
83                     assert_eq!(ft_x, ft_y);
84                 }
86                 if ft_x.is_dir() && ft_y.is_dir() {
87                     assert_same_directory(x.path(), y.path(), preserve_permissions);
88                 } else if ft_x.is_file() && ft_y.is_file() {
89                     assert_eq!(meta_x.len(), meta_y.len());
90                     assert_eq!(fs::read(x.path()).unwrap(), fs::read(y.path()).unwrap());
91                 } else {
92                     panic!(
93                         "entries should be both directories or both files\n  left: `{:?}`,\n right: `{:?}`",
94                         x.path(),
95                         y.path()
96                     );
97                 }
98             }
100             (None, None) => break,
102             (x, y) => {
103                 panic!(
104                     "directories don't have the same number of entries\n  left: `{:?}`,\n right: `{:?}`",
105                     x.map(|x| x.path()),
106                     y.map(|y| y.path()),
107                 )
108             }
109         }
110     }
113 #[test]
114 fn src_is_src() {
115     assert_same_directory("src", "src", true);
118 #[test]
119 #[should_panic]
120 fn src_is_not_tests() {
121     assert_same_directory("src", "tests", false);