#[macro_use] mod utils; use std::{iter::once, path::PathBuf}; use fs_err as fs; use parse_display::Display; use proptest::sample::size_range; use rand::{rngs::SmallRng, RngCore, SeedableRng}; use tempfile::tempdir; use test_strategy::{proptest, Arbitrary}; use crate::utils::create_file_random; #[derive(Arbitrary, Debug, Display)] #[display(style = "snake_case")] enum DirectoryExtension { Tar, Tbz, Tgz, Tlz4, Tlz, Tlzma, Txz, Zip, } #[derive(Arbitrary, Debug, Display)] #[display(style = "snake_case")] enum FileExtension { Bz, Bz2, Gz, // Lz4, // broken Lz, Lzma, Xz, } #[derive(Arbitrary, Debug, Display)] #[display("{0}")] enum Extension { Directory(DirectoryExtension), File(FileExtension), } fn merge_extensions(ext: impl ToString, exts: Vec) -> String { once(ext.to_string()).chain(exts.into_iter().map(|x| x.to_string())).collect::>().join(".") } fn create_random_files(dir: impl Into, depth: u8, rng: &mut SmallRng) { if depth == 0 { return; } let dir = &dir.into(); for _ in 0..rng.next_u32() % 8 { create_file_random(&mut tempfile::Builder::new().tempfile_in(dir).unwrap().keep().unwrap().0, rng); } for _ in 0..rng.next_u32() % 4 { create_random_files(&tempfile::tempdir_in(dir).unwrap().into_path(), depth - 1, rng); } } #[proptest(cases = 512)] fn single_empty_file(ext: Extension, #[any(size_range(0..8).lift())] exts: Vec) { let dir = tempdir().unwrap(); let dir = dir.path(); let before = &dir.join("before"); fs::create_dir(before).unwrap(); let before_file = &before.join("file"); let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts))); let after = &dir.join("after"); create_file_random(&mut fs::File::create(before_file).unwrap(), &mut SmallRng::from_entropy()); ouch!("c", before_file, archive); ouch!("d", archive, "-d", after); assert!(!dir_diff::is_different(before, after).unwrap()); } #[proptest(cases = 512)] fn single_file(ext: Extension, #[any(size_range(0..8).lift())] exts: Vec) { let dir = tempdir().unwrap(); let dir = dir.path(); let before = &dir.join("before"); fs::create_dir(before).unwrap(); let before_file = &before.join("file"); let archive = &dir.join(format!("file.{}", merge_extensions(ext, exts))); let after = &dir.join("after"); fs::write(before_file, []).unwrap(); ouch!("c", before_file, archive); ouch!("d", archive, "-d", after); assert!(!dir_diff::is_different(before, after).unwrap()); } #[proptest(cases = 512)] fn multiple_files( ext: DirectoryExtension, #[any(size_range(0..8).lift())] exts: Vec, #[strategy(0u8..4)] depth: u8, ) { let dir = tempdir().unwrap(); let dir = dir.path(); let before = &dir.join("before"); let before_dir = &before.join("dir"); fs::create_dir_all(before_dir).unwrap(); let archive = &dir.join(format!("archive.{}", merge_extensions(ext, exts))); let after = &dir.join("after"); create_random_files(before_dir, depth, &mut SmallRng::from_entropy()); ouch!("c", before_dir, archive); ouch!("d", archive, "-d", after); assert!(!dir_diff::is_different(before, after).unwrap()); }