Merge pull request #477 from figsoda/bump
[ouch.git] / tests / integration.rs
blob47d57031a6fcf45de581a55b36ccfdc7e7596160
1 #[macro_use]
2 mod utils;
4 use std::{iter::once, path::PathBuf};
6 use fs_err as fs;
7 use parse_display::Display;
8 use proptest::sample::size_range;
9 use rand::{rngs::SmallRng, Rng, SeedableRng};
10 use tempfile::tempdir;
11 use test_strategy::{proptest, Arbitrary};
13 use crate::utils::{assert_same_directory, write_random_content};
15 // tar and zip extensions
16 #[derive(Arbitrary, Debug, Display)]
17 #[display(style = "lowercase")]
18 enum DirectoryExtension {
19     Tar,
20     Tbz,
21     Tbz2,
22     Tgz,
23     Tlz4,
24     Tlzma,
25     Tsz,
26     Txz,
27     Tzst,
28     Zip,
31 // extensions of single file compression formats
32 #[derive(Arbitrary, Debug, Display)]
33 #[display(style = "lowercase")]
34 enum FileExtension {
35     Bz,
36     Bz2,
37     Gz,
38     Lz4,
39     Lzma,
40     Sz,
41     Xz,
42     Zst,
45 #[derive(Arbitrary, Debug, Display)]
46 #[display("{0}")]
47 enum Extension {
48     Directory(DirectoryExtension),
49     File(FileExtension),
52 // converts a list of extension structs to string
53 fn merge_extensions(ext: impl ToString, exts: Vec<FileExtension>) -> String {
54     once(ext.to_string())
55         .chain(exts.into_iter().map(|x| x.to_string()))
56         .collect::<Vec<_>>()
57         .join(".")
60 // create random nested directories and files under the specified directory
61 fn create_random_files(dir: impl Into<PathBuf>, depth: u8, rng: &mut SmallRng) {
62     if depth == 0 {
63         return;
64     }
66     let dir = &dir.into();
68     // create 0 to 7 random files
69     for _ in 0..rng.gen_range(0..8u32) {
70         write_random_content(
71             &mut tempfile::Builder::new().tempfile_in(dir).unwrap().keep().unwrap().0,
72             rng,
73         );
74     }
76     // create more random files in 0 to 3 new directories
77     for _ in 0..rng.gen_range(0..4u32) {
78         create_random_files(&tempfile::tempdir_in(dir).unwrap().into_path(), depth - 1, rng);
79     }
82 // compress and decompress a single empty file
83 #[proptest(cases = 512)]
84 fn single_empty_file(ext: Extension, #[any(size_range(0..8).lift())] exts: Vec<FileExtension>) {
85     let dir = tempdir().unwrap();
86     let dir = dir.path();
87     let before = &dir.join("before");
88     fs::create_dir(before).unwrap();
89     let before_file = &before.join("file");
90     let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts)));
91     let after = &dir.join("after");
92     write_random_content(
93         &mut fs::File::create(before_file).unwrap(),
94         &mut SmallRng::from_entropy(),
95     );
96     ouch!("-A", "c", before_file, archive);
97     ouch!("-A", "d", archive, "-d", after);
98     assert_same_directory(before, after, false);
101 // compress and decompress a single file
102 #[proptest(cases = 512)]
103 fn single_file(
104     ext: Extension,
105     #[any(size_range(0..8).lift())] exts: Vec<FileExtension>,
106     #[strategy(proptest::option::of(0i16..12))] level: Option<i16>,
107 ) {
108     let dir = tempdir().unwrap();
109     let dir = dir.path();
110     let before = &dir.join("before");
111     fs::create_dir(before).unwrap();
112     let before_file = &before.join("file");
113     let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts)));
114     let after = &dir.join("after");
115     fs::write(before_file, []).unwrap();
116     if let Some(level) = level {
117         ouch!("-A", "c", "-l", level.to_string(), before_file, archive);
118     } else {
119         ouch!("-A", "c", before_file, archive);
120     }
121     ouch!("-A", "d", archive, "-d", after);
122     assert_same_directory(before, after, false);
125 // compress and decompress a directory with random content generated with create_random_files
126 #[proptest(cases = 512)]
127 fn multiple_files(
128     ext: DirectoryExtension,
129     #[any(size_range(0..8).lift())] exts: Vec<FileExtension>,
130     #[strategy(0u8..4)] depth: u8,
131 ) {
132     let dir = tempdir().unwrap();
133     let dir = dir.path();
134     let before = &dir.join("before");
135     let before_dir = &before.join("dir");
136     fs::create_dir_all(before_dir).unwrap();
137     let archive = &dir.join(format!("archive.{}", merge_extensions(&ext, exts)));
138     let after = &dir.join("after");
139     create_random_files(before_dir, depth, &mut SmallRng::from_entropy());
140     ouch!("-A", "c", before_dir, archive);
141     ouch!("-A", "d", archive, "-d", after);
142     assert_same_directory(before, after, !matches!(ext, DirectoryExtension::Zip));