database: fix tests, remove blockchain specific references

This commit is contained in:
hinto.janai 2024-06-13 16:39:09 -04:00
parent 3dab3f234f
commit 7024517cf4
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
3 changed files with 190 additions and 372 deletions

View file

@ -20,7 +20,6 @@ use crate::{
env::{Env, EnvInner},
error::RuntimeError,
resize::ResizeAlgorithm,
storable::StorableVec,
tests::{tmp_concrete_env, TestTable},
transaction::{TxRo, TxRw},
ConcreteEnv,
@ -158,406 +157,219 @@ fn non_manual_resize_2() {
env.current_map_size();
}
// /// Test all `DatabaseR{o,w}` operations.
// #[test]
// fn db_read_write() {
// let (env, _tempdir) = tmp_concrete_env();
// let env_inner = env.env_inner();
// let tx_rw = env_inner.tx_rw().unwrap();
// let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
/// Test all `DatabaseR{o,w}` operations.
#[test]
fn db_read_write() {
let (env, _tempdir) = tmp_concrete_env();
let env_inner = env.env_inner();
let tx_rw = env_inner.tx_rw().unwrap();
let mut table = env_inner.open_db_rw::<TestTable>(&tx_rw).unwrap();
// /// The (1st) key.
// const KEY: PreRctOutputId = PreRctOutputId {
// amount: 1,
// amount_index: 123,
// };
// /// The expected value.
// const VALUE: Output = Output {
// key: [35; 32],
// height: 45_761_798,
// output_flags: OutputFlags::empty(),
// tx_idx: 2_353_487,
// };
// /// How many `(key, value)` pairs will be inserted.
// const N: u64 = 100;
/// The (1st) key.
const KEY: u8 = 0;
/// The expected value.
const VALUE: u64 = 0;
/// How many `(key, value)` pairs will be inserted.
const N: u8 = 100;
// /// Assert 2 `Output`'s are equal, and that accessing
// /// their fields don't result in an unaligned panic.
// fn assert_same(output: Output) {
// assert_eq!(output, VALUE);
// assert_eq!(output.key, VALUE.key);
// assert_eq!(output.height, VALUE.height);
// assert_eq!(output.output_flags, VALUE.output_flags);
// assert_eq!(output.tx_idx, VALUE.tx_idx);
// }
/// Assert a u64 is the same as `VALUE`.
fn assert_value(value: u64) {
assert_eq!(value, VALUE);
}
// assert!(table.is_empty().unwrap());
assert!(table.is_empty().unwrap());
// // Insert keys.
// let mut key = KEY;
// for _ in 0..N {
// table.put(&key, &VALUE).unwrap();
// key.amount += 1;
// }
// Insert keys.
let mut key = KEY;
#[allow(clippy::explicit_counter_loop)] // we need the +1 side effect
for _ in 0..N {
table.put(&key, &VALUE).unwrap();
key += 1;
}
// assert_eq!(table.len().unwrap(), N);
assert_eq!(table.len().unwrap(), u64::from(N));
// // Assert the first/last `(key, value)`s are there.
// {
// assert!(table.contains(&KEY).unwrap());
// let get: Output = table.get(&KEY).unwrap();
// assert_same(get);
// Assert the first/last `(key, value)`s are there.
{
assert!(table.contains(&KEY).unwrap());
let get = table.get(&KEY).unwrap();
assert_value(get);
// let first: Output = table.first().unwrap().1;
// assert_same(first);
let first = table.first().unwrap().1;
assert_value(first);
// let last: Output = table.last().unwrap().1;
// assert_same(last);
// }
let last = table.last().unwrap().1;
assert_value(last);
}
// // Commit transactions, create new ones.
// drop(table);
// TxRw::commit(tx_rw).unwrap();
// let tx_ro = env_inner.tx_ro().unwrap();
// let table_ro = env_inner.open_db_ro::<Outputs>(&tx_ro).unwrap();
// let tx_rw = env_inner.tx_rw().unwrap();
// let mut table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
// Commit transactions, create new ones.
drop(table);
TxRw::commit(tx_rw).unwrap();
let tx_ro = env_inner.tx_ro().unwrap();
let table_ro = env_inner.open_db_ro::<TestTable>(&tx_ro).unwrap();
let tx_rw = env_inner.tx_rw().unwrap();
let mut table = env_inner.open_db_rw::<TestTable>(&tx_rw).unwrap();
// // Assert the whole range is there.
// {
// let range = table_ro.get_range(..).unwrap();
// let mut i = 0;
// for result in range {
// let value: Output = result.unwrap();
// assert_same(value);
// Assert the whole range is there.
{
let range = table_ro.get_range(..).unwrap();
let mut i = 0;
for result in range {
let value = result.unwrap();
assert_value(value);
i += 1;
}
assert_eq!(i, N);
}
// i += 1;
// }
// assert_eq!(i, N);
// }
// `get_range()` tests.
let mut key = KEY;
key += N;
let range = KEY..key;
// // `get_range()` tests.
// let mut key = KEY;
// key.amount += N;
// let range = KEY..key;
// Assert count is correct.
assert_eq!(
N as usize,
table_ro.get_range(range.clone()).unwrap().count()
);
// // Assert count is correct.
// assert_eq!(
// N as usize,
// table_ro.get_range(range.clone()).unwrap().count()
// );
// Assert each returned value from the iterator is owned.
{
let mut iter = table_ro.get_range(range.clone()).unwrap();
let value = iter.next().unwrap().unwrap(); // 1. take value out
drop(iter); // 2. drop the `impl Iterator + 'a`
assert_value(value); // 3. assert even without the iterator, the value is alive
}
// // Assert each returned value from the iterator is owned.
// {
// let mut iter = table_ro.get_range(range.clone()).unwrap();
// let value: Output = iter.next().unwrap().unwrap(); // 1. take value out
// drop(iter); // 2. drop the `impl Iterator + 'a`
// assert_same(value); // 3. assert even without the iterator, the value is alive
// }
// Assert each value is the same.
{
let mut iter = table_ro.get_range(range).unwrap();
for _ in 0..N {
let value = iter.next().unwrap().unwrap();
assert_value(value);
}
}
// // Assert each value is the same.
// {
// let mut iter = table_ro.get_range(range).unwrap();
// for _ in 0..N {
// let value: Output = iter.next().unwrap().unwrap();
// assert_same(value);
// }
// }
// Assert `update()` works.
{
const NEW_VALUE: u64 = 999;
// // Assert `update()` works.
// {
// const HEIGHT: u32 = 999;
assert_ne!(table.get(&KEY).unwrap(), NEW_VALUE);
// assert_ne!(table.get(&KEY).unwrap().height, HEIGHT);
#[allow(unused_assignments)]
table
.update(&KEY, |mut value| {
value = NEW_VALUE;
Some(value)
})
.unwrap();
// table
// .update(&KEY, |mut value| {
// value.height = HEIGHT;
// Some(value)
// })
// .unwrap();
assert_eq!(table.get(&KEY).unwrap(), NEW_VALUE);
}
// assert_eq!(table.get(&KEY).unwrap().height, HEIGHT);
// }
// Assert deleting works.
{
table.delete(&KEY).unwrap();
let value = table.get(&KEY);
assert!(!table.contains(&KEY).unwrap());
assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
// Assert the other `(key, value)` pairs are still there.
let mut key = KEY;
key += N - 1; // we used inclusive `0..N`
let value = table.get(&key).unwrap();
assert_value(value);
}
// // Assert deleting works.
// {
// table.delete(&KEY).unwrap();
// let value = table.get(&KEY);
// assert!(!table.contains(&KEY).unwrap());
// assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
// // Assert the other `(key, value)` pairs are still there.
// let mut key = KEY;
// key.amount += N - 1; // we used inclusive `0..N`
// let value = table.get(&key).unwrap();
// assert_same(value);
// }
// Assert `take()` works.
{
let mut key = KEY;
key += 1;
let value = table.take(&key).unwrap();
assert_eq!(value, VALUE);
// // Assert `take()` works.
// {
// let mut key = KEY;
// key.amount += 1;
// let value = table.take(&key).unwrap();
// assert_eq!(value, VALUE);
let get = table.get(&KEY);
assert!(!table.contains(&key).unwrap());
assert!(matches!(get, Err(RuntimeError::KeyNotFound)));
// let get = table.get(&KEY);
// assert!(!table.contains(&key).unwrap());
// assert!(matches!(get, Err(RuntimeError::KeyNotFound)));
// Assert the other `(key, value)` pairs are still there.
key += 1;
let value = table.get(&key).unwrap();
assert_value(value);
}
// // Assert the other `(key, value)` pairs are still there.
// key.amount += 1;
// let value = table.get(&key).unwrap();
// assert_same(value);
// }
drop(table);
TxRw::commit(tx_rw).unwrap();
// drop(table);
// TxRw::commit(tx_rw).unwrap();
// Assert `clear_db()` works.
{
let mut tx_rw = env_inner.tx_rw().unwrap();
env_inner.clear_db::<TestTable>(&mut tx_rw).unwrap();
let table = env_inner.open_db_rw::<TestTable>(&tx_rw).unwrap();
assert!(table.is_empty().unwrap());
for n in 0..N {
let mut key = KEY;
key += n;
let value = table.get(&key);
assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
assert!(!table.contains(&key).unwrap());
}
// // Assert `clear_db()` works.
// {
// let mut tx_rw = env_inner.tx_rw().unwrap();
// env_inner.clear_db::<Outputs>(&mut tx_rw).unwrap();
// let table = env_inner.open_db_rw::<Outputs>(&tx_rw).unwrap();
// assert!(table.is_empty().unwrap());
// for n in 0..N {
// let mut key = KEY;
// key.amount += n;
// let value = table.get(&key);
// assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
// assert!(!table.contains(&key).unwrap());
// }
// Reader still sees old value.
assert!(!table_ro.is_empty().unwrap());
// // Reader still sees old value.
// assert!(!table_ro.is_empty().unwrap());
// Writer sees updated value (nothing).
assert!(table.is_empty().unwrap());
}
}
// // Writer sees updated value (nothing).
// assert!(table.is_empty().unwrap());
// }
// }
/// Assert that `key`'s in database tables are sorted in
/// an ordered B-Tree fashion, i.e. `min_value -> max_value`.
#[test]
fn tables_are_sorted() {
let (env, _tmp) = tmp_concrete_env();
let env_inner = env.env_inner();
let tx_rw = env_inner.tx_rw().unwrap();
let mut table = env_inner.open_db_rw::<TestTable>(&tx_rw).unwrap();
// /// Assert that `key`'s in database tables are sorted in
// /// an ordered B-Tree fashion, i.e. `min_value -> max_value`.
// #[test]
// fn tables_are_sorted() {
// let (env, _tmp) = tmp_concrete_env();
// let env_inner = env.env_inner();
// let tx_rw = env_inner.tx_rw().unwrap();
// let mut tables_mut = env_inner.open_tables_mut(&tx_rw).unwrap();
// Insert `{5, 4, 3, 2, 1, 0}`, assert each new
// number inserted is the minimum `first()` value.
for key in (0..6).rev() {
table.put(&key, &123).unwrap();
let (first, _) = table.first().unwrap();
assert_eq!(first, key);
}
// // Insert `{5, 4, 3, 2, 1, 0}`, assert each new
// // number inserted is the minimum `first()` value.
// for key in (0..6).rev() {
// tables_mut.num_outputs_mut().put(&key, &123).unwrap();
// let (first, _) = tables_mut.num_outputs_mut().first().unwrap();
// assert_eq!(first, key);
// }
drop(table);
TxRw::commit(tx_rw).unwrap();
let tx_rw = env_inner.tx_rw().unwrap();
// drop(tables_mut);
// TxRw::commit(tx_rw).unwrap();
// let tx_rw = env_inner.tx_rw().unwrap();
// Assert iterators are ordered.
{
let tx_ro = env_inner.tx_ro().unwrap();
let table = env_inner.open_db_ro::<TestTable>(&tx_ro).unwrap();
let iter = table.iter().unwrap();
let keys = table.keys().unwrap();
for ((i, iter), key) in (0..6).zip(iter).zip(keys) {
let (iter, _) = iter.unwrap();
let key = key.unwrap();
assert_eq!(i, iter);
assert_eq!(iter, key);
}
}
// // Assert iterators are ordered.
// {
// let tx_ro = env_inner.tx_ro().unwrap();
// let tables = env_inner.open_tables(&tx_ro).unwrap();
// let t = tables.num_outputs_iter();
// let iter = t.iter().unwrap();
// let keys = t.keys().unwrap();
// for ((i, iter), key) in (0..6).zip(iter).zip(keys) {
// let (iter, _) = iter.unwrap();
// let key = key.unwrap();
// assert_eq!(i, iter);
// assert_eq!(iter, key);
// }
// }
let mut table = env_inner.open_db_rw::<TestTable>(&tx_rw).unwrap();
// let mut tables_mut = env_inner.open_tables_mut(&tx_rw).unwrap();
// let t = tables_mut.num_outputs_mut();
// Assert the `first()` values are the minimum, i.e. `{0, 1, 2}`
for key in 0..3 {
let (first, _) = table.first().unwrap();
assert_eq!(first, key);
table.delete(&key).unwrap();
}
// // Assert the `first()` values are the minimum, i.e. `{0, 1, 2}`
// for key in 0..3 {
// let (first, _) = t.first().unwrap();
// assert_eq!(first, key);
// t.delete(&key).unwrap();
// }
// // Assert the `last()` values are the maximum, i.e. `{5, 4, 3}`
// for key in (3..6).rev() {
// let (last, _) = tables_mut.num_outputs_mut().last().unwrap();
// assert_eq!(last, key);
// tables_mut.num_outputs_mut().delete(&key).unwrap();
// }
// }
// //---------------------------------------------------------------------------------------------------- Table Tests
// /// Test multiple tables and their key + values.
// ///
// /// Each one of these tests:
// /// - Opens a specific table
// /// - Essentially does the `db_read_write` test
// macro_rules! test_tables {
// ($(
// $table:ident, // Table type
// $key_type:ty => // Key (type)
// $value_type:ty, // Value (type)
// $key:expr => // Key (the value)
// $value:expr, // Value (the value)
// )* $(,)?) => { paste::paste! { $(
// // Test function's name is the table type in `snake_case`.
// #[test]
// fn [<$table:snake>]() {
// // Open the database env and table.
// let (env, _tempdir) = tmp_concrete_env();
// let env_inner = env.env_inner();
// let mut tx_rw = env_inner.tx_rw().unwrap();
// let mut table = env_inner.open_db_rw::<$table>(&mut tx_rw).unwrap();
// /// The expected key.
// const KEY: $key_type = $key;
// // The expected value.
// let value: $value_type = $value;
// // Assert a passed value is equal to the const value.
// let assert_eq = |v: &$value_type| {
// assert_eq!(v, &value);
// };
// // Insert the key.
// table.put(&KEY, &value).unwrap();
// // Assert key is there.
// {
// let value: $value_type = table.get(&KEY).unwrap();
// assert_eq(&value);
// }
// assert!(table.contains(&KEY).unwrap());
// assert_eq!(table.len().unwrap(), 1);
// // Commit transactions, create new ones.
// drop(table);
// TxRw::commit(tx_rw).unwrap();
// let mut tx_rw = env_inner.tx_rw().unwrap();
// let tx_ro = env_inner.tx_ro().unwrap();
// let mut table = env_inner.open_db_rw::<$table>(&tx_rw).unwrap();
// let table_ro = env_inner.open_db_ro::<$table>(&tx_ro).unwrap();
// // Assert `get_range()` works.
// {
// let range = KEY..;
// assert_eq!(1, table_ro.get_range(range.clone()).unwrap().count());
// let mut iter = table_ro.get_range(range).unwrap();
// let value = iter.next().unwrap().unwrap();
// assert_eq(&value);
// }
// // Assert deleting works.
// {
// table.delete(&KEY).unwrap();
// let value = table.get(&KEY);
// assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
// assert!(!table.contains(&KEY).unwrap());
// assert_eq!(table.len().unwrap(), 0);
// }
// table.put(&KEY, &value).unwrap();
// // Assert `clear_db()` works.
// {
// drop(table);
// env_inner.clear_db::<$table>(&mut tx_rw).unwrap();
// let table = env_inner.open_db_rw::<$table>(&mut tx_rw).unwrap();
// let value = table.get(&KEY);
// assert!(matches!(value, Err(RuntimeError::KeyNotFound)));
// assert!(!table.contains(&KEY).unwrap());
// assert_eq!(table.len().unwrap(), 0);
// }
// }
// )*}};
// }
// // Notes:
// // - Keep this sorted A-Z (by table name)
// test_tables! {
// BlockBlobs, // Table type
// BlockHeight => BlockBlob, // Key type => Value type
// 123 => StorableVec(vec![1,2,3,4,5,6,7,8]), // Actual key => Actual value
// BlockHeights,
// BlockHash => BlockHeight,
// [32; 32] => 123,
// BlockInfos,
// BlockHeight => BlockInfo,
// 123 => BlockInfo {
// timestamp: 1,
// cumulative_generated_coins: 123,
// weight: 321,
// cumulative_difficulty_low: 111,
// cumulative_difficulty_high: 111,
// block_hash: [54; 32],
// cumulative_rct_outs: 2389,
// long_term_weight: 2389,
// },
// KeyImages,
// KeyImage => (),
// [32; 32] => (),
// NumOutputs,
// Amount => AmountIndex,
// 123 => 123,
// TxBlobs,
// TxId => TxBlob,
// 123 => StorableVec(vec![1,2,3,4,5,6,7,8]),
// TxIds,
// TxHash => TxId,
// [32; 32] => 123,
// TxHeights,
// TxId => BlockHeight,
// 123 => 123,
// TxOutputs,
// TxId => AmountIndices,
// 123 => StorableVec(vec![1,2,3,4,5,6,7,8]),
// TxUnlockTime,
// TxId => UnlockTime,
// 123 => 123,
// Outputs,
// PreRctOutputId => Output,
// PreRctOutputId {
// amount: 1,
// amount_index: 2,
// } => Output {
// key: [1; 32],
// height: 1,
// output_flags: OutputFlags::empty(),
// tx_idx: 3,
// },
// PrunedTxBlobs,
// TxId => PrunedBlob,
// 123 => StorableVec(vec![1,2,3,4,5,6,7,8]),
// PrunableTxBlobs,
// TxId => PrunableBlob,
// 123 => StorableVec(vec![1,2,3,4,5,6,7,8]),
// PrunableHashes,
// TxId => PrunableHash,
// 123 => [32; 32],
// RctOutputs,
// AmountIndex => RctOutput,
// 123 => RctOutput {
// key: [1; 32],
// height: 1,
// output_flags: OutputFlags::empty(),
// tx_idx: 3,
// commitment: [3; 32],
// },
// }
// Assert the `last()` values are the maximum, i.e. `{5, 4, 3}`
for key in (3..6).rev() {
let (last, _) = table.last().unwrap();
assert_eq!(last, key);
table.delete(&key).unwrap();
}
}

View file

@ -199,6 +199,12 @@ Implementation detail you should NOT rely on:
/// As noted in `Env::env_inner`, this is a `RwLockReadGuard`
/// when using the `heed` backend, be aware of this and do
/// not hold onto an `EnvInner` for a long time.
///
/// # Tables
/// Note that when opening tables with [`EnvInner::open_db_ro`],
/// they must be created first or else it will return error.
///
/// See [`EnvInner::open_db_rw`] and [`EnvInner::create_db`] for creating tables.
pub trait EnvInner<'env, Ro, Rw>
where
Self: 'env,

View file

@ -14,7 +14,7 @@ pub(crate) struct TestTable;
impl Table for TestTable {
const NAME: &'static str = "test_table";
type Key = u8;
type Value = u8;
type Value = u64;
}
//---------------------------------------------------------------------------------------------------- fn