From 2e367520ea1c33505514e7d20ba7b34431655c56 Mon Sep 17 00:00:00 2001 From: David Greenberg Date: Fri, 17 Jul 2015 09:56:29 -0400 Subject: [PATCH 1/2] Fix boxing problems and add more tests --- Cargo.toml | 13 ++++++- src/main.rs | 102 +++++++++++++------------------------------------ src/rocksdb.rs | 9 +++-- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90b2015..e722c47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,20 @@ name = "rocksdb" description = "A Rust wrapper for Facebook's RocksDB embeddable database." version = "0.0.6" -authors = ["Tyler Neely "] +authors = ["Tyler Neely ", "David Greenberg "] license = "Apache-2.0" +exclude = [ + ".gitignore", + ".travis.yml", + "deploy.sh", + "test/**/*", +] [features] default=[] valgrind=[] + +[[test]] + +name = "test" +path = "test/test.rs" diff --git a/src/main.rs b/src/main.rs index bb084cf..14f0d51 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,85 +20,35 @@ extern crate test; use rocksdb::{Options, RocksDB, MergeOperands, new_bloom_filter, Writable, }; use rocksdb::RocksDBCompactionStyle::RocksDBUniversalCompaction; -fn snapshot_test() { - let path = "_rust_rocksdb_iteratortest"; - { - let mut db = RocksDB::open_default(path).unwrap(); - let p = db.put(b"k1", b"v1111"); - assert!(p.is_ok()); - let p = db.put(b"k2", b"v2222"); - assert!(p.is_ok()); - let p = db.put(b"k3", b"v3333"); - assert!(p.is_ok()); - let mut snap = db.snapshot(); - let mut view1 = snap.iterator(); - println!("See the output of the first iter"); - for (k,v) in view1.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - for (k,v) in view1.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - for (k,v) in view1.from_end() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - } - let opts = Options::new(); - assert!(RocksDB::destroy(&opts, path).is_ok()); -} - -fn iterator_test() { - let path = "_rust_rocksdb_iteratortest"; - { - let mut db = RocksDB::open_default(path).unwrap(); - let p = db.put(b"k1", b"v1111"); - assert!(p.is_ok()); - let p = db.put(b"k2", b"v2222"); - assert!(p.is_ok()); - let p = db.put(b"k3", b"v3333"); - assert!(p.is_ok()); - { - let mut view1 = db.iterator(); - println!("See the output of the first iter"); - for (k,v) in view1.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - for (k,v) in view1.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - for (k,v) in view1.from_end() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - }; - } - let mut view2 = db.iterator(); - let p = db.put(b"k4", b"v4444"); - assert!(p.is_ok()); - let mut view3 = db.iterator(); - println!("See the output of the second iter"); - for (k,v) in view2.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - } - println!("See the output of the third iter"); - for (k,v) in view3.from_start() { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - } - println!("now the 3rd iter from k2 fwd"); - for (k,v) in view3.from(b"k2", rocksdb::Direction::forward) { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - } - println!("now the 3rd iter from k2 and back"); - for (k,v) in view3.from(b"k2", rocksdb::Direction::reverse) { - println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); - } - } - let opts = Options::new(); - assert!(RocksDB::destroy(&opts, path).is_ok()); -} +//fn snapshot_test() { +// let path = "_rust_rocksdb_iteratortest"; +// { +// let mut db = RocksDB::open_default(path).unwrap(); +// let p = db.put(b"k1", b"v1111"); +// assert!(p.is_ok()); +// let p = db.put(b"k2", b"v2222"); +// assert!(p.is_ok()); +// let p = db.put(b"k3", b"v3333"); +// assert!(p.is_ok()); +// let mut snap = db.snapshot(); +// let mut view1 = snap.iterator(); +// println!("See the output of the first iter"); +// for (k,v) in view1.from_start() { +// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); +// }; +// for (k,v) in view1.from_start() { +// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); +// }; +// for (k,v) in view1.from_end() { +// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); +// }; +// } +// let opts = Options::new(); +// assert!(RocksDB::destroy(&opts, path).is_ok()); +//} #[cfg(not(feature = "valgrind"))] fn main() { - snapshot_test(); - iterator_test(); let path = "/tmp/rust-rocksdb"; let mut db = RocksDB::open_default(path).unwrap(); assert!(db.put(b"my key", b"my value").is_ok()); diff --git a/src/rocksdb.rs b/src/rocksdb.rs index d20a24a..a922b85 100644 --- a/src/rocksdb.rs +++ b/src/rocksdb.rs @@ -62,9 +62,9 @@ pub struct SubDBIterator<'a> { } impl <'a> Iterator for SubDBIterator<'a> { - type Item = (&'a [u8], &'a [u8]); + type Item = (Box<[u8]>, Box<[u8]>); - fn next(&mut self) -> Option<(&'a[u8], &'a[u8])> { + fn next(&mut self) -> Option<(Box<[u8]>, Box<[u8]>)> { let native_iter = self.iter.inner; if !self.iter.just_seeked { match self.direction { @@ -83,7 +83,8 @@ impl <'a> Iterator for SubDBIterator<'a> { let key = unsafe { slice::from_raw_parts(key_ptr, key_len as usize) }; let val_ptr = unsafe { rocksdb_ffi::rocksdb_iter_value(native_iter, val_len_ptr) }; let val = unsafe { slice::from_raw_parts(val_ptr, val_len as usize) }; - Some((key,val)) + + Some((key.to_vec().into_boxed_slice(),val.to_vec().into_boxed_slice())) } else { None } @@ -608,7 +609,7 @@ fn iterator_test() { assert!(p.is_ok()); let mut iter = db.iterator(); for (k,v) in iter.from_start() { - println!("Hello {}: {}", from_utf8(k).unwrap(), from_utf8(v).unwrap()); + println!("Hello {}: {}", from_utf8(&*k).unwrap(), from_utf8(&*v).unwrap()); } } let opts = Options::new(); From bf0c2b3bc0df673a513e9cacd722e798075488fe Mon Sep 17 00:00:00 2001 From: David Greenberg Date: Fri, 17 Jul 2015 12:24:32 -0400 Subject: [PATCH 2/2] Add integration tests --- test/test.rs | 3 ++ test/test_iterator.rs | 110 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 test/test.rs create mode 100644 test/test_iterator.rs diff --git a/test/test.rs b/test/test.rs new file mode 100644 index 0000000..d10d9ae --- /dev/null +++ b/test/test.rs @@ -0,0 +1,3 @@ +extern crate rocksdb; + +mod test_iterator; diff --git a/test/test_iterator.rs b/test/test_iterator.rs new file mode 100644 index 0000000..0985bfd --- /dev/null +++ b/test/test_iterator.rs @@ -0,0 +1,110 @@ +use rocksdb::{Options, RocksDB, Writable, Direction}; +use std; + + +#[test] +pub fn test_iterator() { + let path = "_rust_rocksdb_iteratortest"; + { + let k1:Box<[u8]> = b"k1".to_vec().into_boxed_slice(); + let k2:Box<[u8]> = b"k2".to_vec().into_boxed_slice(); + let k3:Box<[u8]> = b"k3".to_vec().into_boxed_slice(); + let k4:Box<[u8]> = b"k4".to_vec().into_boxed_slice(); + let v1:Box<[u8]> = b"v1111".to_vec().into_boxed_slice(); + let v2:Box<[u8]> = b"v2222".to_vec().into_boxed_slice(); + let v3:Box<[u8]> = b"v3333".to_vec().into_boxed_slice(); + let v4:Box<[u8]> = b"v4444".to_vec().into_boxed_slice(); + let mut db = RocksDB::open_default(path).unwrap(); + let p = db.put(&*k1, &*v1); + assert!(p.is_ok()); + let p = db.put(&*k2, &*v2); + assert!(p.is_ok()); + let p = db.put(&*k3, &*v3); + assert!(p.is_ok()); + let mut view1 = db.iterator(); + let expected = vec![(k1, v1), (k2, v2), (k3, v3)]; + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + // Test that it's reusable a few times + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + // Test it in reverse a few times + { + let mut iterator1 = view1.from_end(); + let mut tmp_vec = iterator1.collect::>(); + tmp_vec.reverse(); + assert_eq!(tmp_vec, expected); + } + { + let mut iterator1 = view1.from_end(); + let mut tmp_vec = iterator1.collect::>(); + tmp_vec.reverse(); + assert_eq!(tmp_vec, expected); + } + { + let mut iterator1 = view1.from_end(); + let mut tmp_vec = iterator1.collect::>(); + tmp_vec.reverse(); + assert_eq!(tmp_vec, expected); + } + { + let mut iterator1 = view1.from_end(); + let mut tmp_vec = iterator1.collect::>(); + tmp_vec.reverse(); + assert_eq!(tmp_vec, expected); + } + { + let mut iterator1 = view1.from_end(); + let mut tmp_vec = iterator1.collect::>(); + tmp_vec.reverse(); + assert_eq!(tmp_vec, expected); + } + // Try it forward again + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected); + } + + let mut view2 = db.iterator(); + let p = db.put(k4, v4); + assert!(p.is_ok()); + let mut view3 = db.iterator(); + let expected2 = vec![(k1, v1), (k2, v2), (k3, v3), (k4, v4)]; + { + let mut iterator1 = view1.from_start(); + assert_eq!(iterator1.collect::>(), expected2); + } +//TODO continue implementing tests! + println!("See the output of the third iter"); + for (k,v) in view3.from_start() { + //println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); + } + println!("now the 3rd iter from k2 fwd"); + for (k,v) in view3.from(b"k2", Direction::forward) { + //println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); + } + println!("now the 3rd iter from k2 and back"); + for (k,v) in view3.from(b"k2", Direction::reverse) { + //println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap()); + } + } + let opts = Options::new(); + assert!(RocksDB::destroy(&opts, path).is_ok()); +} +