From f853fbe51c5cefc64b7b705201d085151d74cdf5 Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 6 Jan 2023 12:40:23 +0800 Subject: [PATCH 1/2] test: fix test and small refactoring --- packages/js-drive/lib/storage/GroveDBStore.js | 7 +- packages/rs-drive-nodejs/GroveDB.js | 6 +- packages/rs-drive-nodejs/src/lib.rs | 6 +- packages/rs-drive-nodejs/test/GroveDB.spec.js | 62 ++-- packages/rs-drive/src/drive/contract/mod.rs | 281 +++++++++--------- 5 files changed, 186 insertions(+), 176 deletions(-) diff --git a/packages/js-drive/lib/storage/GroveDBStore.js b/packages/js-drive/lib/storage/GroveDBStore.js index 6a58f8f3560..35a1eb474d9 100644 --- a/packages/js-drive/lib/storage/GroveDBStore.js +++ b/packages/js-drive/lib/storage/GroveDBStore.js @@ -231,6 +231,7 @@ class GroveDBStore { * * @param {PathQuery} query * @param {Object} [options] + * @param {boolean} [options.skipCache=false] * @param {boolean} [options.useTransaction=false] * @return {Promise>} */ @@ -238,7 +239,11 @@ class GroveDBStore { let items; try { - [items] = await this.db.query(query, options.useTransaction || false); + [items] = await this.db.query( + query, + options.skipCache || false, + options.useTransaction || false, + ); } catch (e) { if ( e.message.startsWith('grovedb: path key not found') diff --git a/packages/rs-drive-nodejs/GroveDB.js b/packages/rs-drive-nodejs/GroveDB.js index 51d10024622..100ab9963ff 100644 --- a/packages/rs-drive-nodejs/GroveDB.js +++ b/packages/rs-drive-nodejs/GroveDB.js @@ -193,12 +193,12 @@ class GroveDB { * Get data using query. * * @param {PathQuery} query + * @param {boolean} [skipCache=false] * @param {boolean} [useTransaction=false] - * @param {boolean} [allowCache=false] * @return {Promise<*>} */ - async query(query, useTransaction = false, allowCache = true) { - return groveDbQueryAsync.call(this.db, query, allowCache, useTransaction); + async query(query, skipCache = false, useTransaction = false) { + return groveDbQueryAsync.call(this.db, query, skipCache, useTransaction); } /** diff --git a/packages/rs-drive-nodejs/src/lib.rs b/packages/rs-drive-nodejs/src/lib.rs index 6594c6c028f..a52377c838c 100644 --- a/packages/rs-drive-nodejs/src/lib.rs +++ b/packages/rs-drive-nodejs/src/lib.rs @@ -1576,14 +1576,14 @@ impl PlatformWrapper { fn js_grove_db_query(mut cx: FunctionContext) -> JsResult { let js_path_query = cx.argument::(0)?; - let js_allow_cache = cx.argument::(1)?; + let js_skip_cache = cx.argument::(1)?; let js_using_transaction = cx.argument::(2)?; let js_callback = cx.argument::(3)?.root(&mut cx); let path_query = converter::js_path_query_to_path_query(js_path_query, &mut cx)?; - let allow_cache = js_allow_cache.value(&mut cx); + let skip_cache = js_skip_cache.value(&mut cx); let using_transaction = js_using_transaction.value(&mut cx); @@ -1606,7 +1606,7 @@ impl PlatformWrapper { let result = transaction_result.and_then(|transaction_arg| { grove_db - .query_item_value(&path_query, allow_cache, transaction_arg) + .query_item_value(&path_query, !skip_cache, transaction_arg) .unwrap() .map_err(Error::GroveDB) .map_err(|err| err.to_string()) diff --git a/packages/rs-drive-nodejs/test/GroveDB.spec.js b/packages/rs-drive-nodejs/test/GroveDB.spec.js index 9e1bcfb2df3..565ee7e5e6b 100644 --- a/packages/rs-drive-nodejs/test/GroveDB.spec.js +++ b/packages/rs-drive-nodejs/test/GroveDB.spec.js @@ -836,37 +836,21 @@ describe('GroveDB', () => { expect(skipped).to.equals(0); }); - }); - - describe('#query', () => { - let dPath; - let dKey; - let ePath; - - let daValue; - let dbValue; - let dcValue; - let eaValue; - let eaKey; - let ebValue; - beforeEach(async () => { - await groveDb.insert( - rootTreePath, - treeKey, - { type: 'tree', epoch: 0 }, - ); + it('should be able to retrieve data with subquery', async () => { + // Prepare tree structure + const dKey = Buffer.from('dKey'); + const daValue = Buffer.from('da'); + const dbValue = Buffer.from('db'); + const dcValue = Buffer.from('dc'); + const eaValue = Buffer.from('ea'); + const eaKey = Buffer.from('eaKey'); + const ebValue = Buffer.from('eb'); - dKey = Buffer.from('dKey'); - daValue = Buffer.from('da'); - dbValue = Buffer.from('db'); - dcValue = Buffer.from('dc'); - eaValue = Buffer.from('ea'); - eaKey = Buffer.from('eaKey'); - ebValue = Buffer.from('eb'); + const dPath = [...itemTreePath]; - dPath = [...itemTreePath]; dPath.push(dKey); + await groveDb.insert( itemTreePath, dKey, @@ -892,7 +876,8 @@ describe('GroveDB', () => { ); const eKey = Buffer.from('eKey'); - ePath = [...itemTreePath]; + + const ePath = [...itemTreePath]; ePath.push(eKey); await groveDb.insert( itemTreePath, @@ -911,9 +896,7 @@ describe('GroveDB', () => { Buffer.from('ebKey'), { type: 'item', epoch: 0, value: ebValue }, ); - }); - it('should be able to retrieve data with subquery', async () => { // This should give us only last subtree and apply subquery to it const query = { path: itemTreePath, @@ -951,6 +934,25 @@ describe('GroveDB', () => { }); }); + describe('#query', () => { + let dPath; + let dKey; + let ePath; + + let daValue; + let dbValue; + let dcValue; + let eaValue; + let eaKey; + let ebValue; + + beforeEach(async () => { + + }); + + + }); + describe('#proveQuery', () => { let dPath; let dKey; diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index e3a34b7d86b..8d0fe7bd237 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -1045,6 +1045,8 @@ mod tests { }; use crate::drive::Drive; + use crate::common::helpers::setup::setup_drive_with_initial_state_structure; + fn setup_deep_nested_contract() -> (Drive, Contract, Vec) { // Todo: make TempDir based on _prefix let tmp_dir = TempDir::new().unwrap(); @@ -1310,126 +1312,12 @@ mod tests { .expect("expected to apply contract successfully"); } - #[test] - fn test_contract_cache_returns_same_cost_after_reload() { - let tmp_dir = TempDir::new().unwrap(); - let drive: Drive = Drive::open(tmp_dir, None).expect("expected to open Drive successfully"); - - drive - .create_initial_state_structure(None) - .expect("expected to create root tree successfully"); - - let contract_path = "tests/supporting_files/contract/references/references.json"; - - // let's construct the grovedb structure for the dashpay data contract - let contract_cbor = json_document_to_cbor(contract_path, Some(1)); - let ref_contract = ::from_cbor(&contract_cbor, None) - .expect("expected to deserialize the contract"); - - let transaction = drive.grove.start_transaction(); - - // Create a contract first - drive - .apply_contract( - &ref_contract, - contract_cbor.clone(), - BlockInfo::default(), - true, - StorageFlags::optional_default_as_ref(), - Some(&transaction), - ) - .expect("expected to apply contract successfully"); - - let contract_path = "tests/supporting_files/contract/deepNested/deep-nested50.json"; - // let's construct the grovedb structure for the dashpay data contract - let contract_cbor = json_document_to_cbor(contract_path, Some(1)); - let deep_contract = ::from_cbor(&contract_cbor, None) - .expect("expected to deserialize the contract"); - drive - .apply_contract( - &deep_contract, - contract_cbor.clone(), - BlockInfo::default(), - true, - StorageFlags::optional_default_as_ref(), - Some(&transaction), - ) - .expect("expected to apply contract successfully"); - - let deep_contract_fetch_info = drive - .get_contract_with_fetch_info( - deep_contract.id().to_buffer(), - Some(&Epoch::new(0)), - Some(&transaction), - ) - .expect("got contract") - .1 - .expect("got contract fetch info"); - let ref_contract_fetch_info = drive - .get_contract_with_fetch_info( - ref_contract.id().to_buffer(), - Some(&Epoch::new(0)), - Some(&transaction), - ) - .expect("got contract") - .1 - .expect("got contract fetch info"); - - transaction.commit().expect("expected to commit"); - - let deep_contract_fetch_info_after_prune = drive - .get_contract_with_fetch_info( - deep_contract.id().to_buffer(), - Some(&Epoch::new(0)), - None, - ) - .expect("got contract") - .1 - .expect("got contract fetch info"); - let ref_contract_fetch_info_after_prune = drive - .get_contract_with_fetch_info(ref_contract.id().to_buffer(), Some(&Epoch::new(0)), None) - .expect("got contract") - .1 - .expect("got contract fetch info"); - - assert_eq!( - deep_contract_fetch_info, - deep_contract_fetch_info_after_prune - ); - assert_eq!(ref_contract_fetch_info, ref_contract_fetch_info_after_prune); - - drive.drop_cache(); - - let deep_contract_fetch_info_after_cache_reload = drive - .get_contract_with_fetch_info( - deep_contract.id().to_buffer(), - Some(&Epoch::new(0)), - None, - ) - .expect("got contract") - .1 - .expect("got contract fetch info"); - let ref_contract_fetch_info_after_cache_reload = drive - .get_contract_with_fetch_info(ref_contract.id().to_buffer(), Some(&Epoch::new(0)), None) - .expect("got contract") - .1 - .expect("got contract fetch info"); - - assert_eq!( - deep_contract_fetch_info, - deep_contract_fetch_info_after_cache_reload - ); - assert_eq!( - ref_contract_fetch_info, - ref_contract_fetch_info_after_cache_reload - ); - } - - mod get_contract_with_fetch_info_and_add_to_operations { + mod get_contract_with_fetch_info { use super::*; + use dpp::prelude::Identifier; #[test] - fn test_get_contract_from_global_and_transactional_cache() { + fn should_get_contract_from_global_and_block_cache() { let (drive, mut contract, _) = setup_reference_contract(); let transaction = drive.grove.start_transaction(); @@ -1466,41 +1354,156 @@ mod tests { } #[test] - fn test_get_non_existent_contract() { - let tmp_dir = TempDir::new().unwrap(); - let drive: Drive = - Drive::open(tmp_dir, None).expect("expected to open Drive successfully"); + fn should_return_none_if_contract_not_exist() { + let drive = setup_drive_with_initial_state_structure(); - drive - .create_initial_state_structure(None) - .expect("expected to create state structure"); - let contract_id = rand::thread_rng().gen::<[u8; 32]>(); + let result = drive + .get_contract_with_fetch_info([0; 32], None, None) + .expect("should get contract"); + + assert!(result.0.is_none()); + assert!(result.1.is_none()); + } + + #[test] + fn should_return_fees_for_non_existing_contract_if_epoch_is_passed() { + let drive = setup_drive_with_initial_state_structure(); let result = drive - .get_contract_with_fetch_info(contract_id, None, None) + .get_contract_with_fetch_info([0; 32], Some(&Epoch::new(0)), None) .expect("should get contract"); + assert!(matches!( + result.0, + Some(FeeResult { + processing_fee: 6000, + .. + }) + )); + assert!(result.1.is_none()); } #[test] - fn test_get_non_existent_contract_has_fees() { - let tmp_dir = TempDir::new().unwrap(); - let drive: Drive = - Drive::open(tmp_dir, None).expect("expected to open Drive successfully"); + fn should_return_then_same_costs_for_cached_and_non_cached_contracts_in_merk() { + // Merk trees have own cache and depends on does contract node cached or not + // we get could get different costs. To avoid of it we fetch contracts without tree caching + + let (drive, mut ref_contract, ref_contract_cbor) = setup_reference_contract(); + let transaction = drive.grove.start_transaction(); + + // Create more contracts to trigger re-balancing + for i in 0..150u8 { + ref_contract.id = Identifier::from([i; 32]); + + drive + .apply_contract( + &ref_contract, + ref_contract_cbor.clone(), + BlockInfo::default(), + true, + StorageFlags::optional_default_as_ref(), + Some(&transaction), + ) + .expect("expected to apply contract successfully"); + } + + // Create a deep placed contract + let contract_path = "tests/supporting_files/contract/deepNested/deep-nested50.json"; + let contract_cbor = json_document_to_cbor(contract_path, Some(1)); + let deep_contract = ::from_cbor(&contract_cbor, None) + .expect("expected to deserialize the contract"); drive - .create_initial_state_structure(None) - .expect("expected to create state structure"); - let contract_id = rand::thread_rng().gen::<[u8; 32]>(); + .apply_contract( + &deep_contract, + contract_cbor.clone(), + BlockInfo::default(), + true, + StorageFlags::optional_default_as_ref(), + Some(&transaction), + ) + .expect("expected to apply contract successfully"); - let result = drive - .get_contract_with_fetch_info(contract_id, Some(&Epoch::new(0)), None) - .expect("should get contract"); + // Get fetch info to compare + let ref_contract_fetch_info = drive + .get_contract_with_fetch_info( + Identifier::from([0; 32]).to_buffer(), + Some(&Epoch::new(0)), + Some(&transaction), + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); - let fees = result.0; - assert!(fees.is_some()); - assert_eq!(fees.unwrap().processing_fee, 6000) + let deep_contract_fetch_info = drive + .get_contract_with_fetch_info( + deep_contract.id().to_buffer(), + Some(&Epoch::new(0)), + Some(&transaction), + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); + + transaction.commit().expect("expected to commit"); + + let deep_contract_fetch_info_after_prune = drive + .get_contract_with_fetch_info( + deep_contract.id().to_buffer(), + Some(&Epoch::new(0)), + None, + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); + let ref_contract_fetch_info_after_prune = drive + .get_contract_with_fetch_info( + ref_contract.id().to_buffer(), + Some(&Epoch::new(0)), + None, + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); + + assert_eq!( + deep_contract_fetch_info, + deep_contract_fetch_info_after_prune + ); + + assert_eq!(ref_contract_fetch_info, ref_contract_fetch_info_after_prune); + + drive.drop_cache(); + + let deep_contract_fetch_info_after_cache_reload = drive + .get_contract_with_fetch_info( + deep_contract.id().to_buffer(), + Some(&Epoch::new(0)), + None, + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); + + let ref_contract_fetch_info_after_cache_reload = drive + .get_contract_with_fetch_info( + ref_contract.id().to_buffer(), + Some(&Epoch::new(0)), + None, + ) + .expect("got contract") + .1 + .expect("got contract fetch info"); + + assert_eq!( + deep_contract_fetch_info, + deep_contract_fetch_info_after_cache_reload + ); + assert_eq!( + ref_contract_fetch_info, + ref_contract_fetch_info_after_cache_reload + ); } } } From 8d70c8900c9de32eea1db3e6e4c3a85d05b1f57e Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 6 Jan 2023 12:43:43 +0800 Subject: [PATCH 2/2] test: fix grovedb tests --- packages/rs-drive-nodejs/test/GroveDB.spec.js | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/packages/rs-drive-nodejs/test/GroveDB.spec.js b/packages/rs-drive-nodejs/test/GroveDB.spec.js index 565ee7e5e6b..85726052775 100644 --- a/packages/rs-drive-nodejs/test/GroveDB.spec.js +++ b/packages/rs-drive-nodejs/test/GroveDB.spec.js @@ -434,7 +434,7 @@ describe('GroveDB', () => { }); }); - describe('#query for Item subtrees', () => { + describe('#query', () => { let aValue; let aKey; let bValue; @@ -934,25 +934,6 @@ describe('GroveDB', () => { }); }); - describe('#query', () => { - let dPath; - let dKey; - let ePath; - - let daValue; - let dbValue; - let dcValue; - let eaValue; - let eaKey; - let ebValue; - - beforeEach(async () => { - - }); - - - }); - describe('#proveQuery', () => { let dPath; let dKey;