// Copyright 2018-2019 Mozilla // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. use std::fs; use tempfile::Builder; use rkv::{ backend::{Lmdb, SafeMode}, Rkv, StoreOptions, Value, }; #[test] fn test_open_safe_same_dir_as_lmdb() { let root = Builder::new() .prefix("test_open_safe_same_dir_as_lmdb") .tempdir() .expect("tempdir"); fs::create_dir_all(root.path()).expect("dir created"); // Create database of type A and save to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k.open_single("sk", StoreOptions::create()).expect("opened"); let mut writer = k.write().expect("writer"); sk.put(&mut writer, "foo", &Value::I64(1234)) .expect("wrote"); sk.put(&mut writer, "bar", &Value::Bool(true)) .expect("wrote"); sk.put(&mut writer, "baz", &Value::Str("héllo, yöu")) .expect("wrote"); assert_eq!( sk.get(&writer, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&writer, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&writer, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); writer.commit().expect("committed"); k.sync(true).expect("synced"); } // Verify that database of type A was written to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } // Create database of type B and verify that it is empty. { let k = Rkv::new::(root.path()).expect("new succeeded"); let _ = k .open_single("sk", StoreOptions::default()) .expect_err("not opened"); } // Verify that database of type A wasn't changed. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } // Create database of type B and save to disk (type A exists at the same path). { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k.open_single("sk", StoreOptions::create()).expect("opened"); let mut writer = k.write().expect("writer"); sk.put(&mut writer, "foo1", &Value::I64(5678)) .expect("wrote"); sk.put(&mut writer, "bar1", &Value::Bool(false)) .expect("wrote"); sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu")) .expect("wrote"); assert_eq!( sk.get(&writer, "foo1").expect("read"), Some(Value::I64(5678)) ); assert_eq!( sk.get(&writer, "bar1").expect("read"), Some(Value::Bool(false)) ); assert_eq!( sk.get(&writer, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")) ); writer.commit().expect("committed"); k.sync(true).expect("synced"); } // Verify that database of type B was written to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo1").expect("read"), Some(Value::I64(5678)) ); assert_eq!( sk.get(&reader, "bar1").expect("read"), Some(Value::Bool(false)) ); assert_eq!( sk.get(&reader, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")) ); } // Verify that database of type A still wasn't changed. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } } #[test] fn test_open_lmdb_same_dir_as_safe() { let root = Builder::new() .prefix("test_open_lmdb_same_dir_as_safe") .tempdir() .expect("tempdir"); fs::create_dir_all(root.path()).expect("dir created"); // Create database of type A and save to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k.open_single("sk", StoreOptions::create()).expect("opened"); let mut writer = k.write().expect("writer"); sk.put(&mut writer, "foo", &Value::I64(1234)) .expect("wrote"); sk.put(&mut writer, "bar", &Value::Bool(true)) .expect("wrote"); sk.put(&mut writer, "baz", &Value::Str("héllo, yöu")) .expect("wrote"); assert_eq!( sk.get(&writer, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&writer, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&writer, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); writer.commit().expect("committed"); k.sync(true).expect("synced"); } // Verify that database of type A was written to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } // Create database of type B and verify that it is empty. { let k = Rkv::new::(root.path()).expect("new succeeded"); let _ = k .open_single("sk", StoreOptions::default()) .expect_err("not opened"); } // Verify that database of type A wasn't changed. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } // Create database of type B and save to disk (type A exists at the same path). { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k.open_single("sk", StoreOptions::create()).expect("opened"); let mut writer = k.write().expect("writer"); sk.put(&mut writer, "foo1", &Value::I64(5678)) .expect("wrote"); sk.put(&mut writer, "bar1", &Value::Bool(false)) .expect("wrote"); sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu")) .expect("wrote"); assert_eq!( sk.get(&writer, "foo1").expect("read"), Some(Value::I64(5678)) ); assert_eq!( sk.get(&writer, "bar1").expect("read"), Some(Value::Bool(false)) ); assert_eq!( sk.get(&writer, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")) ); writer.commit().expect("committed"); k.sync(true).expect("synced"); } // Verify that database of type B was written to disk. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo1").expect("read"), Some(Value::I64(5678)) ); assert_eq!( sk.get(&reader, "bar1").expect("read"), Some(Value::Bool(false)) ); assert_eq!( sk.get(&reader, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")) ); } // Verify that database of type A still wasn't changed. { let k = Rkv::new::(root.path()).expect("new succeeded"); let sk = k .open_single("sk", StoreOptions::default()) .expect("opened"); let reader = k.read().expect("reader"); assert_eq!( sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)) ); assert_eq!( sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)) ); assert_eq!( sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")) ); } }