mod helpers;
use helpers::create_and_drop;
use persy::{ByteVec, IndexIter, IndexType, TxIndexIter, ValueMode, PE};
use persy::{Persy, PersyError};
fn create_and_drop_index<F>(test: &str, f: F)
where
F: FnOnce(&Persy, &str),
{
create_and_drop_index_mode(test, ValueMode::Cluster, f);
}
fn create_and_drop_index_mode<F>(test: &str, mode: ValueMode, f: F)
where
F: FnOnce(&Persy, &str),
{
create_and_drop(test, |persy| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>("index1", mode)
.expect("index created correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
f(persy, "index1");
let mut tx = persy.begin().expect("begin transaction works");
tx.drop_index("index1").expect("index created correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_create_drop_index() {
create_and_drop("create_drop_index", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>("index1", ValueMode::Cluster)
.expect("index created correctly");
assert!(tx.exists_index("index1").expect("exists works"));
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
assert!(persy.exists_index("index1").expect("exists works"));
let mut tx = persy.begin().expect("begin transaction works");
tx.drop_index("index1").expect("index created correctly");
assert!(!tx.exists_index("index1").expect("exists works"));
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
assert!(!persy.exists_index("index1").expect("exists works"));
});
}
#[test]
fn test_create_duplicate_index() {
create_and_drop("create_duplicate_index", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>("index1", ValueMode::Cluster)
.expect("index created correctly");
assert!(tx.exists_index("index1").expect("exists works"));
let mut tx1 = persy.begin().expect("begin transaction works");
assert!(!tx1.exists_index("index1").expect("exists works"));
tx1.create_index::<u8, u8>("index1", ValueMode::Cluster)
.expect("index created correctly");
assert!(tx1.exists_index("index1").expect("exists works"));
let prep = tx1.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
match tx.prepare() {
Err(PE::PE(persy::PrepareError::IndexAlreadyExists)) => {}
_ => panic!("Expect duplicate index error"),
}
assert!(persy.exists_index("index1").expect("exists works"));
});
}
#[test]
fn test_create_put_index_same_tx() {
create_and_drop("create_crate_put", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>("index1", ValueMode::Cluster)
.expect("index created correctly");
tx.put::<u8, u8>("index1", 10, 12).expect("put works correctly");
tx.put::<u8, u8>("index1", 11, 12).expect("put works correctly");
tx.put::<u8, u8>("index1", 12, 12).expect("put works correctly");
tx.put::<u8, u8>("index1", 13, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>("index1", &10).expect("get works correctly");
assert_eq!(Some(12), res.next());
let mut res = persy.get::<u8, u8>("index1", &11).expect("get works correctly");
assert_eq!(Some(12), res.next());
let mut res = persy.get::<u8, u8>("index1", &12).expect("get works correctly");
assert_eq!(Some(12), res.next());
let mut res = persy.get::<u8, u8>("index1", &13).expect("get works correctly");
assert_eq!(Some(12), res.next());
let res = persy.range::<u8, u8, _>("index1", ..).expect("get works correctly");
assert_eq!(4, res.count());
let mut tx = persy.begin().expect("begin transaction works");
tx.drop_index("index1").expect("index created correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_create_put_remove_get_drop_index_same_tx() {
create_and_drop("create_put_remove_get_drop_index", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>("index1", ValueMode::Cluster)
.expect("index created correctly");
tx.put::<u8, u8>("index1", 10, 12).expect("put works correctly");
let mut res = tx.get::<u8, u8>("index1", &10).expect("get works correctly");
assert_eq!(Some(12), res.next());
tx.remove::<u8, u8>("index1", 10, None).expect("put works correctly");
let res = tx.get::<u8, u8>("index1", &10).expect("get works correctly");
assert_eq!(0, res.len());
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
tx.drop_index("index1").expect("index created correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[derive(Debug)]
struct TErr {
_pe: PersyError,
}
impl<T: Into<PersyError>> From<PE<T>> for TErr {
fn from(e: PE<T>) -> Self {
TErr { _pe: e.error().into() }
}
}
fn test_for_type<K: IndexType, V>(persy: &Persy, name: &str, k: K, v: V) -> Result<(), TErr>
where
V: IndexType + std::fmt::Debug + PartialEq,
{
let mut tx = persy.begin()?;
tx.create_index::<K, V>(name, ValueMode::Cluster)?;
tx.put::<K, V>(name, k.clone(), v.clone())?;
let mut res = tx.get::<K, V>(name, &k)?;
assert_eq!(Some(v.clone()), res.next());
let prep = tx.prepare()?;
prep.commit()?;
let mut res = persy.get::<K, V>(name, &k)?;
assert_eq!(Some(v), res.next());
let mut tx = persy.begin()?;
tx.remove::<K, V>(name, k.clone(), None)?;
let res = tx.get::<K, V>(name, &k)?;
assert!(res.len() == 0);
let prep = tx.prepare()?;
prep.commit()?;
let res = persy.get::<K, V>(name, &k)?;
assert!(res.len() == 0);
let mut tx = persy.begin()?;
tx.drop_index(name)?;
let prep = tx.prepare()?;
prep.commit()?;
Ok(())
}
#[test]
fn test_all_indexable_types() {
create_and_drop("all_indexable_types", |persy| {
test_for_type::<u8, u8>(persy, "idx_u8", 10, 10).expect("test pass");
test_for_type::<u16, u16>(persy, "idx_u16", 10, 10).expect("test pass");
test_for_type::<u32, u32>(persy, "idx_u32", 10, 10).expect("test pass");
test_for_type::<u64, u64>(persy, "idx_u64", 10, 10).expect("test pass");
test_for_type::<u128, u128>(persy, "idx_u128", 10, 10).expect("test pass");
test_for_type::<i8, i8>(persy, "idx_i8", 10, 10).expect("test pass");
test_for_type::<i16, i16>(persy, "idx_i16", 10, 10).expect("test pass");
test_for_type::<i32, i32>(persy, "idx_i32", 10, 10).expect("test pass");
test_for_type::<i64, i64>(persy, "idx_i64", 10, 10).expect("test pass");
test_for_type::<i128, i128>(persy, "idx_i128", 10, 10).expect("test pass");
test_for_type::<f32, f32>(persy, "idx_f32", 10.0, 10.0).expect("test pass");
test_for_type::<f64, f64>(persy, "idx_f64", 10.0, 10.0).expect("test pass");
test_for_type::<String, String>(persy, "idx_string", "key".to_string(), "value".to_string())
.expect("test pass");
test_for_type::<ByteVec, ByteVec>(persy, "idx_bytevec", vec![10; 10].into(), vec![10; 10].into())
.expect("test pass");
});
}
#[test]
fn test_put_get_index() {
create_and_drop_index("create_drop_index", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
});
}
#[test]
fn test_put_get_tx_index() {
create_and_drop_index("create_put_get_tx_index", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
});
}
#[test]
fn test_put_remove_index() {
create_and_drop_index("create_put_remove_index", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
let mut tx = persy.begin().expect("begin transaction works");
tx.remove::<u8, u8>(index_name, 10, None).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.len(), 0);
});
}
#[test]
fn test_duplicate_put() {
create_and_drop_index_mode("duplicate_put", ValueMode::Exclusive, |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 20).expect("put works correctly");
assert!(tx.prepare().is_err());
});
}
#[test]
fn test_same_value_no_duplicate_put() {
create_and_drop_index_mode("same_value_no_duplicate", ValueMode::Exclusive, |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
});
}
#[test]
fn test_duplicate_second_put() {
create_and_drop_index_mode("create_drop_index", ValueMode::Exclusive, |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 20).expect("put works correctly");
assert!(tx.prepare().is_err());
});
}
#[test]
fn test_duplicate_tx_put() {
create_and_drop_index_mode("duplicate_put_tx", ValueMode::Exclusive, |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 20).expect("put works correctly");
assert!(tx.get::<u8, u8>(index_name, &10).is_err());
});
}
#[test]
fn test_same_value_no_duplicate_put_tx() {
create_and_drop_index_mode(
"some_value_no_duplicate_put_tx",
ValueMode::Exclusive,
|persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let mut value = tx.get::<u8, u8>(index_name, &10).expect("get works");
assert_eq!(value.next(), Some(12));
},
);
}
#[test]
fn test_put_one_index() {
create_and_drop_index("put_one_index", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let res = tx.one::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res, Some(12));
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let snap = persy.snapshot().expect("snapshot ok");
let res = snap.one::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res, Some(12));
let res = persy.one::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res, Some(12));
});
}
#[test]
fn test_put_remove_index_one_tx() {
create_and_drop_index("put_remove_index_one", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, None).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.len(), 0);
});
}
#[test]
fn test_multiple_values_put_get() {
create_and_drop_index("multiple_values_put", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 14).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.collect::<Vec<_>>(), vec![12, 14]);
});
}
#[test]
fn test_multiple_values_put_get_tx() {
create_and_drop_index("multiple_values_put_get_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 14).expect("put works correctly");
let res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.collect::<Vec<_>>(), vec![12, 14]);
});
}
#[test]
fn test_multiple_put_same_value_get() {
create_and_drop_index("multiple_put same_value_gut", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
});
}
#[test]
fn test_multiple_put_same_value_intervalled_get() {
create_and_drop_index("multiple_put same_value_intervalled_get", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 14).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
});
}
#[test]
fn test_multiple_put_remove_same_value_intervalled_get() {
create_and_drop_index("multiple_put remove_same_value_intervalled_get", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 14).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
let mut tx = persy.begin().expect("begin transaction works");
tx.remove::<u8, u8>(index_name, 10, Some(12))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(11))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(13))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(12))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(13))
.expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
});
}
#[test]
fn test_multiple_put_same_value_intervalled_get_same_tx() {
create_and_drop_index(
"multiple_put same_value_intervalled_get_same_tx",
|persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 14).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
},
);
}
#[test]
fn test_multiple_put_same_value_inverted_order_get_same_tx() {
create_and_drop_index("multiple_put same_value_inverted_get_same_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 11).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(11));
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), None);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(11));
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), None);
});
}
#[test]
fn test_multiple_put_remove_same_value_inverted_order_get_same_tx() {
create_and_drop_index(
"multiple_put_remove_same_value_inverted_order_get_same_tx",
|persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 11).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 13).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(11));
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), None);
tx.remove::<u8, u8>(index_name, 10, Some(12))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(11))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(13))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(12))
.expect("put works correctly");
tx.remove::<u8, u8>(index_name, 10, Some(13))
.expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), None);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), None);
},
);
}
#[test]
fn test_index_browse() {
create_and_drop_index("test_index_browse", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let start = 10;
let to = 29;
let mut count = to - start;
let mut iter: IndexIter<u8, u8> = persy.range(index_name, ..).expect("browse works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
});
}
#[test]
fn test_index_range() {
create_and_drop_index("test_index_range", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let start = 13;
let to = 24;
let mut count = to - start;
let mut iter: IndexIter<u8, u8> = persy.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
});
}
#[test]
fn test_index_range_rev() {
create_and_drop_index("test_index_range_rev", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let start = 13;
let to = 24;
let mut count = to - start;
let base: IndexIter<u8, u8> = persy.range(index_name, start..=to).expect("range works correctly");
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().0, to);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(start), last);
assert_eq!(0, count);
});
}
#[test]
fn test_index_range_miss_direct_rev() {
create_and_drop_index("test_index_range_miss_direct_rev", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 20..30 {
tx.put::<u8, u8>(index_name, n, n).expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut base: IndexIter<u8, u8> = persy.range(index_name, ..=5).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
let mut base: IndexIter<u8, u8> = persy.range(index_name, 40..).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
let mut base: IndexIter<u8, u8> = persy.range(index_name, 2..8).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
});
}
#[test]
fn test_index_range_miss_direct_rev_tx() {
create_and_drop_index("test_index_range_miss_direct_rev", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 20..30 {
tx.put::<u8, u8>(index_name, n, n).expect("put works correctly");
}
let mut base: TxIndexIter<u8, u8> = tx.range(index_name, ..=5).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
let mut base: TxIndexIter<u8, u8> = tx.range(index_name, 40..).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
let mut base: TxIndexIter<u8, u8> = tx.range(index_name, 2..8).expect("range works correctly");
assert!(base.next().is_none());
let mut iter = base.rev();
assert!(iter.next().is_none());
let mut base: TxIndexIter<u8, u8> = tx.range(index_name, 28..40).expect("range works correctly");
assert_eq!(base.next().unwrap().1.next(), Some(28));
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().1.next(), Some(29));
assert!(iter.next().is_none());
});
}
#[test]
fn test_index_browse_tx() {
create_and_drop_index("test_index_browse_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let start = 10;
let to = 29;
let mut count = to - start;
let mut last = None;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, ..).expect("browse works correctly");
assert_eq!(iter.next().unwrap().0, start);
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx() {
create_and_drop_index("test_index_range_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
tx.remove::<u8, u8>(index_name, 20, None).expect("remove works");
let start = 13;
let to = 24;
let mut count = to - start - 1;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
}
let mut count = to - start - 2;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(to - 1), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx_off() {
create_and_drop_index("test_index_range_tx_off", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n * 2, 12).expect("put works correctly");
}
tx.remove::<u8, u8>(index_name, 20, None).expect("remove works");
let start = 23;
let to = 39;
let mut count = (to - start) / 2 - 1;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start + 1);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(to - 1), last);
assert_eq!(0, count);
}
let mut count = (to - start) / 2 - 1;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start + 1);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(to - 1), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx_access() {
create_and_drop_index("test_index_range_tx_access", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.create_segment("seg").expect("create segment");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let start = 13;
let to = 24;
let mut count = to - start;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
iter.tx().insert("seg", "data".as_bytes()).expect("insert works");
let mut last = None;
while let Some(mut x) = iter.next_tx() {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
x.2.insert("seg", "data".as_bytes()).expect("insert works");
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx_rev() {
create_and_drop_index("test_index_range_tx_rev", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
tx.remove::<u8, u8>(index_name, 20, None).expect("remove works");
let start = 13;
let to = 24;
let mut count = to - start - 1;
{
let base: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().0, to);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(start), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx_change_committed() {
create_and_drop_index("test_index_range_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
tx.prepare().expect("prepare works").commit().expect("commit works");
let mut tx = persy.begin().expect("begin transaction works");
tx.remove::<u8, u8>(index_name, 20, None).expect("remove works");
tx.put::<u8, u8>(index_name, 31, 12).expect("put works correctly");
let start = 13;
let to = 31;
let mut count = to - start - 2;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
}
let mut count = to - start - 2;
{
let base: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().0, to);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
assert!(x.0 != 20u8);
count -= 1;
}
assert_eq!(Some(start), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_index_range_tx_multiple_change_committed() {
create_and_drop_index("test_index_range_tx", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
tx.prepare().expect("prepare works").commit().expect("commit works");
let mut tx = persy.begin().expect("begin transaction works");
for n in 10..20 {
tx.remove::<u8, u8>(index_name, n, None).expect("remove works");
}
for n in 5..20 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works");
}
let start = 5;
let to = 25;
let mut count = to - start;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
}
let mut count = to - start;
{
let base: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().0, to);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(start), last);
assert_eq!(0, count);
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_range_tx_created_in_tx() {
create_and_drop("range_created_in_tx", |persy| {
let index_name = "index1";
let mut tx = persy.begin().expect("begin transaction works");
tx.create_index::<u8, u8>(index_name, ValueMode::Cluster)
.expect("index created correctly");
for n in 10..30 {
tx.put::<u8, u8>(index_name, n, 12).expect("put works correctly");
}
let start = 13;
let to = 24;
let mut count = to - start;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(to), last);
assert_eq!(0, count);
}
let mut count = to - start - 1;
{
let mut iter: TxIndexIter<u8, u8> = tx.range(index_name, start..to).expect("range works correctly");
assert_eq!(iter.next().unwrap().0, start);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(to - 1), last);
assert_eq!(0, count);
}
let mut count = to - start;
{
let base: TxIndexIter<u8, u8> = tx.range(index_name, start..=to).expect("range works correctly");
let mut iter = base.rev();
assert_eq!(iter.next().unwrap().0, to);
let mut last = None;
for mut x in iter {
last = Some(x.0.clone());
assert_eq!(x.1.next(), Some(12));
count -= 1;
}
assert_eq!(Some(start), last);
assert_eq!(0, count);
}
let mut base: TxIndexIter<u8, u8> = tx.range(index_name, 100..=200).expect("range works correctly");
assert!(base.next().is_none());
let base: TxIndexIter<u8, u8> = tx.range(index_name, 100..=200).expect("range works correctly");
assert!(base.rev().next().is_none());
tx.prepare()
.expect("prepeare successfult")
.commit()
.expect("commit successful");
let mut tx = persy.begin().expect("begin transaction works");
tx.drop_index("index1").expect("index created correctly");
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
});
}
#[test]
fn test_mupltiple_put_same_value_get_tx() {
create_and_drop_index("create_drop_index", |persy, index_name| {
let mut tx = persy.begin().expect("begin transaction works");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
tx.put::<u8, u8>(index_name, 10, 12).expect("put works correctly");
let mut res = tx.get::<u8, u8>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
});
}
#[test]
pub fn test_list_indexes() {
create_and_drop("test_list_indexes", |persy| {
let mut tx = persy.begin().expect("error on transaction begin");
tx.create_index::<u8, u8>("one", ValueMode::Replace)
.expect("error on index creation");
tx.create_index::<u32, u32>("two", ValueMode::Replace)
.expect("error on index creation");
let fin = tx.prepare().expect("error on commit prepare");
fin.commit().expect("error on commit");
let indexes = persy.list_indexes().expect("list indexes works as expected");
assert_eq!(indexes.len(), 2);
let names = indexes.into_iter().map(|x| x.0).collect::<Vec<String>>();
assert!(names.contains(&"one".to_string()));
assert!(names.contains(&"two".to_string()));
let segments = persy.list_segments().expect("list segments works as expected");
assert_eq!(segments.len(), 0);
});
}
#[test]
pub fn test_list_indexes_tx() {
create_and_drop("test_list_indexes", |persy| {
let mut tx = persy.begin().expect("error on transaction begin");
tx.create_index::<u8, u8>("one", ValueMode::Replace)
.expect("error on index creation");
tx.create_index::<u32, u32>("two", ValueMode::Replace)
.expect("error on index creation");
let fin = tx.prepare().expect("error on commit prepare");
fin.commit().expect("error on commit");
let mut tx = persy.begin().expect("error on transaction begin");
tx.create_index::<u8, u8>("three", ValueMode::Replace)
.expect("error on index creation");
tx.drop_index("two").expect("error on index creation");
let indexes = tx.list_indexes().expect("list indexes works as expected");
assert_eq!(indexes.len(), 2);
let names = indexes.into_iter().map(|x| x.0).collect::<Vec<String>>();
assert!(names.contains(&"one".to_string()));
assert!(names.contains(&"three".to_string()));
let segments = tx.list_segments().expect("list segments works as expected");
assert_eq!(segments.len(), 0);
});
}
#[test]
fn test_grow_and_shrink() {
create_and_drop("grow_and_shrink", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
let index_name = "grow_and_shrink";
tx.create_index::<i32, i32>(index_name, ValueMode::Cluster).unwrap();
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut tx = persy.begin().expect("begin transaction works");
for v in 0..1000 {
tx.put::<i32, i32>(index_name, v, 12).expect("put works correctly");
tx.put::<i32, i32>(index_name, v, 13).expect("put works correctly");
tx.put::<i32, i32>(index_name, v, 14).expect("put works correctly");
if v % 100 == 0 {
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
tx = persy.begin().expect("begin transaction works");
}
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<i32, i32>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
assert_eq!(res.next(), Some(13));
assert_eq!(res.next(), Some(14));
assert_eq!(res.next(), None);
let count = persy
.range::<i32, i32, _>(index_name, ..)
.expect("get works correctly")
.count();
assert_eq!(count, 1000);
let mut tx = persy.begin().expect("begin transaction works");
for v in 0..1000 {
tx.remove::<i32, i32>(index_name, v, None).expect("put works correctly");
if v % 100 == 0 {
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
tx = persy.begin().expect("begin transaction works");
}
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut res = persy.get::<i32, i32>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), None);
let count = persy
.range::<i32, i32, _>(index_name, ..)
.expect("get works correctly")
.count();
assert_eq!(count, 0);
});
}
#[test]
fn test_big_delete_txs() {
create_and_drop("big_delete_txs", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
let index_name = "big_delete_txs";
tx.create_index::<i32, i32>(index_name, ValueMode::Cluster).unwrap();
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let all: Vec<i32> = (1..=100000).into_iter().collect();
for chunk in all.chunks(20000) {
let mut tx = persy.begin().expect("begin transaction works");
for k in chunk {
tx.put::<i32, i32>(index_name, *k, 12).expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
}
let mut res = persy.get::<i32, i32>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
for x in 1..10 {
let iter = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works")
.into_iter()
.take(10000 as usize);
let mut tx = persy.begin().expect("begin transaction works");
let mut last = 0;
for (id, _values) in iter {
tx.remove::<i32, i32>(index_name, id, None)
.expect("put works correctly");
last = id;
}
println!("last {}", last);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
let mut r = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works correctly");
assert_eq!(r.next().map(|(k, _)| k), Some((x * 10000) + 1));
let r = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works correctly");
assert_eq!(r.rev().next().map(|(k, _)| k), Some(100000));
}
});
}
#[test]
fn test_less_big_delete_txs() {
create_and_drop("less_big_delete_txs", |persy| {
let mut tx = persy.begin().expect("begin transaction works");
let index_name = "less_big_delete_txs";
tx.create_index::<i32, i32>(index_name, ValueMode::Cluster).unwrap();
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
for x in 0..80 {
let mut tx = persy.begin().expect("begin transaction works");
for k in 0..1000 {
tx.put::<i32, i32>(index_name, (x * 1000) + k, 12)
.expect("put works correctly");
}
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
}
#[cfg(feature = "experimental_inspect")]
persy::inspect::PersyInspect::inspect_tree::<i32, i32, _>(
persy,
index_name,
&mut persy::inspect::PrintTreeInspector::new(),
)
.unwrap();
let mut res = persy.get::<i32, i32>(index_name, &10).expect("get works correctly");
assert_eq!(res.next(), Some(12));
for _x in 1..5 {
let iter = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works")
.into_iter()
.take(10000 as usize);
let val = iter.map(|(k, _)| k).collect::<Vec<_>>();
println!("{:?}", val);
let mut tx = persy.begin().expect("begin transaction works");
let mut last = 0;
for id in val {
tx.remove::<i32, i32>(index_name, id, None)
.expect("put works correctly");
last = id;
}
println!("last {}", last);
let prep = tx.prepare().expect("prepare with index works");
prep.commit().expect("commit with index works");
#[cfg(feature = "experimental_inspect")]
persy::inspect::PersyInspect::inspect_tree::<i32, i32, _>(
persy,
index_name,
&mut persy::inspect::PrintTreeInspector::new(),
)
.unwrap();
let mut r = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works correctly");
assert_eq!(r.next().map(|(k, _)| k), Some(last + 1));
let r = persy
.range::<i32, i32, _>(index_name, ..)
.expect("range works correctly");
assert_eq!(r.rev().next().map(|(k, _)| k), Some(79999));
}
});
}