Mercurial > lbo > hg > leveldb-rs
changeset 367:821c6108558f
version/DB: Set test data into correct otder and add iterator test.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 08 Oct 2017 12:28:12 +0200 |
parents | 8ae87daebe4a |
children | 1dc6ed532dae |
files | src/db_impl.rs src/db_iter.rs src/version.rs |
diffstat | 3 files changed, 86 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/src/db_impl.rs Sun Oct 08 11:46:05 2017 +0200 +++ b/src/db_impl.rs Sun Oct 08 12:28:12 2017 +0200 @@ -95,7 +95,7 @@ /// Opens or creates* a new or existing database. /// /// *depending on the options set (create_if_missing, error_if_exists). - fn open(name: &str, opt: Options) -> Result<DB> { + pub fn open(name: &str, opt: Options) -> Result<DB> { let mut db = DB::new(name, opt); let mut ve = VersionEdit::new(); let save_manifest = db.recover(&mut ve)?; @@ -964,7 +964,7 @@ use version::testutil::make_version; /// build_db creates a database filled with the tables created by make_version(). - pub fn build_db() -> DB { + pub fn build_db() -> (DB, Options) { let name = "db"; let (v, opt) = make_version(); let mut ve = VersionEdit::new(); @@ -988,7 +988,7 @@ lw.flush().unwrap(); set_current_file(&opt.env, name, 10).unwrap(); - DB::open(name, opt).unwrap() + (DB::open(name, opt.clone()).unwrap(), opt) } /// set_file_to_compact ensures that the specified table file will be compacted next. @@ -1213,7 +1213,7 @@ #[allow(unused_variables)] #[test] fn test_db_impl_build_db_sanity() { - let db = build_db(); + let db = build_db().0; let env = &db.opt.env; let name = &db.name; @@ -1222,7 +1222,7 @@ #[test] fn test_db_impl_get_from_table_with_snapshot() { - let mut db = build_db(); + let mut db = build_db().0; assert_eq!(28, db.vset.borrow().last_seq); @@ -1254,11 +1254,15 @@ assert_eq!("val2".as_bytes(), db.get_at(&ss, "eab".as_bytes()).unwrap().unwrap().as_slice()); } + + // from table. + assert_eq!("val2".as_bytes(), + db.get("cab".as_bytes()).unwrap().as_slice()); } #[test] fn test_db_impl_delete() { - let mut db = build_db(); + let mut db = build_db().0; db.put(b"xyy", b"123").unwrap(); db.put(b"xyz", b"123").unwrap(); @@ -1277,7 +1281,7 @@ #[test] fn test_db_impl_compact_single_file() { - let mut db = build_db(); + let mut db = build_db().0; set_file_to_compact(&mut db, 4); db.maybe_do_compaction().unwrap(); @@ -1346,7 +1350,7 @@ #[test] fn test_db_impl_compaction() { - let mut db = build_db(); + let mut db = build_db().0; let v = db.current(); v.borrow_mut().compaction_score = Some(2.0); v.borrow_mut().compaction_level = Some(1); @@ -1407,7 +1411,7 @@ fn test_db_impl_open_close_reopen() { let opt; { - let mut db = build_db(); + let mut db = build_db().0; opt = db.opt.clone(); db.put(b"xx1", b"111").unwrap();
--- a/src/db_iter.rs Sun Oct 08 11:46:05 2017 +0200 +++ b/src/db_iter.rs Sun Oct 08 12:28:12 2017 +0200 @@ -276,16 +276,21 @@ use super::*; use types::{current_key_val, Direction}; use test_util::LdbIteratorIter; + use db_impl::DB; use db_impl::testutil::*; + use std::collections::HashMap; + use std::collections::HashSet; + use std::iter::FromIterator; + #[test] fn db_iter_basic_test() { - let mut db = build_db(); + let mut db = build_db().0; let mut iter = db.new_iter().unwrap(); // keys and values come from make_version(); they are each the latest entry. let keys: &[&[u8]] = &[b"aaa", b"aab", b"aax", b"aba", b"bab", b"bba", b"cab", b"cba"]; - let vals: &[&[u8]] = &[b"val0", b"val2", b"val1", b"val3", b"val2", b"val3", b"val1", + let vals: &[&[u8]] = &[b"val1", b"val2", b"val1", b"val3", b"val2", b"val3", b"val2", b"val3"]; for (k, v) in keys.iter().zip(vals.iter()) { @@ -296,7 +301,7 @@ #[test] fn db_iter_reset() { - let mut db = build_db(); + let mut db = build_db().0; let mut iter = db.new_iter().unwrap(); assert!(iter.advance()); @@ -309,12 +314,12 @@ #[test] fn db_iter_test_fwd_backwd() { - let mut db = build_db(); + let mut db = build_db().0; let mut iter = db.new_iter().unwrap(); // keys and values come from make_version(); they are each the latest entry. let keys: &[&[u8]] = &[b"aaa", b"aab", b"aax", b"aba", b"bab", b"bba", b"cab", b"cba"]; - let vals: &[&[u8]] = &[b"val0", b"val2", b"val1", b"val3", b"val2", b"val3", b"val1", + let vals: &[&[u8]] = &[b"val1", b"val2", b"val1", b"val3", b"val2", b"val3", b"val2", b"val3"]; // This specifies the direction that the iterator should move to. Based on this, an index @@ -353,12 +358,12 @@ #[test] fn db_iter_test_seek() { - let mut db = build_db(); + let mut db = build_db().0; let mut iter = db.new_iter().unwrap(); // gca is the deleted entry. let keys: &[&[u8]] = &[b"aab", b"aaa", b"cab", b"eaa", b"aaa", b"iba", b"fba"]; - let vals: &[&[u8]] = &[b"val2", b"val0", b"val1", b"val1", b"val0", b"val2", b"val3"]; + let vals: &[&[u8]] = &[b"val2", b"val1", b"val2", b"val1", b"val1", b"val2", b"val3"]; for (k, v) in keys.iter().zip(vals.iter()) { println!("{:?}", String::from_utf8(k.to_vec()).unwrap()); @@ -381,7 +386,7 @@ #[test] fn db_iter_deleted_entry_not_returned() { - let mut db = build_db(); + let mut db = build_db().0; let mut iter = db.new_iter().unwrap(); let must_not_appear = b"gca"; @@ -392,7 +397,7 @@ #[test] fn db_iter_deleted_entry_not_returned_memtable() { - let mut db = build_db(); + let mut db = build_db().0; db.put(b"xyz", b"123").unwrap(); db.delete(b"xyz", true).unwrap(); @@ -404,4 +409,51 @@ assert!(k.as_slice() != must_not_appear); } } + + #[test] + fn db_iter_repeated_open_close() { + let opt; + { + let (mut db, opt_) = build_db(); + opt = opt_; + + db.put(b"xx1", b"111").unwrap(); + db.put(b"xx2", b"112").unwrap(); + db.put(b"xx3", b"113").unwrap(); + db.put(b"xx4", b"114").unwrap(); + db.delete(b"xx2", false).unwrap(); + } + + { + let mut db = DB::open("db", opt.clone()).unwrap(); + db.put(b"xx4", b"222").unwrap(); + } + + { + let mut db = DB::open("db", opt).unwrap(); + + let ss = db.get_snapshot(); + + let expected: HashMap<Vec<u8>, Vec<u8>> = HashMap::from_iter(vec![ + (b"xx1".to_vec(), b"111".to_vec()), + (b"xx4".to_vec(), b"222".to_vec()), + (b"aaa".to_vec(), b"val1".to_vec()), + (b"cab".to_vec(), b"val2".to_vec()), + ] + .into_iter()); + let non_existing: HashSet<Vec<u8>> = HashSet::from_iter(vec![ + b"gca".to_vec(), + b"xx2".to_vec(), + ] + .into_iter()); + + let mut iter = db.new_iter_at(ss.clone()).unwrap(); + for (k, v) in LdbIteratorIter::wrap(&mut iter) { + if let Some(ev) = expected.get(&k) { + assert_eq!(ev, &v); + } + assert!(!non_existing.contains(&k)); + } + } + } }
--- a/src/version.rs Sun Oct 08 11:46:05 2017 +0200 +++ b/src/version.rs Sun Oct 08 12:28:12 2017 +0200 @@ -596,29 +596,31 @@ // The different levels overlap in a sophisticated manner to be able to test compactions // and so on. + // The sequence numbers are in "natural order", i.e. highest levels have lowest sequence + // numbers. // Level 0 (overlapping) let f1: &[(&[u8], &[u8], ValueType)] = &[("aaa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("aab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("aba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue)]; - let t1 = write_table(&env, f1, 1, 1); + let t1 = write_table(&env, f1, 25, 1); let f2: &[(&[u8], &[u8], ValueType)] = &[("aax".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("bab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("bba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue)]; - let t2 = write_table(&env, f2, 4, 2); + let t2 = write_table(&env, f2, 22, 2); // Level 1 let f3: &[(&[u8], &[u8], ValueType)] = &[("aaa".as_bytes(), "val0".as_bytes(), ValueType::TypeValue), ("cab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("cba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue)]; - let t3 = write_table(&env, f3, 7, 3); + let t3 = write_table(&env, f3, 19, 3); let f4: &[(&[u8], &[u8], ValueType)] = &[("daa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("dab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("dba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue)]; - let t4 = write_table(&env, f4, 10, 4); + let t4 = write_table(&env, f4, 16, 4); let f5: &[(&[u8], &[u8], ValueType)] = &[("eaa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("eab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), @@ -629,23 +631,23 @@ &[("cab".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("fab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("fba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue)]; - let t6 = write_table(&env, f6, 16, 6); + let t6 = write_table(&env, f6, 10, 6); let f7: &[(&[u8], &[u8], ValueType)] = &[("gaa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("gab".as_bytes(), "val2".as_bytes(), ValueType::TypeValue), ("gba".as_bytes(), "val3".as_bytes(), ValueType::TypeValue), ("gca".as_bytes(), "val4".as_bytes(), ValueType::TypeDeletion), ("gda".as_bytes(), "val5".as_bytes(), ValueType::TypeValue)]; - let t7 = write_table(&env, f7, 21, 7); + let t7 = write_table(&env, f7, 5, 7); // Level 3 (2 * 2 entries, for iterator behavior). let f8: &[(&[u8], &[u8], ValueType)] = &[("haa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("hba".as_bytes(), "val2".as_bytes(), ValueType::TypeValue)]; - let t8 = write_table(&env, f8, 23, 8); + let t8 = write_table(&env, f8, 3, 8); let f9: &[(&[u8], &[u8], ValueType)] = &[("iaa".as_bytes(), "val1".as_bytes(), ValueType::TypeValue), ("iba".as_bytes(), "val2".as_bytes(), ValueType::TypeValue)]; - let t9 = write_table(&env, f9, 25, 9); + let t9 = write_table(&env, f9, 1, 9); let cache = TableCache::new("db", opts.clone(), 100); @@ -734,9 +736,9 @@ fn test_version_get_simple() { let v = make_version().0; let cases: &[(&[u8], u64, Result<Option<Vec<u8>>>)] = - &[("aaa".as_bytes(), 0, Ok(None)), - ("aaa".as_bytes(), 1, Ok(Some("val1".as_bytes().to_vec()))), + &[("aaa".as_bytes(), 1, Ok(None)), ("aaa".as_bytes(), 100, Ok(Some("val1".as_bytes().to_vec()))), + ("aaa".as_bytes(), 21, Ok(Some("val0".as_bytes().to_vec()))), ("aab".as_bytes(), 0, Ok(None)), ("aab".as_bytes(), 100, Ok(Some("val2".as_bytes().to_vec()))), ("daa".as_bytes(), 100, Ok(Some("val1".as_bytes().to_vec()))),