From 36125d51350a4cd560f68d2248f339b0f5753fd9 Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Fri, 20 Feb 2026 15:30:57 -0600 Subject: [PATCH 1/4] test(drive): add error path tests for document insert/update/delete operations --- .../rs-drive/src/drive/document/delete/mod.rs | 34 +++++++++ .../rs-drive/src/drive/document/insert/mod.rs | 72 +++++++++++++++++++ .../rs-drive/src/drive/document/update/mod.rs | 49 +++++++++++++ 3 files changed, 155 insertions(+) diff --git a/packages/rs-drive/src/drive/document/delete/mod.rs b/packages/rs-drive/src/drive/document/delete/mod.rs index 159cdd41a70..e6e76c513ab 100644 --- a/packages/rs-drive/src/drive/document/delete/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/mod.rs @@ -61,6 +61,8 @@ mod tests { use crate::config::DriveConfig; use crate::drive::document::tests::setup_dashpay; use crate::drive::Drive; + use crate::error::drive::DriveError; + use crate::error::Error; use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use crate::util::storage_flags::StorageFlags; @@ -74,6 +76,7 @@ mod tests { use dpp::document::Document; use dpp::fee::default_costs::KnownCostItem::StorageDiskUsageCreditPerByte; use dpp::fee::default_costs::{CachedEpochIndexFeeVersions, EpochCosts}; + use dpp::identifier::Identifier; use dpp::tests::json_document::{json_document_to_contract, json_document_to_document}; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; @@ -184,6 +187,37 @@ mod tests { assert_eq!(results_on_transaction.len(), 0); } + #[test] + fn test_delete_nonexistent_document_returns_error() { + let (drive, contract) = setup_dashpay("delete-nonexistent", true); + + let platform_version = PlatformVersion::latest(); + + let document_id = Identifier::random(); + + let err = drive + .delete_document_for_contract( + document_id, + &contract, + "profile", + BlockInfo::default(), + true, + None, + platform_version, + Some(&EPOCH_CHANGE_FEE_VERSION_TEST), + ) + .expect_err("expected deleting a nonexistent document to fail"); + + assert!(matches!( + err, + Error::Drive(DriveError::DeletingDocumentThatDoesNotExist(_)) + ) || matches!( + err, + Error::GroveDB(ref grovedb_error) + if matches!(grovedb_error.as_ref(), grovedb::Error::PathKeyNotFound(_)) + )); + } + #[test] fn test_add_and_remove_family_one_document() { let drive = setup_drive_with_initial_state_structure(None); diff --git a/packages/rs-drive/src/drive/document/insert/mod.rs b/packages/rs-drive/src/drive/document/insert/mod.rs index 9b430e8a85b..2136fb432a7 100644 --- a/packages/rs-drive/src/drive/document/insert/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/mod.rs @@ -62,6 +62,8 @@ mod tests { use dpp::tests::json_document::json_document_to_document; use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; + use crate::error::drive::DriveError; + use crate::error::Error; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); @@ -153,6 +155,76 @@ mod tests { .expect("expected to override a document successfully"); } + #[test] + fn test_add_dashpay_document_duplicate_insert_returns_error() { + let (drive, dashpay) = setup_dashpay("add-duplicate-error", true); + + let random_owner_id = rand::thread_rng().gen::<[u8; 32]>(); + + let platform_version = PlatformVersion::first(); + + let document_type = dashpay + .document_type_for_name("contactRequest") + .expect("expected to get document type"); + + let dashpay_cr_document = json_document_to_document( + "tests/supporting_files/contract/dashpay/contact-request0.json", + Some(random_owner_id.into()), + document_type, + platform_version, + ) + .expect("expected to get cbor document"); + + drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo(( + &dashpay_cr_document, + StorageFlags::optional_default_as_cow(), + )), + owner_id: Some(random_owner_id), + }, + contract: &dashpay, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + None, + ) + .expect("expected to insert a document successfully"); + + let err = drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo(( + &dashpay_cr_document, + StorageFlags::optional_default_as_cow(), + )), + owner_id: Some(random_owner_id), + }, + contract: &dashpay, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + None, + ) + .expect_err("expected duplicate insert to return an error"); + + assert!(matches!( + err, + Error::Drive(DriveError::CorruptedDocumentAlreadyExists(_)) + )); + } + #[test] fn test_add_dashpay_documents() { let drive = setup_drive_with_initial_state_structure(None); diff --git a/packages/rs-drive/src/drive/document/update/mod.rs b/packages/rs-drive/src/drive/document/update/mod.rs index 2d52d89c1ee..522e40effbd 100644 --- a/packages/rs-drive/src/drive/document/update/mod.rs +++ b/packages/rs-drive/src/drive/document/update/mod.rs @@ -43,6 +43,8 @@ mod tests { use crate::config::DriveConfig; use crate::drive::Drive; + use crate::error::drive::DriveError; + use crate::error::Error; use crate::util::object_size_info::DocumentInfo::{DocumentOwnedInfo, DocumentRefInfo}; use crate::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use crate::util::storage_flags::StorageFlags; @@ -249,6 +251,53 @@ mod tests { assert_eq!(results_no_transaction.len(), 1); } + #[test] + fn test_update_nonexistent_document_returns_error() { + let (drive, contract) = setup_dashpay("update-nonexistent", true); + + let platform_version = PlatformVersion::latest(); + + let document_type = contract + .document_type_for_name("contactRequest") + .expect("contactRequest document exists"); + + let owner_id = random::<[u8; 32]>(); + + let document = json_document_to_document( + "tests/supporting_files/contract/dashpay/contact-request0.json", + Some(owner_id.into()), + document_type, + platform_version, + ) + .expect("expected to get cbor document"); + + let err = drive + .update_document_for_contract( + &document, + &contract, + document_type, + Some(owner_id), + BlockInfo::default(), + true, + StorageFlags::optional_default_as_cow(), + None, + platform_version, + Some(&EPOCH_CHANGE_FEE_VERSION_TEST), + ) + .expect_err("expected updating a nonexistent document to fail"); + + assert!( + matches!( + err, + Error::Drive(DriveError::UpdatingDocumentThatDoesNotExist(_)) + ) || matches!( + err, + Error::GroveDB(ref grovedb_error) + if matches!(grovedb_error.as_ref(), grovedb::Error::PathKeyNotFound(_)) + ) + ); + } + #[test] fn test_create_and_update_document_in_different_transactions() { let (drive, contract) = setup_dashpay("", true); From 3cd3d8676ac487495b7d77191f8db3734afb8340 Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Fri, 20 Feb 2026 15:31:00 -0600 Subject: [PATCH 2/4] test(drive): add cache lifecycle tests for DataContractCache --- packages/rs-drive/src/cache/data_contract.rs | 124 ++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/packages/rs-drive/src/cache/data_contract.rs b/packages/rs-drive/src/cache/data_contract.rs index cdedae6b39f..a02b64ad80a 100644 --- a/packages/rs-drive/src/cache/data_contract.rs +++ b/packages/rs-drive/src/cache/data_contract.rs @@ -77,11 +77,11 @@ impl DataContractCache { #[cfg(test)] mod tests { use super::*; + use dpp::version::PlatformVersion; mod get { use super::*; use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; - use dpp::version::PlatformVersion; #[test] fn test_get_from_global_cache_when_block_cache_is_not_requested() { @@ -165,4 +165,126 @@ mod tests { assert_eq!(fetch_info_from_cache, fetch_info_block) } } + + mod insert { + use super::*; + + #[test] + fn test_insert_into_global_cache() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info.contract.id().to_buffer(); + + data_contract_cache.insert(Arc::clone(&fetch_info), false); + + let from_cache = data_contract_cache.get(contract_id, false); + assert_eq!(from_cache, Some(fetch_info)); + } + + #[test] + fn test_insert_into_block_cache() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info.contract.id().to_buffer(); + + data_contract_cache.insert(Arc::clone(&fetch_info), true); + + let from_cache = data_contract_cache.get(contract_id, true); + assert_eq!(from_cache, Some(fetch_info)); + } + } + + mod remove { + use super::*; + + #[test] + fn test_remove_clears_global_cache_entry() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info.contract.id().to_buffer(); + + data_contract_cache.insert(fetch_info, false); + data_contract_cache.remove(contract_id); + + assert!(data_contract_cache.get(contract_id, false).is_none()); + } + + #[test] + fn test_remove_clears_entry_from_both_caches() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info_global = + Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info_global.contract.id().to_buffer(); + let fetch_info_block = Arc::clone(&fetch_info_global); + + data_contract_cache.insert(fetch_info_global, false); + data_contract_cache.insert(fetch_info_block, true); + data_contract_cache.remove(contract_id); + + assert!(data_contract_cache.block_cache.get(&contract_id).is_none()); + assert!(data_contract_cache.global_cache.get(&contract_id).is_none()); + } + } + + mod merge_and_clear_block_cache { + use super::*; + + #[test] + fn test_merge_moves_block_items_to_global_cache() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info.contract.id().to_buffer(); + + data_contract_cache.insert(fetch_info, true); + data_contract_cache.merge_and_clear_block_cache(); + + assert!(data_contract_cache.global_cache.get(&contract_id).is_some()); + } + + #[test] + fn test_merge_clears_block_cache() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info.contract.id().to_buffer(); + + data_contract_cache.insert(fetch_info, true); + data_contract_cache.merge_and_clear_block_cache(); + + assert!(data_contract_cache.block_cache.get(&contract_id).is_none()); + } + } + + mod clear { + use super::*; + + #[test] + fn test_clear_empties_global_and_block_caches() { + let data_contract_cache = DataContractCache::new(10, 10); + + let protocol_version = PlatformVersion::latest().protocol_version; + let fetch_info_global = + Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let contract_id = fetch_info_global.contract.id().to_buffer(); + let fetch_info_block = Arc::clone(&fetch_info_global); + + data_contract_cache.insert(fetch_info_global, false); + data_contract_cache.insert(fetch_info_block, true); + data_contract_cache.clear(); + + assert!(data_contract_cache.get(contract_id, false).is_none()); + assert!(data_contract_cache.block_cache.get(&contract_id).is_none()); + } + } } From 940aedb7827578d61dd62191af71655b725d6fe8 Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Sat, 21 Feb 2026 13:27:49 -0600 Subject: [PATCH 3/4] style(drive): apply cargo fmt --- packages/rs-drive/src/cache/data_contract.rs | 30 +++++++++++++------ .../rs-drive/src/drive/document/delete/mod.rs | 18 ++++++----- .../rs-drive/src/drive/document/insert/mod.rs | 4 +-- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/packages/rs-drive/src/cache/data_contract.rs b/packages/rs-drive/src/cache/data_contract.rs index a02b64ad80a..0a752aadb1d 100644 --- a/packages/rs-drive/src/cache/data_contract.rs +++ b/packages/rs-drive/src/cache/data_contract.rs @@ -174,7 +174,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info.contract.id().to_buffer(); data_contract_cache.insert(Arc::clone(&fetch_info), false); @@ -188,7 +190,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info.contract.id().to_buffer(); data_contract_cache.insert(Arc::clone(&fetch_info), true); @@ -206,7 +210,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info.contract.id().to_buffer(); data_contract_cache.insert(fetch_info, false); @@ -220,8 +226,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info_global = - Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info_global = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info_global.contract.id().to_buffer(); let fetch_info_block = Arc::clone(&fetch_info_global); @@ -242,7 +249,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info.contract.id().to_buffer(); data_contract_cache.insert(fetch_info, true); @@ -256,7 +265,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info.contract.id().to_buffer(); data_contract_cache.insert(fetch_info, true); @@ -274,8 +285,9 @@ mod tests { let data_contract_cache = DataContractCache::new(10, 10); let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info_global = - Arc::new(DataContractFetchInfo::dpns_contract_fixture(protocol_version)); + let fetch_info_global = Arc::new(DataContractFetchInfo::dpns_contract_fixture( + protocol_version, + )); let contract_id = fetch_info_global.contract.id().to_buffer(); let fetch_info_block = Arc::clone(&fetch_info_global); diff --git a/packages/rs-drive/src/drive/document/delete/mod.rs b/packages/rs-drive/src/drive/document/delete/mod.rs index e6e76c513ab..2e658677a1d 100644 --- a/packages/rs-drive/src/drive/document/delete/mod.rs +++ b/packages/rs-drive/src/drive/document/delete/mod.rs @@ -208,14 +208,16 @@ mod tests { ) .expect_err("expected deleting a nonexistent document to fail"); - assert!(matches!( - err, - Error::Drive(DriveError::DeletingDocumentThatDoesNotExist(_)) - ) || matches!( - err, - Error::GroveDB(ref grovedb_error) - if matches!(grovedb_error.as_ref(), grovedb::Error::PathKeyNotFound(_)) - )); + assert!( + matches!( + err, + Error::Drive(DriveError::DeletingDocumentThatDoesNotExist(_)) + ) || matches!( + err, + Error::GroveDB(ref grovedb_error) + if matches!(grovedb_error.as_ref(), grovedb::Error::PathKeyNotFound(_)) + ) + ); } #[test] diff --git a/packages/rs-drive/src/drive/document/insert/mod.rs b/packages/rs-drive/src/drive/document/insert/mod.rs index 2136fb432a7..144af1a1d44 100644 --- a/packages/rs-drive/src/drive/document/insert/mod.rs +++ b/packages/rs-drive/src/drive/document/insert/mod.rs @@ -51,6 +51,8 @@ mod tests { use once_cell::sync::Lazy; use std::collections::BTreeMap; + use crate::error::drive::DriveError; + use crate::error::Error; use crate::util::object_size_info::DocumentInfo::DocumentRefInfo; use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; use dpp::block::epoch::Epoch; @@ -62,8 +64,6 @@ mod tests { use dpp::tests::json_document::json_document_to_document; use dpp::version::fee::FeeVersion; use dpp::version::PlatformVersion; - use crate::error::drive::DriveError; - use crate::error::Error; static EPOCH_CHANGE_FEE_VERSION_TEST: Lazy = Lazy::new(|| BTreeMap::from([(0, FeeVersion::first())])); From e829157af05a9264196553087b9e61004a1597be Mon Sep 17 00:00:00 2001 From: PastaClaw Date: Mon, 23 Feb 2026 16:49:23 -0600 Subject: [PATCH 4/4] test(drive): remove redundant insert cache tests --- packages/rs-drive/src/cache/data_contract.rs | 36 -------------------- 1 file changed, 36 deletions(-) diff --git a/packages/rs-drive/src/cache/data_contract.rs b/packages/rs-drive/src/cache/data_contract.rs index 0a752aadb1d..f3dbbf3479d 100644 --- a/packages/rs-drive/src/cache/data_contract.rs +++ b/packages/rs-drive/src/cache/data_contract.rs @@ -166,42 +166,6 @@ mod tests { } } - mod insert { - use super::*; - - #[test] - fn test_insert_into_global_cache() { - let data_contract_cache = DataContractCache::new(10, 10); - - let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( - protocol_version, - )); - let contract_id = fetch_info.contract.id().to_buffer(); - - data_contract_cache.insert(Arc::clone(&fetch_info), false); - - let from_cache = data_contract_cache.get(contract_id, false); - assert_eq!(from_cache, Some(fetch_info)); - } - - #[test] - fn test_insert_into_block_cache() { - let data_contract_cache = DataContractCache::new(10, 10); - - let protocol_version = PlatformVersion::latest().protocol_version; - let fetch_info = Arc::new(DataContractFetchInfo::dpns_contract_fixture( - protocol_version, - )); - let contract_id = fetch_info.contract.id().to_buffer(); - - data_contract_cache.insert(Arc::clone(&fetch_info), true); - - let from_cache = data_contract_cache.get(contract_id, true); - assert_eq!(from_cache, Some(fetch_info)); - } - } - mod remove { use super::*;