diff --git a/libparsec/crates/client/tests/unit/workspace/resolve_path.rs b/libparsec/crates/client/tests/unit/workspace/resolve_path.rs index 5a770dcc651..fea526836c8 100644 --- a/libparsec/crates/client/tests/unit/workspace/resolve_path.rs +++ b/libparsec/crates/client/tests/unit/workspace/resolve_path.rs @@ -115,13 +115,13 @@ async fn inconsistent_path_parent_mismatch( let wksp1_bar_txt_id: VlobID = *env.template.get_stuff("wksp1_bar_txt_id"); let wksp1_foo_id: VlobID = *env.template.get_stuff("wksp1_foo_id"); let (patched_parent_id, expected_error) = match kind { - "other_entry" => (wksp1_foo_id, ResolvePathError::EntryNotFound), + "other_entry" => (wksp1_bar_txt_id, ResolvePathError::EntryNotFound), "self_referencing" => ( - wksp1_bar_txt_id, + wksp1_foo_id, ResolvePathError::Internal( DataError::DataIntegrity { - data_type: "libparsec_types::local_manifest::LocalFileManifest", - invariant: "id and parent are different", + data_type: "libparsec_types::local_manifest::LocalFolderManifest", + invariant: "id and parent are different for child manifest", } .into(), ), @@ -130,10 +130,10 @@ async fn inconsistent_path_parent_mismatch( }; env.customize(|builder| { builder - .workspace_data_storage_local_file_manifest_create_or_update( + .workspace_data_storage_local_folder_manifest_create_or_update( "alice@dev1", wksp1_id, - wksp1_bar_txt_id, + wksp1_foo_id, None, ) .customize(|x| { @@ -148,7 +148,7 @@ async fn inconsistent_path_parent_mismatch( let err = ops .store - .resolve_path(&"/bar.txt".parse().unwrap()) + .resolve_path(&"/foo".parse().unwrap()) .await .unwrap_err(); diff --git a/libparsec/crates/types/src/local_manifest.rs b/libparsec/crates/types/src/local_manifest.rs index ecc0fe7b8fa..5526862c1c8 100644 --- a/libparsec/crates/types/src/local_manifest.rs +++ b/libparsec/crates/types/src/local_manifest.rs @@ -23,6 +23,7 @@ macro_rules! impl_local_manifest_dump { ($name:ident) => { impl $name { pub fn dump_and_encrypt(&self, key: &SecretKey) -> Vec { + self.check_data_integrity().expect("Manifest integrity"); let serialized = format_v0_dump(&self); key.encrypt(&serialized) } @@ -586,7 +587,22 @@ impl LocalFolderManifest { } } + /// A note about this method being public: + /// This structure represents mutable data (it gets loaded from disk, updated, then stored back modified) + /// Hence this `check_data_integrity`'s main goal is during deserialization. + /// However it is also useful as sanity check: + /// - Right before serialization + /// - After any modification (hence the need for this method to be public) + /// + /// Note that this method does not perform data integrity check related to the manifest being a + /// child or root manifest. + pub fn check_data_integrity(&self) -> DataResult<()> { + Ok(()) + } + fn check_data_integrity_as_child(&self) -> DataResult<()> { + self.check_data_integrity()?; + // Check that id and parent are different if self.base.id == self.parent { return Err(DataError::DataIntegrity { @@ -598,6 +614,8 @@ impl LocalFolderManifest { } fn check_data_integrity_as_root(&self) -> DataResult<()> { + self.check_data_integrity()?; + // Check that id and parent are the same if self.base.id != self.parent { return Err(DataError::DataIntegrity {