From 7a387d434b31b19e3e43efaabceddcda9699cf3b Mon Sep 17 00:00:00 2001 From: ardocrat Date: Mon, 18 May 2026 13:22:24 +0300 Subject: [PATCH] lmdb: migration test, clean data after allocate test --- store/tests/lmdb.rs | 117 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/store/tests/lmdb.rs b/store/tests/lmdb.rs index ac0b56f9..797614db 100644 --- a/store/tests/lmdb.rs +++ b/store/tests/lmdb.rs @@ -16,9 +16,17 @@ use grin_core as core; use grin_store as store; use grin_util as util; -use crate::core::global; -use crate::core::ser::{self, Readable, Reader, Writeable, Writer}; +use core::global; +use core::ser::{self, Readable, Reader, Writeable, Writer}; +use store::{ + needs_resize, to_key, to_key_u64, Store, ALLOC_CHUNK_SIZE_DEFAULT_TEST, DEFAULT_ENV_NAME, +}; + +use byteorder::WriteBytesExt; +use heed::types::Bytes; +use heed::{Database, Env, EnvOpenOptions, WithoutTls}; use std::fs; +use std::path::Path; const WRITE_CHUNK_SIZE: usize = 20; const TEST_ALLOC_SIZE: usize = store::lmdb::ALLOC_CHUNK_SIZE_DEFAULT / 8 / WRITE_CHUNK_SIZE; @@ -168,5 +176,110 @@ fn lmdb_allocate() -> Result<(), store::Error> { } } + clean_output_dir(test_dir); + Ok(()) +} + +fn create_old_db( + test_dir: &str, +) -> Result<(Database, Env), store::Error> { + let env_name = DEFAULT_ENV_NAME; + let alloc_chunk_size = ALLOC_CHUNK_SIZE_DEFAULT_TEST; + let full_path = Path::new(test_dir) + .join(env_name) + .to_str() + .unwrap() + .to_string(); + let _ = fs::create_dir_all(&full_path); + + let env = unsafe { + let mut options = EnvOpenOptions::new().read_txn_without_tls(); + let env_options = options.map_size(alloc_chunk_size).max_dbs(1); + env_options.open(&full_path)? + }; + let (resize, new_size) = needs_resize(&env, alloc_chunk_size); + if resize { + unsafe { + env.resize(new_size)?; + }; + } + + let mut write = env.write_txn()?; + let db: Database = env.create_database(&mut write, Some(env_name))?; + write.commit()?; + + Ok((db, env)) +} + +#[test] +fn test_migration() -> Result<(), store::Error> { + let test_dir = "target/test_migration"; + setup(test_dir); + + let test_prefix_1 = b'H'; + let test_key_1 = [0, 1, 2, 4]; + let test_data_1 = [1, 2, 3, 4]; + + let test_prefix_2 = b'G'; + let test_key_2 = [3, 4, 5, 6]; + let test_key_64_2 = 65480464; + let test_data_2 = [4, 5, 6, 7]; + + let test_key_3 = [6, 7, 8, 9]; + let test_data_3 = [7, 8, 9, 10]; + + // Create old db and fill the data. + { + let (old_db, old_env) = create_old_db(test_dir)?; + let mut w = old_env.write_txn()?; + + // Create old format key value. + let key_1 = to_key(test_prefix_1, test_key_1); + old_db.put(&mut w, key_1.as_slice(), test_data_1.as_slice())?; + + // Create old format 64 key value. + let key_2 = to_key_u64(test_prefix_2, test_key_2, test_key_64_2); + old_db.put(&mut w, key_2.as_slice(), test_data_2.as_slice())?; + + // Create key value without prefix. + old_db.put(&mut w, test_key_3.as_slice(), test_data_3.as_slice())?; + + w.commit()?; + } + + // Create new store to migrate data. + let store = Store::new( + test_dir, + None, + Some(DEFAULT_ENV_NAME), + vec![test_prefix_1, test_prefix_2], + None, + )?; + + // Check we can see key value. + { + assert!(store.exists(Some(test_prefix_1), &test_key_1)?); + let data = store.get_ser::>(Some(test_prefix_1), &test_key_1, None)?; + assert_eq!(data, Some(test_data_1.to_vec())); + } + + // Check we can see key 64 value. + { + let mut key = test_key_2.to_vec(); + key.write_u64::(test_key_64_2) + .unwrap(); + assert!(store.exists(Some(test_prefix_2), &key)?); + let data = store.get_ser::>(Some(test_prefix_2), &key, None)?; + assert_eq!(data, Some(test_data_2.to_vec())); + } + + // Check we can see key value without prefix. + { + assert!(store.exists(None, &test_key_3)?); + let data = store.get_ser::>(None, &test_key_3, None)?; + assert_eq!(data, Some(test_data_3.to_vec())); + } + + clean_output_dir(test_dir); Ok(()) }