mod helpers; use helpers::create_and_drop; use persy::{ByteVec, IndexIter, IndexType, TxIndexIter, ValueMode, PE}; use persy::{Persy, PersyError}; fn create_and_drop_index(test: &str, f: F) where F: FnOnce(&Persy, &str), { create_and_drop_index_mode(test, ValueMode::Cluster, f); } fn create_and_drop_index_mode(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::("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::("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::("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::("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::("index1", ValueMode::Cluster) .expect("index created correctly"); tx.put::("index1", 10, 12).expect("put works correctly"); tx.put::("index1", 11, 12).expect("put works correctly"); tx.put::("index1", 12, 12).expect("put works correctly"); tx.put::("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::("index1", &10).expect("get works correctly"); assert_eq!(Some(12), res.next()); let mut res = persy.get::("index1", &11).expect("get works correctly"); assert_eq!(Some(12), res.next()); let mut res = persy.get::("index1", &12).expect("get works correctly"); assert_eq!(Some(12), res.next()); let mut res = persy.get::("index1", &13).expect("get works correctly"); assert_eq!(Some(12), res.next()); let res = persy.range::("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::("index1", ValueMode::Cluster) .expect("index created correctly"); tx.put::("index1", 10, 12).expect("put works correctly"); let mut res = tx.get::("index1", &10).expect("get works correctly"); assert_eq!(Some(12), res.next()); tx.remove::("index1", 10, None).expect("put works correctly"); let res = tx.get::("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> From> for TErr { fn from(e: PE) -> Self { TErr { _pe: e.error().into() } } } fn test_for_type(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::(name, ValueMode::Cluster)?; tx.put::(name, k.clone(), v.clone())?; let mut res = tx.get::(name, &k)?; assert_eq!(Some(v.clone()), res.next()); let prep = tx.prepare()?; prep.commit()?; let mut res = persy.get::(name, &k)?; assert_eq!(Some(v), res.next()); let mut tx = persy.begin()?; tx.remove::(name, k.clone(), None)?; let res = tx.get::(name, &k)?; assert!(res.len() == 0); let prep = tx.prepare()?; prep.commit()?; let res = persy.get::(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::(persy, "idx_u8", 10, 10).expect("test pass"); test_for_type::(persy, "idx_u16", 10, 10).expect("test pass"); test_for_type::(persy, "idx_u32", 10, 10).expect("test pass"); test_for_type::(persy, "idx_u64", 10, 10).expect("test pass"); test_for_type::(persy, "idx_u128", 10, 10).expect("test pass"); test_for_type::(persy, "idx_i8", 10, 10).expect("test pass"); test_for_type::(persy, "idx_i16", 10, 10).expect("test pass"); test_for_type::(persy, "idx_i32", 10, 10).expect("test pass"); test_for_type::(persy, "idx_i64", 10, 10).expect("test pass"); test_for_type::(persy, "idx_i128", 10, 10).expect("test pass"); test_for_type::(persy, "idx_f32", 10.0, 10.0).expect("test pass"); test_for_type::(persy, "idx_f64", 10.0, 10.0).expect("test pass"); test_for_type::(persy, "idx_string", "key".to_string(), "value".to_string()) .expect("test pass"); test_for_type::(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::(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::(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::(index_name, 10, 12).expect("put works correctly"); let mut res = tx.get::(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::(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::(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::(index_name, &10).expect("get works correctly"); assert_eq!(res.next(), Some(12)); let mut tx = persy.begin().expect("begin transaction works"); tx.remove::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(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::(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::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 20).expect("put works correctly"); assert!(tx.get::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 12).expect("put works correctly"); let mut value = tx.get::(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::(index_name, 10, 12).expect("put works correctly"); let res = tx.one::(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::(index_name, &10).expect("get works correctly"); assert_eq!(res, Some(12)); let res = persy.one::(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::(index_name, 10, 12).expect("put works correctly"); tx.remove::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(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::(index_name, &10).expect("get works correctly"); assert_eq!(res.collect::>(), 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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 14).expect("put works correctly"); let res = tx.get::(index_name, &10).expect("get works correctly"); assert_eq!(res.collect::>(), 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::(index_name, 10, 12).expect("put works correctly"); tx.put::(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::(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::(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::(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::(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::(index_name, 10, 12).expect("put works correctly"); let mut res = tx.get::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); tx.put::(index_name, 10, 14).expect("put works correctly"); tx.put::(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::(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::(index_name, 10, Some(12)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(11)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(13)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(12)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(13)) .expect("put works correctly"); let mut res = tx.get::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); tx.put::(index_name, 10, 14).expect("put works correctly"); tx.put::(index_name, 10, 12).expect("put works correctly"); let mut res = tx.get::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 11).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); tx.put::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); let mut res = tx.get::(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::(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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 11).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); tx.put::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 13).expect("put works correctly"); let mut res = tx.get::(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::(index_name, 10, Some(12)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(11)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(13)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(12)) .expect("put works correctly"); tx.remove::(index_name, 10, Some(13)) .expect("put works correctly"); let mut res = tx.get::(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::(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::(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 = 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::(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 = 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::(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 = 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::(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 = 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 = 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 = 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::(index_name, n, n).expect("put works correctly"); } let mut base: TxIndexIter = 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 = 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 = 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 = 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::(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 = 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::(index_name, n, 12).expect("put works correctly"); } tx.remove::(index_name, 20, None).expect("remove works"); let start = 13; let to = 24; let mut count = to - start - 1; { let mut iter: TxIndexIter = 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 = 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::(index_name, n * 2, 12).expect("put works correctly"); } tx.remove::(index_name, 20, None).expect("remove works"); let start = 23; let to = 39; let mut count = (to - start) / 2 - 1; { let mut iter: TxIndexIter = 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 = 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::(index_name, n, 12).expect("put works correctly"); } let start = 13; let to = 24; let mut count = to - start; { let mut iter: TxIndexIter = 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::(index_name, n, 12).expect("put works correctly"); } tx.remove::(index_name, 20, None).expect("remove works"); let start = 13; let to = 24; let mut count = to - start - 1; { let base: TxIndexIter = 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::(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::(index_name, 20, None).expect("remove works"); tx.put::(index_name, 31, 12).expect("put works correctly"); let start = 13; let to = 31; let mut count = to - start - 2; { let mut iter: TxIndexIter = 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 = 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::(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::(index_name, n, None).expect("remove works"); } for n in 5..20 { tx.put::(index_name, n, 12).expect("put works"); } let start = 5; let to = 25; let mut count = to - start; { let mut iter: TxIndexIter = 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 = 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::(index_name, ValueMode::Cluster) .expect("index created correctly"); for n in 10..30 { tx.put::(index_name, n, 12).expect("put works correctly"); } let start = 13; let to = 24; let mut count = to - start; { let mut iter: TxIndexIter = 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 = 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 = 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 = tx.range(index_name, 100..=200).expect("range works correctly"); assert!(base.next().is_none()); let base: TxIndexIter = 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::(index_name, 10, 12).expect("put works correctly"); tx.put::(index_name, 10, 12).expect("put works correctly"); let mut res = tx.get::(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::("one", ValueMode::Replace) .expect("error on index creation"); tx.create_index::("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::>(); 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::("one", ValueMode::Replace) .expect("error on index creation"); tx.create_index::("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::("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::>(); 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::(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::(index_name, v, 12).expect("put works correctly"); tx.put::(index_name, v, 13).expect("put works correctly"); tx.put::(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::(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::(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::(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::(index_name, &10).expect("get works correctly"); assert_eq!(res.next(), None); let count = persy .range::(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::(index_name, ValueMode::Cluster).unwrap(); let prep = tx.prepare().expect("prepare with index works"); prep.commit().expect("commit with index works"); let all: Vec = (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::(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::(index_name, &10).expect("get works correctly"); assert_eq!(res.next(), Some(12)); for x in 1..10 { let iter = persy .range::(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::(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::(index_name, ..) .expect("range works correctly"); assert_eq!(r.next().map(|(k, _)| k), Some((x * 10000) + 1)); let r = persy .range::(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::(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::(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::( persy, index_name, &mut persy::inspect::PrintTreeInspector::new(), ) .unwrap(); let mut res = persy.get::(index_name, &10).expect("get works correctly"); assert_eq!(res.next(), Some(12)); for _x in 1..5 { let iter = persy .range::(index_name, ..) .expect("range works") .into_iter() .take(10000 as usize); let val = iter.map(|(k, _)| k).collect::>(); println!("{:?}", val); let mut tx = persy.begin().expect("begin transaction works"); let mut last = 0; for id in val { tx.remove::(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::( persy, index_name, &mut persy::inspect::PrintTreeInspector::new(), ) .unwrap(); let mut r = persy .range::(index_name, ..) .expect("range works correctly"); assert_eq!(r.next().map(|(k, _)| k), Some(last + 1)); let r = persy .range::(index_name, ..) .expect("range works correctly"); assert_eq!(r.rev().next().map(|(k, _)| k), Some(79999)); } }); }