Giving better tests failure messages

This commit is contained in:
João M. Bezerra 2021-08-13 03:21:23 -03:00
parent 7265effd65
commit 1a67da03ed

View File

@ -11,35 +11,33 @@ use rand::{rngs::SmallRng, RngCore, SeedableRng};
/// Tests each format that supports multiple files with random input. /// Tests each format that supports multiple files with random input.
/// TODO: test the remaining formats. /// TODO: test the remaining formats.
fn test_each_format() { fn test_each_format() {
assert!(test_compression_and_decompression("tar")); test_compressing_and_decompressing_archive("tar");
assert!(test_compression_and_decompression("tar.gz")); test_compressing_and_decompressing_archive("tar.gz");
assert!(test_compression_and_decompression("tar.bz")); test_compressing_and_decompressing_archive("tar.bz");
assert!(test_compression_and_decompression("tar.bz2")); test_compressing_and_decompressing_archive("tar.bz2");
assert!(test_compression_and_decompression("tar.xz")); test_compressing_and_decompressing_archive("tar.xz");
assert!(test_compression_and_decompression("tar.lz")); test_compressing_and_decompressing_archive("tar.lz");
assert!(test_compression_and_decompression("tar.lzma")); test_compressing_and_decompressing_archive("tar.lzma");
assert!(test_compression_and_decompression("zip")); test_compressing_and_decompressing_archive("zip");
assert!(test_compression_and_decompression("zip.gz")); test_compressing_and_decompressing_archive("zip.gz");
assert!(test_compression_and_decompression("zip.bz")); test_compressing_and_decompressing_archive("zip.bz");
assert!(test_compression_and_decompression("zip.bz2")); test_compressing_and_decompressing_archive("zip.bz2");
assert!(test_compression_and_decompression("zip.xz")); test_compressing_and_decompressing_archive("zip.xz");
assert!(test_compression_and_decompression("zip.lz")); test_compressing_and_decompressing_archive("zip.lz");
assert!(test_compression_and_decompression("zip.lzma")); test_compressing_and_decompressing_archive("zip.lzma");
// Why not // Why not
assert!(test_compression_and_decompression("tar.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.lz.lz.lz.lz.lz.lz.lz.lz.lz.lz.bz.bz.bz.bz.bz.bz.bz")); test_compressing_and_decompressing_archive("tar.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.gz.lz.lz.lz.lz.lz.lz.lz.lz.lz.lz.bz.bz.bz.bz.bz.bz.bz");
} }
type FileContent = Vec<u8>; type FileContent = Vec<u8>;
fn test_compression_and_decompression(format: &str) -> bool { /// Compress and decompresses random files to archive formats, checks if contents match
let mut rng = SmallRng::from_entropy(); fn test_compressing_and_decompressing_archive(format: &str) {
// System temporary directory depends on the platform, for linux it's /tmp
// System temporary directory depends on the platform
// For linux it is /tmp
let system_tmp = env::temp_dir(); let system_tmp = env::temp_dir();
// Create a folder that will be deleted on drop // Create a temporary testing folder that will be deleted on scope drop
let testing_dir = tempfile::Builder::new() let testing_dir = tempfile::Builder::new()
.prefix("ouch-testing") .prefix("ouch-testing")
.tempdir_in(system_tmp) .tempdir_in(system_tmp)
@ -47,28 +45,32 @@ fn test_compression_and_decompression(format: &str) -> bool {
let testing_dir_path = testing_dir.path(); let testing_dir_path = testing_dir.path();
// Quantity of compressed files vary from 1 to 10 // Quantity of compressed files vary from 1 to 10
let mut rng = SmallRng::from_entropy();
let quantity_of_files = rng.next_u32() % 10 + 1; let quantity_of_files = rng.next_u32() % 10 + 1;
let contents_of_files: Vec<FileContent> = let contents_of_files: Vec<FileContent> =
(0..quantity_of_files).map(|_| generate_random_file_content(&mut rng)).collect(); (0..quantity_of_files).map(|_| generate_random_file_content(&mut rng)).collect();
// Create them
let mut file_paths = create_files(&testing_dir_path, &contents_of_files); let mut file_paths = create_files(&testing_dir_path, &contents_of_files);
// Compress them
let compressed_archive_path = compress_files(&testing_dir_path, &file_paths, &format); let compressed_archive_path = compress_files(&testing_dir_path, &file_paths, &format);
// Decompress them
let mut extracted_paths = extract_files(&compressed_archive_path); let mut extracted_paths = extract_files(&compressed_archive_path);
// // If you want to visualize the compressed and extracted files in the temporary directory // // DEBUG UTIL:
// // before their auto-destruction: // // Uncomment line below to freeze the code and see compressed and extracted files in
// dbg!(&testing_dir); // // the temporary directory before their auto-destruction.
// std::thread::sleep(std::time::Duration::from_secs(60)); // std::thread::sleep(std::time::Duration::from_secs(1_000_000));
file_paths.sort(); file_paths.sort();
extracted_paths.sort(); extracted_paths.sort();
assert_correct_paths(&file_paths, &extracted_paths); assert_correct_paths(&file_paths, &extracted_paths, format);
compare_file_contents(&extracted_paths, &contents_of_files) compare_file_contents(&extracted_paths, &contents_of_files, format);
} }
// Crate file contents from 1024 up to 8192 random bytes /// Crate file contents from 1024 up to 8192 random bytes
fn generate_random_file_content(rng: &mut impl RngCore) -> FileContent { fn generate_random_file_content(rng: &mut impl RngCore) -> FileContent {
let quantity = 1024 + rng.next_u32() % (8192 - 1024); let quantity = 1024 + rng.next_u32() % (8192 - 1024);
let mut vec = vec![0; quantity as usize]; let mut vec = vec![0; quantity as usize];
@ -76,8 +78,9 @@ fn generate_random_file_content(rng: &mut impl RngCore) -> FileContent {
vec vec
} }
// Create files using the indexes as file names (eg. 0, 1, 2 and 3) /// Create files using the indexes as file names (eg. 0, 1, 2 and 3)
// Returns the paths ///
/// Return the path to each one.
fn create_files(at: &Path, contents: &[FileContent]) -> Vec<PathBuf> { fn create_files(at: &Path, contents: &[FileContent]) -> Vec<PathBuf> {
contents contents
.iter() .iter()
@ -129,16 +132,28 @@ fn extract_files(archive_path: &Path) -> Vec<PathBuf> {
.collect() .collect()
} }
fn assert_correct_paths(original: &[PathBuf], extracted: &[PathBuf]) { fn assert_correct_paths(original: &[PathBuf], extracted: &[PathBuf], format: &str) {
assert_eq!(original.len(), extracted.len()); assert_eq!(
original.len(),
extracted.len(),
"Number of compressed files does not match number of decompressed when testing archive format '{:?}'.",
format
);
for (original, extracted) in original.iter().zip(extracted) { for (original, extracted) in original.iter().zip(extracted) {
assert_eq!(original.file_name(), extracted.file_name()); assert_eq!(original.file_name(), extracted.file_name(), "");
} }
} }
fn compare_file_contents(extracted: &[PathBuf], contents: &[FileContent]) -> bool { fn compare_file_contents(extracted: &[PathBuf], contents: &[FileContent], format: &str) {
extracted.iter().zip(contents).all(|(extracted_path, expected_content)| { extracted.iter().zip(contents).for_each(|(extracted_path, expected_content)| {
let actual_content = fs::read(extracted_path).unwrap(); let actual_content = fs::read(extracted_path).unwrap();
expected_content == actual_content.as_slice()
}) assert_eq!(
expected_content,
actual_content.as_slice(),
"Contents of file with path '{:?}' does not match after compression and decompression while testing archive format '{:?}.'",
extracted_path.canonicalize().unwrap(),
format
);
});
} }