-
Notifications
You must be signed in to change notification settings - Fork 54
test(drive): improve identity module test coverage #3330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,237 @@ | ||
| mod fetch_identity_balance; | ||
| mod fetch_identity_balance_include_debt; | ||
| mod fetch_identity_negative_balance; | ||
|
|
||
| #[cfg(feature = "server")] | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; | ||
| use crate::util::test_helpers::test_utils::identities::create_test_identity; | ||
| use dpp::block::block_info::BlockInfo; | ||
| use dpp::identity::accessors::IdentityGettersV0; | ||
| use dpp::identity::Identity; | ||
| use dpp::version::PlatformVersion; | ||
|
|
||
| mod fetch_identity_balance { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn should_return_none_for_non_existent_identity() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let balance = drive | ||
| .fetch_identity_balance([0; 32], None, platform_version) | ||
| .expect("should not error"); | ||
|
|
||
| assert!(balance.is_none()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn should_return_balance_for_existing_identity() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let identity = Identity::random_identity(3, Some(42), platform_version) | ||
| .expect("expected a random identity"); | ||
|
|
||
| let expected_balance = identity.balance(); | ||
|
|
||
| drive | ||
| .add_new_identity( | ||
| identity.clone(), | ||
| false, | ||
| &BlockInfo::default(), | ||
| true, | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("expected to add identity"); | ||
|
|
||
| let balance = drive | ||
| .fetch_identity_balance(identity.id().to_buffer(), None, platform_version) | ||
| .expect("should not error") | ||
| .expect("should have balance"); | ||
|
|
||
| assert_eq!(balance, expected_balance); | ||
| } | ||
|
|
||
| #[test] | ||
| fn should_return_balance_with_costs_estimated() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let identity = Identity::random_identity(3, Some(42), platform_version) | ||
| .expect("expected a random identity"); | ||
|
|
||
| drive | ||
| .add_new_identity( | ||
| identity.clone(), | ||
| false, | ||
| &BlockInfo::default(), | ||
| true, | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("expected to add identity"); | ||
|
|
||
| let block_info = BlockInfo::default(); | ||
|
|
||
| // Estimated mode (apply=false) | ||
| let (balance, fee_result) = drive | ||
| .fetch_identity_balance_with_costs( | ||
| identity.id().to_buffer(), | ||
| &block_info, | ||
| false, | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("should return balance with costs"); | ||
|
|
||
| // In estimated (stateless) mode, the balance query does not read | ||
| // from the database. It returns Some(0) as a placeholder value | ||
| // while computing estimated costs. | ||
| assert!(fee_result.processing_fee > 0); | ||
| assert_eq!(balance, Some(0)); | ||
| } | ||
| } | ||
|
|
||
| mod fetch_identity_balance_include_debt { | ||
| use super::*; | ||
| use crate::fees::op::LowLevelDriveOperation; | ||
|
|
||
| #[test] | ||
| fn should_return_none_for_non_existent_identity() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let balance = drive | ||
| .fetch_identity_balance_include_debt([0; 32], None, platform_version) | ||
| .expect("should not error"); | ||
|
|
||
| assert!(balance.is_none()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn should_return_positive_balance_for_identity_with_funds() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let identity = create_test_identity(&drive, [0; 32], Some(1), None, platform_version) | ||
| .expect("expected an identity"); | ||
|
|
||
| let added_balance = 1000; | ||
|
|
||
| drive | ||
| .add_to_identity_balance( | ||
| identity.id().to_buffer(), | ||
| added_balance, | ||
| &BlockInfo::default(), | ||
| true, | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("should add balance"); | ||
|
|
||
| let balance = drive | ||
| .fetch_identity_balance_include_debt( | ||
| identity.id().to_buffer(), | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("should not error") | ||
| .expect("should have balance"); | ||
|
|
||
| assert_eq!(balance, added_balance as i64); | ||
| } | ||
|
|
||
| #[test] | ||
| fn should_return_negative_balance_for_identity_with_debt() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let identity = create_test_identity(&drive, [0; 32], Some(1), None, platform_version) | ||
| .expect("expected an identity"); | ||
|
|
||
| let negative_amount: u64 = 500; | ||
|
|
||
| // Set negative balance (debt) | ||
| let batch = vec![drive | ||
| .update_identity_negative_credit_operation( | ||
| identity.id().to_buffer(), | ||
| negative_amount, | ||
| platform_version, | ||
| ) | ||
| .expect("expected operation")]; | ||
|
|
||
| let mut drive_operations: Vec<LowLevelDriveOperation> = vec![]; | ||
| drive | ||
| .apply_batch_low_level_drive_operations( | ||
| None, | ||
| None, | ||
| batch, | ||
| &mut drive_operations, | ||
| &platform_version.drive, | ||
| ) | ||
| .expect("should apply batch"); | ||
|
|
||
| let balance = drive | ||
| .fetch_identity_balance_include_debt( | ||
| identity.id().to_buffer(), | ||
| None, | ||
| platform_version, | ||
| ) | ||
| .expect("should not error") | ||
| .expect("should have balance"); | ||
|
|
||
| assert_eq!(balance, -(negative_amount as i64)); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Medium: Missing edge case — combined positive balance + negative credit This test covers the
For a financial system, testing what happens when both fields are set is important even if it "shouldn't happen" — it documents the behavior under corruption. |
||
| } | ||
| } | ||
|
|
||
| mod fetch_identity_negative_balance { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn should_error_for_non_existent_identity() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let mut drive_operations = vec![]; | ||
| // For a non-existent identity, the path doesn't exist, so grove_get_raw | ||
| // returns an error (PathParentLayerNotFound) since the identity subtree | ||
| // doesn't exist at all. | ||
| let result = drive.fetch_identity_negative_balance_operations( | ||
| [0; 32], | ||
| true, | ||
| None, | ||
| &mut drive_operations, | ||
| platform_version, | ||
| ); | ||
|
|
||
| assert!(result.is_err()); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Low: The comment explains the error is assert!(matches!(
result,
Err(Error::GroveDB(_))
), "expected GroveDB error for non-existent identity path"); |
||
| } | ||
|
|
||
| #[test] | ||
| fn should_return_zero_negative_balance_for_new_identity() { | ||
| let drive = setup_drive_with_initial_state_structure(None); | ||
| let platform_version = PlatformVersion::latest(); | ||
|
|
||
| let identity = create_test_identity(&drive, [0; 32], Some(1), None, platform_version) | ||
| .expect("expected an identity"); | ||
|
|
||
| let mut drive_operations = vec![]; | ||
| let negative_balance = drive | ||
| .fetch_identity_negative_balance_operations( | ||
| identity.id().to_buffer(), | ||
| true, | ||
| None, | ||
| &mut drive_operations, | ||
| platform_version, | ||
| ) | ||
| .expect("should not error") | ||
| .expect("should have negative balance"); | ||
|
|
||
| assert_eq!(negative_balance, 0); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Low: Estimated-mode test asserts a hardcoded placeholder
In
apply=falsemode, the production code returnsSome(0)without querying the database (it's aStatelessDirectQuery). This test goes through the overhead of creating and inserting an identity that is never read. The only meaningful assertion here isprocessing_fee > 0(fee calculation wiring).Consider adding a comment that this test validates fee calculation in estimation mode, not actual balance fetching. The inserted identity is irrelevant to the test outcome.