From 6104142fb3940c91800ccd43d925591ffbcad81b Mon Sep 17 00:00:00 2001 From: funnyVOLT Date: Tue, 16 Jan 2024 00:06:36 +0300 Subject: [PATCH 1/3] make unit tests of update_one and update_all methord --- src/index.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 13 deletions(-) diff --git a/src/index.rs b/src/index.rs index 960253a..09ce69d 100644 --- a/src/index.rs +++ b/src/index.rs @@ -374,21 +374,23 @@ impl ResourceIndex { self.forget_path(canonical_path, old_id) } Ok(new_entry) => { + // valid resource exists by the path - let curr_entry = &self.path2id[canonical_path]; - - if curr_entry.id == new_entry.id { - // in rare cases we are here due to hash collision - - if curr_entry.modified == new_entry.modified { - log::warn!("path {:?} was modified but not its content", &canonical_path); + // in rare cases we are here due to hash collision + if let Some(curr_entry) = + self.path2id.get(canonical_path) + { + if curr_entry.id == new_entry.id { + // in rare cases we are here due to hash collision + if curr_entry.modified == new_entry.modified { + log::warn!("path {:?} was modified but not its content", &canonical_path); + } + // the caller must have ensured that the path was + // updated + return Err(ArklibError::Collision( + "New content has the same id".into(), + )); } - - // the caller must have ensured that the path was - // updated - return Err(ArklibError::Collision( - "New content has the same id".into(), - )); } // new resource exists by the path @@ -984,4 +986,84 @@ mod tests { assert!(new2 > old2); assert!(new2 > new1); } + + #[test] + fn should_correctly_update_one_resource() { + run_test_and_clean_up(|path| { + create_file_at(path.clone(), Some(FILE_SIZE_2), Some(FILE_NAME_2)); + let mut actual = ResourceIndex::build(path.clone()); + + println!("==🌹🌹=update_one unit tests start=="); + + for (key, value) in &actual.path2id { + println!( + "===❤❤========update_one_new_entry Resource ID: {}", + &actual.path2id[key].id + ); + } + + create_file_at(path.clone(), Some(FILE_SIZE_1), Some(FILE_NAME_1)); + let mut file_path = path.clone(); + file_path.push(FILE_NAME_1); + let old_id = ResourceId { + data_size: FILE_SIZE_1, + crc32: CRC32_1, + }; + let path_buf: CanonicalPathBuf = + CanonicalPathBuf::canonicalize(&file_path).unwrap(); + let update = actual + .update_one(&path_buf.clone(), old_id) + .expect("Should update one resource correctly"); + + for (key, value) in &actual.path2id { + println!( + "===😂😂========update_after_entry Resource ID: {}", + &actual.path2id[key].id + ); + } + + println!( + "===✔✔==added=:{} deleted={}",update.added.len().to_string(),update.deleted.len().to_string() + ); + + assert_eq!(update.added.len(), 1); + assert_eq!(actual.path2id.len(), 2); + }) + } + + #[test] + fn should_correctly_update_all_resource() { + run_test_and_clean_up(|path| { + create_file_at(path.clone(), Some(FILE_SIZE_2), Some(FILE_NAME_2)); + let mut actual = ResourceIndex::build(path.clone()); + + println!("==🌹🌹=update_all unit tests start=="); + for (key, value) in &actual.path2id { + println!( + "===❤❤========update_one_new_entry Resource ID: {}", + &actual.path2id[key].id + ); + } + + create_file_at(path.clone(), Some(FILE_SIZE_1), Some(FILE_NAME_1)); + + let update = actual + .update_all() + .expect("Should update index correctly"); + + for (key, value) in &actual.path2id { + println!( + "===😂😂========update_after_entry Resource ID: {}", + &actual.path2id[key].id + ); + } + + println!( + "===✔✔==added=:{} deleted={}",update.added.len().to_string(),update.deleted.len().to_string() + ); + + assert_eq!(update.deleted.len(), 0); + assert_eq!(update.added.len(), 1); + }) + } } From 30cb80abb296d1a0b71345224545601af975d38a Mon Sep 17 00:00:00 2001 From: funnyVOLT Date: Wed, 17 Jan 2024 20:27:12 +0300 Subject: [PATCH 2/3] function of 'update_all' implemented using 'update_one'. --- src/index.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 14 deletions(-) diff --git a/src/index.rs b/src/index.rs index 09ce69d..4fd67bb 100644 --- a/src/index.rs +++ b/src/index.rs @@ -352,6 +352,10 @@ impl ResourceIndex { return self.forget_id(old_id); } + let deleted: HashSet = HashSet::new(); + let added: HashMap = HashMap::new(); + let mut update = IndexUpdate { deleted, added }; + let canonical_path_buf = CanonicalPathBuf::canonicalize(path)?; let canonical_path = canonical_path_buf.as_canonical_path(); @@ -365,35 +369,42 @@ impl ResourceIndex { Err(_) => { // updating the index after resource removal is a correct // scenario - self.forget_path(canonical_path, old_id) + return self.forget_path(canonical_path, old_id); } Ok(metadata) => { match scan_entry(canonical_path, metadata) { Err(_) => { // a directory or empty file exists by the path - self.forget_path(canonical_path, old_id) + return self.forget_path(canonical_path, old_id); } Ok(new_entry) => { - - // valid resource exists by the path // in rare cases we are here due to hash collision if let Some(curr_entry) = self.path2id.get(canonical_path) { if curr_entry.id == new_entry.id { - // in rare cases we are here due to hash collision if curr_entry.modified == new_entry.modified { - log::warn!("path {:?} was modified but not its content", &canonical_path); + log::warn!("path {:?} does not modified but not its content", &canonical_path); + return Ok(update); } - // the caller must have ensured that the path was + + //in cases Resourceid' didn't modify and 'SystemTime' was modified // updated - return Err(ArklibError::Collision( - "New content has the same id".into(), - )); + log::warn!("Resourceid didn't modify but SystemTime was modified"); + // update.added.insert( + // canonical_path_buf.clone(), + // new_entry.id, + // ); + // self.insert_entry( + // canonical_path_buf.clone(), + // new_entry, + // ); + // update.deleted.insert(old_id); + return Ok(update); } } - // new resource exists by the path + //new resource exists by the path self.forget_path(canonical_path, old_id).map( |mut update| { update.added.insert( @@ -607,7 +618,7 @@ fn is_hidden(entry: &DirEntry) -> bool { #[cfg(test)] mod tests { use crate::id::ResourceId; - use crate::index::{discover_paths, IndexEntry}; + use crate::index::{discover_paths, scan_entries, IndexEntry}; use crate::initialize; use crate::ResourceIndex; use canonical_path::CanonicalPathBuf; @@ -621,6 +632,10 @@ mod tests { use std::time::SystemTime; use uuid::Uuid; + use std::collections::{HashMap, HashSet}; + type Paths = HashSet; + use walkdir::DirEntry; + const FILE_SIZE_1: u64 = 10; const FILE_SIZE_2: u64 = 11; @@ -1023,7 +1038,9 @@ mod tests { } println!( - "===✔✔==added=:{} deleted={}",update.added.len().to_string(),update.deleted.len().to_string() + "===✔✔==added=:{} deleted={}", + update.added.len().to_string(), + update.deleted.len().to_string() ); assert_eq!(update.added.len(), 1); @@ -1059,11 +1076,81 @@ mod tests { } println!( - "===✔✔==added=:{} deleted={}",update.added.len().to_string(),update.deleted.len().to_string() + "===✔✔==added=:{} deleted={}", + update.added.len().to_string(), + update.deleted.len().to_string() ); assert_eq!(update.deleted.len(), 0); assert_eq!(update.added.len(), 1); }) } + + #[test] + fn should_correctly_update_all_using_update_one_resource() { + run_test_and_clean_up(|path| { + create_file_at(path.clone(), Some(FILE_SIZE_2), Some(FILE_NAME_2)); + let mut actual = ResourceIndex::build(path.clone()); + + let mut all_deleted: HashSet = HashSet::new(); + let mut all_added: HashMap = + HashMap::new(); + + println!("==🌹🌹=update_all using update_one unit tests start=="); + for (key, value) in &actual.path2id { + println!( + "===❤❤========update_one_new_entry Resource ID: {}", + value.id + ); + } + + create_file_at(path.clone(), Some(FILE_SIZE_1), Some(FILE_NAME_1)); + + for (old_path, old_index_enry) in &actual.path2id { + let one_index_update = actual + .clone() + .update_one(&old_path.clone(), old_index_enry.id) + .expect("Should update one resource correctly"); + + for (add_path, &add_id) in one_index_update.added.iter() { + all_added.insert(add_path.clone(), add_id.clone()); + } + + for delete_id in one_index_update.deleted { + all_deleted.insert(delete_id); + } + } + + let curr_paths: HashMap = + discover_paths(path.clone()); + let curr_entries = scan_entries(curr_paths); + + for (cur_path, cur_entry) in curr_entries { + let one_index_update = actual + .update_one(&cur_path.clone(), cur_entry.id) + .expect("Should update one resource correctly"); + + for (add_path, &add_id) in one_index_update.added.iter() { + all_added.insert(add_path.clone(), add_id.clone()); + } + + for delete_id in one_index_update.deleted { + all_deleted.insert(delete_id); + } + } + + for (key, entry) in &actual.path2id { + println!( + "===😂😂========update_after_entry Resource ID: {}", + entry.id + ); + } + + println!( + "===✔✔==added=:{} deleted={}", + all_added.len().to_string(), + all_deleted.len().to_string() + ); + }) + } } From a05e2d0300aef3824b4b347b443d2f60e466165c Mon Sep 17 00:00:00 2001 From: funnyVOLT Date: Thu, 18 Jan 2024 18:43:55 +0300 Subject: [PATCH 3/3] make test update_all compare update_one --- src/index.rs | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/index.rs b/src/index.rs index 4fd67bb..afe5b14 100644 --- a/src/index.rs +++ b/src/index.rs @@ -30,7 +30,7 @@ pub struct ResourceIndex { root: PathBuf, } -#[derive(Debug)] +#[derive(PartialEq, Debug)] pub struct IndexUpdate { pub deleted: HashSet, pub added: HashMap, @@ -618,7 +618,7 @@ fn is_hidden(entry: &DirEntry) -> bool { #[cfg(test)] mod tests { use crate::id::ResourceId; - use crate::index::{discover_paths, scan_entries, IndexEntry}; + use crate::index::{discover_paths, scan_entries, IndexEntry, IndexUpdate}; use crate::initialize; use crate::ResourceIndex; use canonical_path::CanonicalPathBuf; @@ -646,6 +646,8 @@ mod tests { const CRC32_1: u32 = 3817498742; const CRC32_2: u32 = 1804055020; + use crate::{ArklibError, Result}; + fn get_temp_dir() -> PathBuf { create_dir_at(std::env::temp_dir()) } @@ -1153,4 +1155,46 @@ mod tests { ); }) } + + #[test] + fn should_correctly_update_all_compare_update_one_resource() { + run_test_and_clean_up(|path| { + create_file_at(path.clone(), Some(FILE_SIZE_2), Some(FILE_NAME_2)); + let mut actual = ResourceIndex::build(path.clone()); + create_file_at(path.clone(), Some(FILE_SIZE_1), Some(FILE_NAME_1)); + + let updated_using_update_all_result = actual.clone().update_all(); + + let mut all_deleted: HashSet = HashSet::new(); + let mut all_added: HashMap = + HashMap::new(); + + let curr_paths: HashMap = + discover_paths(path.clone()); + let curr_entries = scan_entries(curr_paths); + + for (cur_path, cur_entry) in curr_entries { + let one_index_update = actual + .update_one(&cur_path.clone(), cur_entry.id) + .expect("Should update one resource correctly"); + + for (add_path, &add_id) in one_index_update.added.iter() { + all_added.insert(add_path.clone(), add_id.clone()); + } + + for delete_id in one_index_update.deleted { + all_deleted.insert(delete_id); + } + } + + let updated_using_update_one = IndexUpdate { + deleted: all_deleted, + added: all_added, + }; + let updated_using_update_all = + updated_using_update_all_result.unwrap(); + + assert_eq!(updated_using_update_all, updated_using_update_one); + }) + } }