Mercurial > lbo > hg > leveldb-rs
changeset 335:c444cc8d2606
db_iter: Add iterator direction moving test.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Tue, 03 Oct 2017 20:41:18 +0200 |
parents | 5956ad13bc49 |
children | 0a8b22c98f09 |
files | src/db_iter.rs |
diffstat | 1 files changed, 62 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/db_iter.rs Mon Oct 02 19:48:42 2017 +0200 +++ b/src/db_iter.rs Tue Oct 03 20:41:18 2017 +0200 @@ -101,14 +101,27 @@ fn find_prev_user_entry(&mut self) -> bool { assert!(self.dir == Direction::Reverse); let mut value_type = ValueType::TypeDeletion; + let mut newsavedval = vec![]; + + // The iterator should be already set to the previous entry if this is a direction change + // (i.e. first prev() call after advance()). savedkey is set to the key of that entry. + // + // We read the current entry, ignore it for comparison (because value_type is Deletion), + // assign it to savedkey and savedval and go back another step (at the end of the loop). + // + // We then look at the entry one *before* the entry we want to return. We check it against + // the saved key (still containing the key of the desired entry), see that it's less-than, + // and break. The key and value of the desired entry are in savedkey and savedval. while self.iter.valid() { - self.iter.current(&mut self.buf, &mut self.savedval); + self.iter.current(&mut self.buf, &mut newsavedval); self.record_read_sample(); let (typ, seq, ukey) = parse_internal_key(&self.buf); + println!("current: {:?} / {:?}", ukey, self.savedval); if seq > 0 && seq <= self.ss.sequence() { if value_type != ValueType::TypeDeletion && self.cmp.cmp(ukey, &self.savedkey) == Ordering::Less { + println!("found previous key {:?} / {:?}", ukey, self.savedval); // We found a non-deleted entry for a previous key (in the previous iteration) break; } @@ -119,6 +132,8 @@ } else { self.savedkey.clear(); self.savedkey.extend_from_slice(&ukey); + self.savedval.clear(); + self.savedval.extend_from_slice(&newsavedval); } } self.iter.prev(); @@ -206,6 +221,7 @@ newsavedkey.clear(); newsavedkey.extend_from_slice(parse_internal_key(&self.buf).2); if self.cmp.cmp(&newsavedkey, &self.savedkey) == Ordering::Less { + println!("breaking with {:?} / {:?}", newsavedkey, self.savedval); break; } } @@ -257,10 +273,9 @@ #[cfg(test)] mod tests { use super::*; - use types::current_key_val; + use types::{current_key_val, Direction}; use db_impl::testutil::*; - // not yet passing #[test] fn db_iter_basic_test() { let mut db = build_db(); @@ -276,4 +291,48 @@ assert_eq!((k.to_vec(), v.to_vec()), current_key_val(&iter).unwrap()); } } + + #[test] + fn db_iter_test_fwd_backwd() { + let mut db = build_db(); + 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", + b"val3"]; + + // This specifies the direction that the iterator should move to. Based on this, an index + // into keys/vals is incremented/decremented so that we get a nice test checking iterator + // move correctness. + let dirs: &[Direction] = &[Direction::Forward, + Direction::Forward, + Direction::Forward, + Direction::Reverse, + Direction::Reverse, + Direction::Forward, + Direction::Forward, + Direction::Reverse, + Direction::Forward, + Direction::Forward, + Direction::Forward, + Direction::Forward]; + let mut i = 0; + iter.advance(); + for d in dirs { + println!("i = {}", i); + assert_eq!((keys[i].to_vec(), vals[i].to_vec()), + current_key_val(&iter).unwrap()); + match *d { + Direction::Forward => { + assert!(iter.advance()); + i += 1; + } + Direction::Reverse => { + assert!(iter.prev()); + i -= 1; + } + } + } + } }