duplicates testing uses proptest now
This commit is contained in:
parent
ee13dd22be
commit
6629977515
6 changed files with 198 additions and 38 deletions
99
Cargo.lock
generated
99
Cargo.lock
generated
|
@ -37,6 +37,7 @@ dependencies = [
|
|||
"hex",
|
||||
"log",
|
||||
"nix 0.19.0",
|
||||
"proptest",
|
||||
"rand 0.7.3",
|
||||
"rayon",
|
||||
"rust-crypto",
|
||||
|
@ -56,6 +57,21 @@ version = "0.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -77,6 +93,12 @@ version = "3.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cargo-husky"
|
||||
version = "1.5.0"
|
||||
|
@ -191,6 +213,12 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "fs2"
|
||||
version = "0.4.3"
|
||||
|
@ -331,6 +359,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
|
@ -362,6 +399,32 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12e6c80c1139113c28ee4670dc50cc42915228b51f56a9e407f0ec60f966646f"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"num-traits",
|
||||
"quick-error",
|
||||
"rand 0.7.3",
|
||||
"rand_chacha",
|
||||
"rand_xorshift",
|
||||
"regex-syntax",
|
||||
"rusty-fork",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.7"
|
||||
|
@ -450,6 +513,15 @@ dependencies = [
|
|||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.0"
|
||||
|
@ -490,6 +562,12 @@ version = "0.1.57"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
@ -518,6 +596,18 @@ version = "0.3.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
|
||||
[[package]]
|
||||
name = "rusty-fork"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"quick-error",
|
||||
"tempfile",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
|
@ -692,6 +782,15 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.1"
|
||||
|
|
|
@ -27,6 +27,9 @@ thiserror = "1.0"
|
|||
uuid = { version = "0.8", features = ["v4"] }
|
||||
walkdir = "2.3"
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "0.10"
|
||||
|
||||
[dev-dependencies.cargo-husky]
|
||||
version = "1"
|
||||
default-features = false
|
||||
|
|
|
@ -168,3 +168,36 @@ impl<'a> Repository<'a> {
|
|||
Ok(hasher.finalize()[..].into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod must {
|
||||
use super::Repository;
|
||||
use crate::test::source::TempSource;
|
||||
use anyhow::Result;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
fn have_size_equal_to_sum_of_sizes_of_backed_up_files() -> Result<()> {
|
||||
let source = TempSource::new().unwrap();
|
||||
let repository_path = tempdir().unwrap().into_path();
|
||||
Repository::init(&repository_path)?;
|
||||
|
||||
let file_size1 = 13;
|
||||
let file_size2 = 27;
|
||||
|
||||
let mut backup_repository = Repository::open(&repository_path)?;
|
||||
source.write_random_bytes_to_file("file1", file_size1)?;
|
||||
backup_repository.store(&source.file_path("file1"))?;
|
||||
|
||||
source.write_random_bytes_to_file("file2", file_size2)?;
|
||||
backup_repository.store(&source.file_path("file2"))?;
|
||||
|
||||
assert_eq!((file_size1 + file_size2) as u64, backup_repository.data_weight()?);
|
||||
|
||||
backup_repository.save_index()?;
|
||||
|
||||
assert_eq!((file_size1 + file_size2) as u64, backup_repository.data_weight()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,17 @@ pub fn assert_same_after_restore(source_path: &Path) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn assert_restored_file_contents(repository_path: &Path, source_file_full_path: &Path, contents: &str) -> Result<()> {
|
||||
pub fn assert_restored_file_contents(repository_path: &Path, source_file_full_path: &Path, contents: &[u8]) -> Result<()> {
|
||||
let mut restore_repository = Repository::open(repository_path)?;
|
||||
let item = restore_repository.newest_item_by_source_path(&source_file_full_path)?;
|
||||
let restore_target = tempdir().unwrap();
|
||||
let restore_engine = restore::Engine::new(&mut restore_repository, &restore_target.path())?;
|
||||
|
||||
restore_engine.restore(&item.unwrap())?;
|
||||
let restored_file_path = restore_target.path().join(source_file_full_path.strip_prefix("/")?);
|
||||
assert_target_file_contents(&restored_file_path, contents)
|
||||
}
|
||||
pub fn assert_restored_file_byte_contents(repository_path: &Path, source_file_full_path: &Path, contents: &[u8]) -> Result<()> {
|
||||
let mut restore_repository = Repository::open(repository_path)?;
|
||||
let item = restore_repository.newest_item_by_source_path(&source_file_full_path)?;
|
||||
let restore_target = tempdir().unwrap();
|
||||
|
@ -47,7 +57,7 @@ pub fn assert_restored_file_contents(repository_path: &Path, source_file_full_pa
|
|||
pub fn assert_restored_from_version_has_contents(
|
||||
repository_path: &Path,
|
||||
source_file_full_path: &Path,
|
||||
old_contents: &str,
|
||||
old_contents: &[u8],
|
||||
old_id: &ItemId,
|
||||
) -> Result<()> {
|
||||
let mut restore_repository = Repository::open(repository_path)?;
|
||||
|
@ -78,16 +88,27 @@ pub fn restore_all_from_reloaded_repository(repository_path: &Path, restore_targ
|
|||
}
|
||||
}
|
||||
|
||||
pub fn backup_file_with_contents(
|
||||
pub fn backup_file_with_text_contents(
|
||||
source: &TempSource,
|
||||
repository_path: &Path,
|
||||
source_file_relative_path: &str,
|
||||
contents: &str,
|
||||
) -> Result<()> {
|
||||
{
|
||||
backup_file_with_byte_contents(source, repository_path, source_file_relative_path, contents.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backup_file_with_byte_contents(
|
||||
source: &TempSource,
|
||||
repository_path: &Path,
|
||||
source_file_relative_path: &str,
|
||||
contents: &[u8],
|
||||
) -> Result<()> {
|
||||
{
|
||||
let mut backup_repository = Repository::open(repository_path)?;
|
||||
let mut backup_engine = backup::Engine::new(source.path(), &mut backup_repository)?;
|
||||
source.write_text_to_file(source_file_relative_path, contents).unwrap();
|
||||
source.write_bytes_to_file(source_file_relative_path, contents).unwrap();
|
||||
backup_engine.backup()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -136,13 +157,10 @@ pub fn get_sorted_files_recursively<T: AsRef<Path>>(path: T) -> Result<Vec<Box<P
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
fn assert_target_file_contents(restored_path: &Path, expected_contents: &str) -> Result<()> {
|
||||
let mut actual_contents = String::new();
|
||||
fn assert_target_file_contents(restored_path: &Path, expected_contents: &[u8]) -> Result<()> {
|
||||
let mut actual_contents = vec![];
|
||||
assert!(restored_path.exists(), "Expected '{}' to be there", restored_path.display());
|
||||
File::open(restored_path)
|
||||
.unwrap()
|
||||
.read_to_string(&mut actual_contents)
|
||||
.unwrap();
|
||||
File::open(restored_path)?.read_to_end(&mut actual_contents)?;
|
||||
assert_eq!(expected_contents, actual_contents);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -25,6 +25,12 @@ impl TempSource {
|
|||
self.write_bytes_to_file(filename, text.as_bytes())
|
||||
}
|
||||
|
||||
pub fn write_random_bytes_to_file(&self, filename: &str, size: usize) -> Result<(), Error> {
|
||||
let random_bytes: Vec<u8> = (0..size).map(|_| rand::random::<u8>()).collect();
|
||||
self.write_bytes_to_file(filename, &random_bytes)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &Path {
|
||||
self.directory.path()
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ use bakare::backup;
|
|||
use bakare::repository::Repository;
|
||||
use bakare::test::{assertions::*, source::TempSource};
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn restore_multiple_files() -> Result<()> {
|
||||
let source = TempSource::new().unwrap();
|
||||
|
@ -26,12 +28,12 @@ fn restore_files_after_reopening_repository() -> Result<()> {
|
|||
let source_file_relative_path = "some file path";
|
||||
let original_contents = "some old contents";
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, original_contents)?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, original_contents)?;
|
||||
|
||||
restore_all_from_reloaded_repository(&repository_path, &restore_target)?;
|
||||
|
||||
let source_file_full_path = &source.file_path(source_file_relative_path);
|
||||
assert_restored_file_contents(repository_path, source_file_full_path, original_contents)
|
||||
assert_restored_file_contents(repository_path, source_file_full_path, original_contents.as_bytes())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -44,15 +46,15 @@ fn restore_older_version_of_file() -> Result<()> {
|
|||
let source_file_full_path = source.file_path(source_file_relative_path);
|
||||
let old_contents = "some old contents";
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, old_contents)?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, old_contents)?;
|
||||
|
||||
let old_item = newest_item(&repository_path, &source_file_full_path)?;
|
||||
let old_id = old_item.id();
|
||||
|
||||
let new_contents = "totally new contents";
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, new_contents)?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, new_contents)?;
|
||||
|
||||
assert_restored_from_version_has_contents(&repository_path, &source_file_full_path, old_contents, &old_id)
|
||||
assert_restored_from_version_has_contents(&repository_path, &source_file_full_path, old_contents.as_bytes(), &old_id)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -64,12 +66,12 @@ fn newer_version_should_be_greater_than_earlier_version() -> Result<()> {
|
|||
let source_file_relative_path = "some path";
|
||||
let source_file_full_path = source.file_path(source_file_relative_path);
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, "old")?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, "old")?;
|
||||
|
||||
let old_item = newest_item(&repository_path, &source_file_full_path)?;
|
||||
let old_version = old_item.version();
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, "new")?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, "new")?;
|
||||
|
||||
let new_item = newest_item(&repository_path, &source_file_full_path)?;
|
||||
let new_version = new_item.version();
|
||||
|
@ -79,26 +81,25 @@ fn newer_version_should_be_greater_than_earlier_version() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn store_duplicated_files_just_once() -> Result<()> {
|
||||
fn store_duplicated_files_just_once(contents in any::<[u8;3]>()) {
|
||||
let source = TempSource::new().unwrap();
|
||||
let repository_path = &tempdir().unwrap().into_path();
|
||||
Repository::init(repository_path)?;
|
||||
assert_eq!(data_weight(&repository_path)?, 0);
|
||||
Repository::init(repository_path).unwrap();
|
||||
assert_eq!(data_weight(&repository_path).unwrap(), 0);
|
||||
|
||||
let contents = "some contents";
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, "1", contents)?;
|
||||
let first_weight = data_weight(&repository_path)?;
|
||||
backup_file_with_byte_contents(&source, &repository_path, "1", &contents).unwrap();
|
||||
let first_weight = data_weight(&repository_path).unwrap();
|
||||
assert!(first_weight > 0);
|
||||
|
||||
backup_file_with_contents(&source, &repository_path, "2", contents)?;
|
||||
let second_weight = data_weight(&repository_path)?;
|
||||
backup_file_with_byte_contents(&source, &repository_path, "2", &contents).unwrap();
|
||||
let second_weight = data_weight(&repository_path).unwrap();
|
||||
assert_eq!(first_weight, second_weight);
|
||||
|
||||
assert_restored_file_contents(repository_path, &source.file_path("1"), contents)?;
|
||||
assert_restored_file_contents(repository_path, &source.file_path("2"), contents)?;
|
||||
Ok(())
|
||||
assert_restored_file_contents(repository_path, &source.file_path("1"), &contents).unwrap();
|
||||
assert_restored_file_contents(repository_path, &source.file_path("2"), &contents).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -108,12 +109,12 @@ fn restore_latest_version_by_default() -> Result<()> {
|
|||
Repository::init(repository_path)?;
|
||||
|
||||
let source_file_relative_path = "some path";
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, "old contents")?;
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, "newer contents")?;
|
||||
backup_file_with_contents(&source, &repository_path, source_file_relative_path, "newest contents")?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, "old contents")?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, "newer contents")?;
|
||||
backup_file_with_text_contents(&source, &repository_path, source_file_relative_path, "newest contents")?;
|
||||
|
||||
let source_file_full_path = &source.file_path(source_file_relative_path);
|
||||
assert_restored_file_contents(repository_path, source_file_full_path, "newest contents")
|
||||
assert_restored_file_contents(repository_path, source_file_full_path, "newest contents".as_bytes())
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue