Files
nanoreth/crates/libmdbx-rs/tests/cursor.rs
rakita 8ac5214fc6 chore(libmbx): fmt, clippy and deny list updated (#134)
* feat(db): Add mdbx-rs apache licenced code 55e234

* feat(db): replace mdbx with reth-mdbx, metadata changes

* chore(db): bump mdbx-sys to 0.12.1

* remove libmdbx from cargo deny

* cargo fmt

* cargo clippy

* one more clippy error
2022-10-25 03:18:51 -07:00

339 lines
12 KiB
Rust

use reth_libmdbx::*;
use std::borrow::Cow;
use tempfile::tempdir;
type Environment = reth_libmdbx::Environment<NoWriteMap>;
#[test]
fn test_get() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
let db = txn.open_db(None).unwrap();
assert_eq!(None, txn.cursor(&db).unwrap().first::<(), ()>().unwrap());
txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap();
txn.put(&db, b"key3", b"val3", WriteFlags::empty()).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.get_current().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.next().unwrap(), Some((*b"key2", *b"val2")));
assert_eq!(cursor.prev().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.last().unwrap(), Some((*b"key3", *b"val3")));
assert_eq!(cursor.set(b"key1").unwrap(), Some(*b"val1"));
assert_eq!(cursor.set_key(b"key3").unwrap(), Some((*b"key3", *b"val3")));
assert_eq!(cursor.set_range(b"key2\0").unwrap(), Some((*b"key3", *b"val3")));
}
#[test]
fn test_get_dup() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap();
txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap();
txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val1", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val2", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val3", WriteFlags::empty()).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.first_dup().unwrap(), Some(*b"val1"));
assert_eq!(cursor.get_current().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.next_nodup().unwrap(), Some((*b"key2", *b"val1")));
assert_eq!(cursor.next().unwrap(), Some((*b"key2", *b"val2")));
assert_eq!(cursor.prev().unwrap(), Some((*b"key2", *b"val1")));
assert_eq!(cursor.next_dup().unwrap(), Some((*b"key2", *b"val2")));
assert_eq!(cursor.next_dup().unwrap(), Some((*b"key2", *b"val3")));
assert_eq!(cursor.next_dup::<(), ()>().unwrap(), None);
assert_eq!(cursor.prev_dup().unwrap(), Some((*b"key2", *b"val2")));
assert_eq!(cursor.last_dup().unwrap(), Some(*b"val3"));
assert_eq!(cursor.prev_nodup().unwrap(), Some((*b"key1", *b"val3")));
assert_eq!(cursor.next_dup::<(), ()>().unwrap(), None);
assert_eq!(cursor.set(b"key1").unwrap(), Some(*b"val1"));
assert_eq!(cursor.set(b"key2").unwrap(), Some(*b"val1"));
assert_eq!(cursor.set_range(b"key1\0").unwrap(), Some((*b"key2", *b"val1")));
assert_eq!(cursor.get_both(b"key1", b"val3").unwrap(), Some(*b"val3"));
assert_eq!(cursor.get_both_range::<()>(b"key1", b"val4").unwrap(), None);
assert_eq!(cursor.get_both_range(b"key2", b"val").unwrap(), Some(*b"val1"));
assert_eq!(cursor.last().unwrap(), Some((*b"key2", *b"val3")));
cursor.del(WriteFlags::empty()).unwrap();
assert_eq!(cursor.last().unwrap(), Some((*b"key2", *b"val2")));
cursor.del(WriteFlags::empty()).unwrap();
assert_eq!(cursor.last().unwrap(), Some((*b"key2", *b"val1")));
cursor.del(WriteFlags::empty()).unwrap();
assert_eq!(cursor.last().unwrap(), Some((*b"key1", *b"val3")));
}
#[test]
fn test_get_dupfixed() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
let db = txn.create_db(None, DatabaseFlags::DUP_SORT | DatabaseFlags::DUP_FIXED).unwrap();
txn.put(&db, b"key1", b"val1", WriteFlags::empty()).unwrap();
txn.put(&db, b"key1", b"val2", WriteFlags::empty()).unwrap();
txn.put(&db, b"key1", b"val3", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val4", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val5", WriteFlags::empty()).unwrap();
txn.put(&db, b"key2", b"val6", WriteFlags::empty()).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert_eq!(cursor.first().unwrap(), Some((*b"key1", *b"val1")));
assert_eq!(cursor.get_multiple().unwrap(), Some(*b"val1val2val3"));
assert_eq!(cursor.next_multiple::<(), ()>().unwrap(), None);
}
#[test]
fn test_iter() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let items: Vec<(_, _)> = vec![
(*b"key1", *b"val1"),
(*b"key2", *b"val2"),
(*b"key3", *b"val3"),
(*b"key5", *b"val5"),
];
{
let txn = env.begin_rw_txn().unwrap();
let db = txn.open_db(None).unwrap();
for (key, data) in &items {
txn.put(&db, key, data, WriteFlags::empty()).unwrap();
}
assert!(!txn.commit().unwrap());
}
let txn = env.begin_ro_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
// Because Result implements FromIterator, we can collect the iterator
// of items of type Result<_, E> into a Result<Vec<_, E>> by specifying
// the collection type via the turbofish syntax.
assert_eq!(items, cursor.iter().collect::<Result<Vec<_>>>().unwrap());
// Alternately, we can collect it into an appropriately typed variable.
let retr: Result<Vec<_>> = cursor.iter_start().collect();
assert_eq!(items, retr.unwrap());
cursor.set::<()>(b"key2").unwrap();
assert_eq!(
items.clone().into_iter().skip(2).collect::<Vec<_>>(),
cursor.iter().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(items, cursor.iter_start().collect::<Result<Vec<_>>>().unwrap());
assert_eq!(
items.clone().into_iter().skip(1).collect::<Vec<_>>(),
cursor.iter_from(b"key2").collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
items.into_iter().skip(3).collect::<Vec<_>>(),
cursor.iter_from(b"key4").collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
Vec::<((), ())>::new(),
cursor.iter_from(b"key6").collect::<Result<Vec<_>>>().unwrap()
);
}
#[test]
fn test_iter_empty_database() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_ro_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert!(cursor.iter::<(), ()>().next().is_none());
assert!(cursor.iter_start::<(), ()>().next().is_none());
assert!(cursor.iter_from::<(), ()>(b"foo").next().is_none());
}
#[test]
fn test_iter_empty_dup_database() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
txn.commit().unwrap();
let txn = env.begin_ro_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert!(cursor.iter::<(), ()>().next().is_none());
assert!(cursor.iter_start::<(), ()>().next().is_none());
assert!(cursor.iter_from::<(), ()>(b"foo").next().is_none());
assert!(cursor.iter_from::<(), ()>(b"foo").next().is_none());
assert!(cursor.iter_dup::<(), ()>().flatten().next().is_none());
assert!(cursor.iter_dup_start::<(), ()>().flatten().next().is_none());
assert!(cursor.iter_dup_from::<(), ()>(b"foo").flatten().next().is_none());
assert!(cursor.iter_dup_of::<(), ()>(b"foo").next().is_none());
}
#[test]
fn test_iter_dup() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
txn.commit().unwrap();
let items: Vec<(_, _)> = [
(b"a", b"1"),
(b"a", b"2"),
(b"a", b"3"),
(b"b", b"1"),
(b"b", b"2"),
(b"b", b"3"),
(b"c", b"1"),
(b"c", b"2"),
(b"c", b"3"),
(b"e", b"1"),
(b"e", b"2"),
(b"e", b"3"),
]
.iter()
.map(|&(&k, &v)| (k, v))
.collect();
{
let txn = env.begin_rw_txn().unwrap();
for (key, data) in items.clone() {
let db = txn.open_db(None).unwrap();
txn.put(&db, key, data, WriteFlags::empty()).unwrap();
}
txn.commit().unwrap();
}
let txn = env.begin_ro_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert_eq!(items, cursor.iter_dup().flatten().collect::<Result<Vec<_>>>().unwrap());
cursor.set::<()>(b"b").unwrap();
assert_eq!(
items.iter().copied().skip(4).collect::<Vec<_>>(),
cursor.iter_dup().flatten().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(items, cursor.iter_dup_start().flatten().collect::<Result<Vec<_>>>().unwrap());
assert_eq!(
items.iter().copied().into_iter().skip(3).collect::<Vec<_>>(),
cursor.iter_dup_from(b"b").flatten().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
items.iter().copied().into_iter().skip(3).collect::<Vec<_>>(),
cursor.iter_dup_from(b"ab").flatten().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
items.iter().copied().into_iter().skip(9).collect::<Vec<_>>(),
cursor.iter_dup_from(b"d").flatten().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
Vec::<([u8; 1], [u8; 1])>::new(),
cursor.iter_dup_from(b"f").flatten().collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(
items.iter().copied().skip(3).take(3).collect::<Vec<_>>(),
cursor.iter_dup_of(b"b").collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(0, cursor.iter_dup_of::<(), ()>(b"foo").count());
}
#[test]
fn test_iter_del_get() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let items = vec![(*b"a", *b"1"), (*b"b", *b"2")];
{
let txn = env.begin_rw_txn().unwrap();
let db = txn.create_db(None, DatabaseFlags::DUP_SORT).unwrap();
assert_eq!(
txn.cursor(&db)
.unwrap()
.iter_dup_of::<(), ()>(b"a")
.collect::<Result<Vec<_>>>()
.unwrap()
.len(),
0
);
txn.commit().unwrap();
}
{
let txn = env.begin_rw_txn().unwrap();
let db = txn.open_db(None).unwrap();
for (key, data) in &items {
txn.put(&db, key, data, WriteFlags::empty()).unwrap();
}
txn.commit().unwrap();
}
let txn = env.begin_rw_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
assert_eq!(items, cursor.iter_dup().flatten().collect::<Result<Vec<_>>>().unwrap());
assert_eq!(
items.iter().copied().take(1).collect::<Vec<(_, _)>>(),
cursor.iter_dup_of(b"a").collect::<Result<Vec<_>>>().unwrap()
);
assert_eq!(cursor.set(b"a").unwrap(), Some(*b"1"));
cursor.del(WriteFlags::empty()).unwrap();
assert_eq!(cursor.iter_dup_of::<(), ()>(b"a").collect::<Result<Vec<_>>>().unwrap().len(), 0);
}
#[test]
fn test_put_del() {
let dir = tempdir().unwrap();
let env = Environment::new().open(dir.path()).unwrap();
let txn = env.begin_rw_txn().unwrap();
let db = txn.open_db(None).unwrap();
let mut cursor = txn.cursor(&db).unwrap();
cursor.put(b"key1", b"val1", WriteFlags::empty()).unwrap();
cursor.put(b"key2", b"val2", WriteFlags::empty()).unwrap();
cursor.put(b"key3", b"val3", WriteFlags::empty()).unwrap();
assert_eq!(
cursor.get_current().unwrap().unwrap(),
(Cow::Borrowed(b"key3" as &[u8]), Cow::Borrowed(b"val3" as &[u8]))
);
cursor.del(WriteFlags::empty()).unwrap();
assert_eq!(cursor.get_current::<Vec<u8>, Vec<u8>>().unwrap(), None);
assert_eq!(
cursor.last().unwrap().unwrap(),
(Cow::Borrowed(b"key2" as &[u8]), Cow::Borrowed(b"val2" as &[u8]))
);
}