Removing .*.tar and .*.zip from tests
[ouch.git] / tests / compress_and_decompress.rs
blob05141ccdcbf7e755198cf8bbff6404de4b110166
1 use std::{
2     env, fs,
3     io::prelude::*,
4     path::{Path, PathBuf},
5 };
7 use ouch::{cli::Command, commands::run, oof};
8 use rand::{rngs::SmallRng, RngCore, SeedableRng};
9 use tempdir::TempDir;
11 #[test]
12 /// Tests each format that supports multiple files with random input.
13 /// TODO: test the remaining formats.
14 fn test_each_format() {
15     test_compression_and_decompression("tar");
16     test_compression_and_decompression("tar.gz");
17     test_compression_and_decompression("tar.bz");
18     test_compression_and_decompression("tar.bz2");
19     test_compression_and_decompression("tar.xz");
20     test_compression_and_decompression("tar.lz");
21     test_compression_and_decompression("tar.lzma");
22     test_compression_and_decompression("zip");
23     test_compression_and_decompression("zip.gz");
24     test_compression_and_decompression("zip.bz");
25     test_compression_and_decompression("zip.bz2");
26     test_compression_and_decompression("zip.xz");
27     test_compression_and_decompression("zip.lz");
28     test_compression_and_decompression("zip.lzma");
31 type FileContent = Vec<u8>;
33 fn test_compression_and_decompression(format: &str) -> bool {
34     let mut rng = SmallRng::from_entropy();
36     // System temporary directory depends on the platform
37     // For linux it is /tmp
38     let system_tmp = env::temp_dir();
39     // Create a folder that will be deleted on drop
40     let testing_dir = String::from("ouch-testing-") + format;
41     let testing_dir = TempDir::new_in(system_tmp, &testing_dir).expect("Could not create tempdir");
42     let testing_dir = testing_dir.path();
44     // Quantity of compressed files vary from 1 to 10
45     let quantity_of_files = rng.next_u32() % 10 + 1;
47     let contents_of_files: Vec<FileContent> =
48         (0..quantity_of_files).map(|_| generate_random_file_content(&mut rng)).collect();
50     let mut file_paths = create_files(&testing_dir, &contents_of_files);
51     let compressed_archive_path = compress_files(&testing_dir, &file_paths, &format);
52     let mut extracted_paths = extract_files(&compressed_archive_path);
54     // // If you want to visualize the compressed and extracted files in the temporary directory
55     // // before their auto-destruction:
56     // dbg!(&testing_dir);
57     // std::thread::sleep(std::time::Duration::from_secs(60));
59     file_paths.sort();
60     extracted_paths.sort();
62     assert_correct_paths(&file_paths, &extracted_paths);
63     compare_file_contents(&extracted_paths, &contents_of_files)
66 // Crate file contents from 1024 up to 8192 random bytes
67 fn generate_random_file_content(rng: &mut impl RngCore) -> FileContent {
68     let quantity = 1024 + rng.next_u32() % (8192 - 1024);
69     let mut vec = vec![0; quantity as usize];
70     rng.fill_bytes(&mut vec);
71     vec
74 // Create files using the indexes as file names (eg. 0, 1, 2 and 3)
75 // Returns the paths
76 fn create_files(at: &Path, contents: &[FileContent]) -> Vec<PathBuf> {
77     contents
78         .iter()
79         .enumerate()
80         .map(|(i, content)| {
81             let path = at.join(i.to_string());
82             let mut file = fs::File::create(&path).expect("Could not create dummy test file");
83             file.write_all(content).expect("Could not write to dummy test file");
84             path
85         })
86         .collect()
89 fn compress_files(at: &Path, paths_to_compress: &[PathBuf], format: &str) -> PathBuf {
90     let archive_path = String::from("archive.") + format;
91     let archive_path = at.join(archive_path);
93     let command = Command::Compress {
94         files: paths_to_compress.to_vec(),
95         compressed_output_path: archive_path.to_path_buf(),
96     };
97     run(command, &oof::Flags::default()).expect("Failed to compress test dummy files");
99     archive_path
102 fn extract_files(archive_path: &Path) -> Vec<PathBuf> {
103     // We will extract in the same folder as the archive
104     // If the archive is at:
105     //   /tmp/ouch-testing-tar.Rbq4DusBrtF8/archive.tar
106     // Then the extraction_output_folder will be:
107     //   /tmp/ouch-testing-tar.Rbq4DusBrtF8/extraction_results/
108     let mut extraction_output_folder = archive_path.to_path_buf();
109     // Remove the name of the extracted archive
110     assert!(extraction_output_folder.pop());
111     // Add the suffix "results"
112     extraction_output_folder.push("extraction_results");
114     let command = Command::Decompress {
115         files: vec![archive_path.to_owned()],
116         output_folder: Some(extraction_output_folder.clone()),
117     };
118     run(command, &oof::Flags::default()).expect("Failed to extract");
120     fs::read_dir(extraction_output_folder)
121         .unwrap()
122         .map(Result::unwrap)
123         .map(|entry| entry.path())
124         .collect()
127 fn assert_correct_paths(original: &[PathBuf], extracted: &[PathBuf]) {
128     assert_eq!(original.len(), extracted.len());
129     for (original, extracted) in original.iter().zip(extracted) {
130         assert_eq!(original.file_name(), extracted.file_name());
131     }
134 fn compare_file_contents(extracted: &[PathBuf], contents: &[FileContent]) -> bool {
135     for (extracted_path, expected_content) in extracted.iter().zip(contents) {
136         let read_content = fs::read(extracted_path).expect("Failed to read from file");
137         if &read_content != expected_content {
138             return false;
139         }
140     }
141     true