chore: use new Cargo profile in CI for shorter compilation
[ouch.git] / tests / utils.rs
blob0cda620b2ed226f32aa9d0741ee3e15689ac496e
1 // This warning is unavoidable when reusing testing utils.
2 #![allow(dead_code)]
4 use std::{
5     env,
6     io::Write,
7     path::{Path, PathBuf},
8 };
10 use assert_cmd::Command;
11 use fs_err as fs;
12 use rand::{Rng, RngCore};
14 /// Run ouch with the provided arguments, returns [`assert_cmd::Output`]
15 #[macro_export]
16 macro_rules! ouch {
17     ($($e:expr),*) => {
18         $crate::utils::cargo_bin()
19             $(.arg($e))*
20             .arg("--yes")
21             .unwrap()
22     }
25 pub fn cargo_bin() -> Command {
26     env::vars()
27         .find_map(|(k, v)| {
28             (k.starts_with("CARGO_TARGET_") && k.ends_with("_RUNNER")).then(|| {
29                 let mut runner = v.split_whitespace();
30                 let mut cmd = Command::new(runner.next().unwrap());
31                 cmd.args(runner).arg(assert_cmd::cargo::cargo_bin("ouch"));
32                 cmd
33             })
34         })
35         .unwrap_or_else(|| Command::cargo_bin("ouch").expect("Failed to find ouch executable"))
38 /// Creates files in the specified directory.
39 ///
40 /// ## Example
41 ///
42 /// ```no_run
43 /// let (_dropper, dir) = testdir().unwrap();
44 /// create_files_in(dir, &["file1.txt", "file2.txt"]);
45 /// ```
46 pub fn create_files_in(dir: &Path, files: &[&str]) {
47     for f in files {
48         std::fs::File::create(dir.join(f)).unwrap();
49     }
52 /// Write random content to a file
53 pub fn write_random_content(file: &mut impl Write, rng: &mut impl RngCore) {
54     let mut data = vec![0; rng.gen_range(0..4096)];
56     rng.fill_bytes(&mut data);
57     file.write_all(&data).unwrap();
60 /// Check that two directories have the exact same content recursively.
61 /// Checks equility of file types if preserve_permissions is true, ignored on non-unix
62 // Silence clippy warning that triggers because of the `#[cfg(unix)]` on Windows.
63 #[allow(clippy::only_used_in_recursion)]
64 pub fn assert_same_directory(x: impl Into<PathBuf>, y: impl Into<PathBuf>, preserve_permissions: bool) {
65     fn read_dir(dir: impl Into<PathBuf>) -> impl Iterator<Item = fs::DirEntry> {
66         let mut dir: Vec<_> = fs::read_dir(dir).unwrap().map(|entry| entry.unwrap()).collect();
67         dir.sort_by_key(|x| x.file_name());
68         dir.into_iter()
69     }
71     let mut x = read_dir(x);
72     let mut y = read_dir(y);
74     loop {
75         match (x.next(), y.next()) {
76             (Some(x), Some(y)) => {
77                 assert_eq!(x.file_name(), y.file_name());
79                 let meta_x = x.metadata().unwrap();
80                 let meta_y = y.metadata().unwrap();
81                 let ft_x = meta_x.file_type();
82                 let ft_y = meta_y.file_type();
84                 #[cfg(unix)]
85                 if preserve_permissions {
86                     assert_eq!(ft_x, ft_y);
87                 }
89                 if ft_x.is_dir() && ft_y.is_dir() {
90                     assert_same_directory(x.path(), y.path(), preserve_permissions);
91                 } else if ft_x.is_file() && ft_y.is_file() {
92                     assert_eq!(meta_x.len(), meta_y.len());
93                     assert_eq!(fs::read(x.path()).unwrap(), fs::read(y.path()).unwrap());
94                 } else {
95                     panic!(
96                         "entries should be both directories or both files\n  left: `{:?}`,\n right: `{:?}`",
97                         x.path(),
98                         y.path()
99                     );
100                 }
101             }
103             (None, None) => break,
105             (x, y) => {
106                 panic!(
107                     "directories don't have the same number of entries\n  left: `{:?}`,\n right: `{:?}`",
108                     x.map(|x| x.path()),
109                     y.map(|y| y.path()),
110                 )
111             }
112         }
113     }
116 #[test]
117 fn src_is_src() {
118     assert_same_directory("src", "src", true);
121 #[test]
122 #[should_panic]
123 fn src_is_not_tests() {
124     assert_same_directory("src", "tests", false);