diff --git a/tests/test_column_family.rs b/tests/test_column_family.rs index 97ac54f..dba89da 100644 --- a/tests/test_column_family.rs +++ b/tests/test_column_family.rs @@ -13,22 +13,24 @@ // limitations under the License. // extern crate rocksdb; +mod util; use rocksdb::{DB, MergeOperands, Options, ColumnFamilyDescriptor}; +use util::DBPath; #[test] pub fn test_column_family() { - let path = "_rust_rocksdb_cftest"; + let n = DBPath::new("_rust_rocksdb_cftest"); // should be able to create column families { let mut opts = Options::default(); opts.create_if_missing(true); opts.set_merge_operator("test operator", test_provided_merge, None); - let mut db = DB::open(&opts, path).unwrap(); + let mut db = DB::open(&opts, &n).unwrap(); let opts = Options::default(); match db.create_cf("cf1", &opts) { - Ok(_) => println!("cf1 created successfully"), + Ok(_db) => println!("cf1 created successfully"), Err(e) => { panic!("could not create column family: {}", e); } @@ -39,8 +41,8 @@ pub fn test_column_family() { { let mut opts = Options::default(); opts.set_merge_operator("test operator", test_provided_merge, None); - match DB::open(&opts, path) { - Ok(_) => { + match DB::open(&opts, &n) { + Ok(_db) => { panic!("should not have opened DB successfully without \ specifying column families") @@ -57,8 +59,8 @@ pub fn test_column_family() { { let mut opts = Options::default(); opts.set_merge_operator("test operator", test_provided_merge, None); - match DB::open_cf(&opts, path, &["cf1"]) { - Ok(_) => println!("successfully opened db with column family"), + match DB::open_cf(&opts, &n, &["cf1"]) { + Ok(_db) => println!("successfully opened db with column family"), Err(e) => panic!("failed to open db with column family: {}", e), } } @@ -66,7 +68,7 @@ pub fn test_column_family() { // should be able to list a cf { let opts = Options::default(); - let vec = DB::list_cf(&opts, path); + let vec = DB::list_cf(&opts, &n); match vec { Ok(vec) => assert_eq!(vec, vec!["default", "cf1"]), Err(e) => panic!("failed to drop column family: {}", e), @@ -81,19 +83,17 @@ pub fn test_column_family() { } // should b able to drop a cf { - let mut db = DB::open_cf(&Options::default(), path, &["cf1"]).unwrap(); + let mut db = DB::open_cf(&Options::default(), &n, &["cf1"]).unwrap(); match db.drop_cf("cf1") { Ok(_) => println!("cf1 successfully dropped."), Err(e) => panic!("failed to drop column family: {}", e), } } - - assert!(DB::destroy(&Options::default(), path).is_ok()); } #[test] fn test_create_missing_column_family() { - let path = "_rust_rocksdb_missing_cftest"; + let n = DBPath::new("_rust_rocksdb_missing_cftest"); // should be able to create new column families when opening a new database { @@ -101,24 +101,22 @@ fn test_create_missing_column_family() { opts.create_if_missing(true); opts.create_missing_column_families(true); - match DB::open_cf(&opts, path, &["cf1"]) { - Ok(_) => println!("successfully created new column family"), + match DB::open_cf(&opts, &n, &["cf1"]) { + Ok(_db) => println!("successfully created new column family"), Err(e) => panic!("failed to create new column family: {}", e), } } - - assert!(DB::destroy(&Options::default(), path).is_ok()); } #[test] #[ignore] fn test_merge_operator() { - let path = "_rust_rocksdb_cftest_merge"; + let n = DBPath::new("_rust_rocksdb_cftest_merge"); // TODO should be able to write, read, merge, batch, and iterate over a cf { let mut opts = Options::default(); opts.set_merge_operator("test operator", test_provided_merge, None); - let db = match DB::open_cf(&opts, path, &["cf1"]) { + let db = match DB::open_cf(&opts, &n, &["cf1"]) { Ok(db) => { println!("successfully opened db with column family"); db @@ -180,7 +178,7 @@ fn test_provided_merge(_: &[u8], #[test] pub fn test_column_family_with_options() { - let path = "_rust_rocksdb_cf_with_optionstest"; + let n = DBPath::new("_rust_rocksdb_cf_with_optionstest"); { let mut cfopts = Options::default(); cfopts.set_max_write_buffer_number(16); @@ -191,8 +189,8 @@ pub fn test_column_family_with_options() { opts.create_missing_column_families(true); let cfs = vec![cf_descriptor]; - match DB::open_cf_descriptors(&opts, path, cfs) { - Ok(_) => println!("created db with column family descriptors succesfully"), + match DB::open_cf_descriptors(&opts, &n, cfs) { + Ok(_db) => println!("created db with column family descriptors succesfully"), Err(e) => { panic!("could not create new database with column family descriptors: {}", e); } @@ -207,13 +205,11 @@ pub fn test_column_family_with_options() { let opts = Options::default(); let cfs = vec![cf_descriptor]; - match DB::open_cf_descriptors(&opts, path, cfs) { - Ok(_) => println!("succesfully re-opened database with column family descriptorrs"), + match DB::open_cf_descriptors(&opts, &n, cfs) { + Ok(_db) => println!("succesfully re-opened database with column family descriptors"), Err(e) => { panic!("unable to re-open database with column family descriptors: {}", e); } } } - - assert!(DB::destroy(&Options::default(), path).is_ok()); -} \ No newline at end of file +} diff --git a/tests/test_iterator.rs b/tests/test_iterator.rs index ef7a7bd..fb735f7 100644 --- a/tests/test_iterator.rs +++ b/tests/test_iterator.rs @@ -13,8 +13,10 @@ // limitations under the License. // extern crate rocksdb; +mod util; use rocksdb::{DB, Direction, IteratorMode, MemtableFactory, Options}; +use util::DBPath; fn cba(input: &Box<[u8]>) -> Box<[u8]> { input.iter().cloned().collect::>().into_boxed_slice() @@ -22,7 +24,7 @@ fn cba(input: &Box<[u8]>) -> Box<[u8]> { #[test] pub fn test_iterator() { - let path = "_rust_rocksdb_iteratortest"; + let n = DBPath::new("_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(); @@ -32,7 +34,7 @@ pub fn test_iterator() { 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 db = DB::open_default(path).unwrap(); + let db = DB::open_default(&n).unwrap(); let p = db.put(&*k1, &*v1); assert!(p.is_ok()); let p = db.put(&*k2, &*v2); @@ -153,15 +155,13 @@ pub fn test_iterator() { assert!(!iterator1.valid()); } } - let opts = Options::default(); - assert!(DB::destroy(&opts, path).is_ok()); } fn key(k: &[u8]) -> Box<[u8]> { k.to_vec().into_boxed_slice() } #[test] pub fn test_prefix_iterator() { - let path = "_rust_rocksdb_prefixiteratortest"; + let n = DBPath::new("_rust_rocksdb_prefixiteratortest"); { let a1: Box<[u8]> = key(b"aaa1"); let a2: Box<[u8]> = key(b"aaa2"); @@ -174,7 +174,7 @@ pub fn test_prefix_iterator() { opts.create_if_missing(true); opts.set_prefix_extractor(prefix_extractor); - let db = DB::open(&opts, path).unwrap(); + let db = DB::open(&opts, &n).unwrap(); assert!(db.put(&*a1, &*a1).is_ok()); assert!(db.put(&*a2, &*a2).is_ok()); @@ -193,8 +193,6 @@ pub fn test_prefix_iterator() { assert_eq!(b_iterator.collect::>(), expected) } } - let opts = Options::default(); - assert!(DB::destroy(&opts, path).is_ok()); } #[test] diff --git a/tests/test_multithreaded.rs b/tests/test_multithreaded.rs index 30ef752..38e5d1b 100644 --- a/tests/test_multithreaded.rs +++ b/tests/test_multithreaded.rs @@ -13,18 +13,21 @@ // limitations under the License. // extern crate rocksdb; +mod util; -use rocksdb::{DB, Options}; +use rocksdb::DB; use std::thread; use std::sync::Arc; +use util::DBPath; + const N: usize = 100_000; #[test] pub fn test_multithreaded() { - let path = "_rust_rocksdb_multithreadtest"; + let n = DBPath::new("_rust_rocksdb_multithreadtest"); { - let db = DB::open_default(path).unwrap(); + let db = DB::open_default(&n).unwrap(); let db = Arc::new(db); db.put(b"key", b"value1").unwrap(); @@ -63,5 +66,4 @@ pub fn test_multithreaded() { j2.join().unwrap(); j3.join().unwrap(); } - assert!(DB::destroy(&Options::default(), path).is_ok()); } diff --git a/tests/test_raw_iterator.rs b/tests/test_raw_iterator.rs index 1591d90..080bb7e 100644 --- a/tests/test_raw_iterator.rs +++ b/tests/test_raw_iterator.rs @@ -13,142 +13,144 @@ // limitations under the License. // extern crate rocksdb; +mod util; use rocksdb::DB; - - -fn setup_test_db(name: &str) -> DB { - use std::fs::remove_dir_all; - - let path = "_rust_rocksdb_rawiteratortest_".to_string() + name; - - match remove_dir_all(&path) { - Ok(_) => {} - Err(_) => {} // Don't care if tis fails - } - - DB::open_default(path).unwrap() -} - +use util::DBPath; #[test] pub fn test_forwards_iteration() { - let db = setup_test_db("forwards_iteration"); - db.put(b"k1", b"v1").unwrap(); - db.put(b"k2", b"v2").unwrap(); - db.put(b"k3", b"v3").unwrap(); - db.put(b"k4", b"v4").unwrap(); - - let mut iter = db.raw_iterator(); - iter.seek_to_first(); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k1".to_vec())); - assert_eq!(iter.value(), Some(b"v1".to_vec())); - - iter.next(); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k2".to_vec())); - assert_eq!(iter.value(), Some(b"v2".to_vec())); - - iter.next(); // k3 - iter.next(); // k4 - iter.next(); // invalid! - - assert_eq!(iter.valid(), false); - assert_eq!(iter.key(), None); - assert_eq!(iter.value(), None); + let n = DBPath::new("forwards_iteration"); + { + let db = DB::open_default(&n).unwrap(); + db.put(b"k1", b"v1").unwrap(); + db.put(b"k2", b"v2").unwrap(); + db.put(b"k3", b"v3").unwrap(); + db.put(b"k4", b"v4").unwrap(); + + let mut iter = db.raw_iterator(); + iter.seek_to_first(); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k1".to_vec())); + assert_eq!(iter.value(), Some(b"v1".to_vec())); + + iter.next(); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k2".to_vec())); + assert_eq!(iter.value(), Some(b"v2".to_vec())); + + iter.next(); // k3 + iter.next(); // k4 + iter.next(); // invalid! + + assert_eq!(iter.valid(), false); + assert_eq!(iter.key(), None); + assert_eq!(iter.value(), None); + } } #[test] pub fn test_seek_last() { - let db = setup_test_db("backwards_iteration"); - db.put(b"k1", b"v1").unwrap(); - db.put(b"k2", b"v2").unwrap(); - db.put(b"k3", b"v3").unwrap(); - db.put(b"k4", b"v4").unwrap(); - - let mut iter = db.raw_iterator(); - iter.seek_to_last(); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k4".to_vec())); - assert_eq!(iter.value(), Some(b"v4".to_vec())); - - iter.prev(); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k3".to_vec())); - assert_eq!(iter.value(), Some(b"v3".to_vec())); - - iter.prev(); // k2 - iter.prev(); // k1 - iter.prev(); // invalid! - - assert_eq!(iter.valid(), false); - assert_eq!(iter.key(), None); - assert_eq!(iter.value(), None); + let n = DBPath::new("backwards_iteration"); + { + let db = DB::open_default(&n).unwrap(); + db.put(b"k1", b"v1").unwrap(); + db.put(b"k2", b"v2").unwrap(); + db.put(b"k3", b"v3").unwrap(); + db.put(b"k4", b"v4").unwrap(); + + let mut iter = db.raw_iterator(); + iter.seek_to_last(); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k4".to_vec())); + assert_eq!(iter.value(), Some(b"v4".to_vec())); + + iter.prev(); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k3".to_vec())); + assert_eq!(iter.value(), Some(b"v3".to_vec())); + + iter.prev(); // k2 + iter.prev(); // k1 + iter.prev(); // invalid! + + assert_eq!(iter.valid(), false); + assert_eq!(iter.key(), None); + assert_eq!(iter.value(), None); + } } #[test] pub fn test_seek() { - let db = setup_test_db("seek"); - db.put(b"k1", b"v1").unwrap(); - db.put(b"k2", b"v2").unwrap(); - db.put(b"k4", b"v4").unwrap(); - - let mut iter = db.raw_iterator(); - iter.seek(b"k2"); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k2".to_vec())); - assert_eq!(iter.value(), Some(b"v2".to_vec())); - - // Check it gets the next key when the key doesn't exist - iter.seek(b"k3"); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k4".to_vec())); - assert_eq!(iter.value(), Some(b"v4".to_vec())); + let n = DBPath::new("seek"); + { + let db = DB::open_default(&n).unwrap(); + db.put(b"k1", b"v1").unwrap(); + db.put(b"k2", b"v2").unwrap(); + db.put(b"k4", b"v4").unwrap(); + + let mut iter = db.raw_iterator(); + iter.seek(b"k2"); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k2".to_vec())); + assert_eq!(iter.value(), Some(b"v2".to_vec())); + + // Check it gets the next key when the key doesn't exist + iter.seek(b"k3"); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k4".to_vec())); + assert_eq!(iter.value(), Some(b"v4".to_vec())); + } } #[test] pub fn test_seek_to_nonexistant() { - let db = setup_test_db("seek_to_nonexistant"); - db.put(b"k1", b"v1").unwrap(); - db.put(b"k3", b"v3").unwrap(); - db.put(b"k4", b"v4").unwrap(); - - let mut iter = db.raw_iterator(); - iter.seek(b"k2"); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k3".to_vec())); - assert_eq!(iter.value(), Some(b"v3".to_vec())); + let n = DBPath::new("seek_to_nonexistant"); + { + let db = DB::open_default(&n).unwrap(); + db.put(b"k1", b"v1").unwrap(); + db.put(b"k3", b"v3").unwrap(); + db.put(b"k4", b"v4").unwrap(); + + let mut iter = db.raw_iterator(); + iter.seek(b"k2"); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k3".to_vec())); + assert_eq!(iter.value(), Some(b"v3".to_vec())); + } } #[test] pub fn test_seek_for_prev() { - let db = setup_test_db("seek_for_prev"); - db.put(b"k1", b"v1").unwrap(); - db.put(b"k2", b"v2").unwrap(); - db.put(b"k4", b"v4").unwrap(); - - let mut iter = db.raw_iterator(); - iter.seek(b"k2"); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k2".to_vec())); - assert_eq!(iter.value(), Some(b"v2".to_vec())); - - // Check it gets the previous key when the key doesn't exist - iter.seek_for_prev(b"k3"); - - assert_eq!(iter.valid(), true); - assert_eq!(iter.key(), Some(b"k2".to_vec())); - assert_eq!(iter.value(), Some(b"v2".to_vec())); + let n = DBPath::new("seek_for_prev"); + { + let db = DB::open_default(&n).unwrap(); + db.put(b"k1", b"v1").unwrap(); + db.put(b"k2", b"v2").unwrap(); + db.put(b"k4", b"v4").unwrap(); + + let mut iter = db.raw_iterator(); + iter.seek(b"k2"); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k2".to_vec())); + assert_eq!(iter.value(), Some(b"v2".to_vec())); + + // Check it gets the previous key when the key doesn't exist + iter.seek_for_prev(b"k3"); + + assert_eq!(iter.valid(), true); + assert_eq!(iter.key(), Some(b"k2".to_vec())); + assert_eq!(iter.value(), Some(b"v2".to_vec())); + } } diff --git a/tests/test_rocksdb_options.rs b/tests/test_rocksdb_options.rs index 12c9555..9429a6a 100644 --- a/tests/test_rocksdb_options.rs +++ b/tests/test_rocksdb_options.rs @@ -13,15 +13,18 @@ // limitations under the License. // extern crate rocksdb; +mod util; use rocksdb::{DB, Options}; +use util::DBPath; #[test] fn test_set_num_levels() { - let path = "_rust_rocksdb_test_set_num_levels"; - let mut opts = Options::default(); - opts.create_if_missing(true); - opts.set_num_levels(2); - let db = DB::open(&opts, path).unwrap(); - drop(db); + let n = DBPath::new("_rust_rocksdb_test_set_num_levels"); + { + let mut opts = Options::default(); + opts.create_if_missing(true); + opts.set_num_levels(2); + let _db = DB::open(&opts, &n).unwrap(); + } } diff --git a/tests/test_slice_transform.rs b/tests/test_slice_transform.rs index 832681a..484ad6f 100644 --- a/tests/test_slice_transform.rs +++ b/tests/test_slice_transform.rs @@ -1,48 +1,51 @@ extern crate rocksdb; +mod util; use rocksdb::{DB, Options, SliceTransform}; +use util::DBPath; #[test] pub fn test_slice_transform() { + let n = DBPath::new("_rust_rocksdb_slicetransform_test"); + { + let a1: Box<[u8]> = key(b"aaa1"); + let a2: Box<[u8]> = key(b"aaa2"); + let b1: Box<[u8]> = key(b"bbb1"); + let b2: Box<[u8]> = key(b"bbb2"); - let path = "_rust_rocksdb_slicetransform_test"; - let a1: Box<[u8]> = key(b"aaa1"); - let a2: Box<[u8]> = key(b"aaa2"); - let b1: Box<[u8]> = key(b"bbb1"); - let b2: Box<[u8]> = key(b"bbb2"); + fn first_three(k: &[u8]) -> Vec { + k.iter().take(3).cloned().collect() + } - fn first_three(k: &[u8]) -> Vec { - k.iter().take(3).cloned().collect() - } + let prefix_extractor = SliceTransform::create("first_three", first_three, None); - let prefix_extractor = SliceTransform::create("first_three", first_three, None); + let mut opts = Options::default(); + opts.create_if_missing(true); + opts.set_prefix_extractor(prefix_extractor); - let mut opts = Options::default(); - opts.create_if_missing(true); - opts.set_prefix_extractor(prefix_extractor); + let db = DB::open(&opts, &n).unwrap(); - let db = DB::open(&opts, path).unwrap(); + assert!(db.put(&*a1, &*a1).is_ok()); + assert!(db.put(&*a2, &*a2).is_ok()); + assert!(db.put(&*b1, &*b1).is_ok()); + assert!(db.put(&*b2, &*b2).is_ok()); - assert!(db.put(&*a1, &*a1).is_ok()); - assert!(db.put(&*a2, &*a2).is_ok()); - assert!(db.put(&*b1, &*b1).is_ok()); - assert!(db.put(&*b2, &*b2).is_ok()); + fn cba(input: &Box<[u8]>) -> Box<[u8]> { + input.iter().cloned().collect::>().into_boxed_slice() + } - fn cba(input: &Box<[u8]>) -> Box<[u8]> { - input.iter().cloned().collect::>().into_boxed_slice() - } + fn key(k: &[u8]) -> Box<[u8]> { k.to_vec().into_boxed_slice() } - fn key(k: &[u8]) -> Box<[u8]> { k.to_vec().into_boxed_slice() } + { + let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))]; + let a_iterator = db.prefix_iterator(b"aaa"); + assert_eq!(a_iterator.collect::>(), expected) + } - { - let expected = vec![(cba(&a1), cba(&a1)), (cba(&a2), cba(&a2))]; - let a_iterator = db.prefix_iterator(b"aaa"); - assert_eq!(a_iterator.collect::>(), expected) - } - - { - let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))]; - let b_iterator = db.prefix_iterator(b"bbb"); - assert_eq!(b_iterator.collect::>(), expected) + { + let expected = vec![(cba(&b1), cba(&b1)), (cba(&b2), cba(&b2))]; + let b_iterator = db.prefix_iterator(b"bbb"); + assert_eq!(b_iterator.collect::>(), expected) + } } } diff --git a/tests/util/mod.rs b/tests/util/mod.rs new file mode 100644 index 0000000..e94413e --- /dev/null +++ b/tests/util/mod.rs @@ -0,0 +1,41 @@ +extern crate rocksdb; + +use std::time::{SystemTime, UNIX_EPOCH}; +use std::path::{PathBuf, Path}; + +use rocksdb::{DB, Options}; + +/// Ensures that DB::Destroy is called for this database when DBPath is dropped. +pub struct DBPath { + path: PathBuf +} + +impl DBPath { + /// Suffixes the given `prefix` with a timestamp to ensure that subsequent test runs don't reuse + /// an old database in case of panics prior to Drop being called. + pub fn new(prefix: &str) -> DBPath { + let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let path = format!( + "{}.{}.{}", + prefix, + current_time.as_secs(), + current_time.subsec_nanos() + ); + + DBPath { path: PathBuf::from(path) } + } +} + +impl Drop for DBPath { + fn drop(&mut self) { + let opts = Options::default(); + DB::destroy(&opts, &self.path).unwrap(); + } +} + +impl AsRef for DBPath { + fn as_ref(&self) -> &Path { + &self.path + } +} +