use crate::common::test_key::TestKey; use crate::common::test_value::TestValue; use crate::common::{cleanup_paths, get_test_data, get_test_data_in_range}; use dharmadb::dharma::Dharma; use dharmadb::errors::Errors; use dharmadb::options::DharmaOpts; use dharmadb::storage::write_ahead_log::WriteAheadLog; mod common; #[test] fn test_create_database() { let options = DharmaOpts::default(); cleanup_paths(&options); let db: Result, Errors> = Dharma::create(options); assert!(db.is_ok()); } #[test] fn test_insert_and_get() { let options = DharmaOpts::default(); cleanup_paths(&options); let mut db: Dharma = Dharma::create(options).unwrap(); let insert_result = db.put(TestKey::from(1), TestValue::from("first value")); assert!(insert_result.is_ok()); let query_result = db.get(&TestKey::from(1)); assert!(query_result.is_ok()); let maybe_result = query_result.unwrap(); assert_eq!(maybe_result, Some(TestValue::from("first value"))); } #[test] fn test_delete() { let options = DharmaOpts::default(); cleanup_paths(&options); let mut db: Dharma = Dharma::create(options).unwrap(); let key = TestKey::from(1); let insert_result = db.put(key.clone(), TestValue::from("first value")); assert!(insert_result.is_ok()); // delete value associated with key let delete_result = db.delete(key.clone()); assert!(delete_result.is_ok()); // value should not be retrievable after delete let get_result = db.get(&key); assert!(get_result.is_ok()); assert_eq!(get_result, Ok(None)); } #[test] fn test_database_flush() { let options = DharmaOpts::default(); cleanup_paths(&options); let data = get_test_data(50); let mut db: Dharma = Dharma::create(options).unwrap(); for (key, value) in data { db.put(key, value); } let flush_result = db.flush(); assert!(flush_result.is_ok()); } #[test] fn test_database_operations_after_flush() { let options = DharmaOpts::default(); cleanup_paths(&options); let data = get_test_data(200); let expected_data = data.clone(); let mut db: Dharma = Dharma::create(options).unwrap(); for (key, value) in data { db.put(key, value); } // flush database to ensure no data remains in memory let flush_result = db.flush(); assert!(flush_result.is_ok()); assert_eq!(db.in_memory_size(), 0); // test reading values back for (key, value) in expected_data { let get_result = db.get(&key); assert!(get_result.is_ok()); let maybe_get_value = get_result.unwrap(); assert!(maybe_get_value.is_some()); assert_eq!(maybe_get_value.unwrap(), value); } } #[test] fn test_database_delete_after_flush() { let options = DharmaOpts::default(); cleanup_paths(&options); let data = get_test_data(10); let expected_data = data.clone(); let mut db: Dharma = Dharma::create(options).unwrap(); for (key, value) in data { db.put(key, value); } // delete keys in range of 0..5 for i in 0..5 { assert!(db.delete(TestKey::from(i)).is_ok()); } db.flush(); // data in delete range should return null for i in 0..5 { let get_result = db.get(&TestKey::from(i)); assert!(get_result.is_ok()); let maybe_value = get_result.unwrap(); assert!(maybe_value.is_none()); } // data in non deleted range should exist for (key, value) in get_test_data_in_range(5, 10) { let get_result = db.get(&key); assert!(get_result.is_ok()); let maybe_value = get_result.unwrap(); assert!(maybe_value.is_some()); assert_eq!(maybe_value.unwrap(), value); } } #[test] fn test_database_reads_data_from_existing_sstable() { let options = DharmaOpts::default(); cleanup_paths(&options); let test_data_1 = get_test_data(200); let test_data_2 = get_test_data(200); let mut db = Dharma::create(options.clone()).unwrap(); for (key, value) in test_data_1 { db.put(key, value); } let flush_result = db.flush(); assert!(flush_result.is_ok()); std::mem::drop(db); // initialize new database let mut new_db: Dharma = Dharma::create(options.clone()).unwrap(); for (key, expected_value) in test_data_2 { let retrieved_value = new_db.get(&key); assert!(retrieved_value.is_ok()); assert_eq!(retrieved_value.unwrap().unwrap(), expected_value); } } #[test] fn test_database_initialization_fails_when_wal_exists_at_path() { let options = DharmaOpts::default(); cleanup_paths(&options); let data = get_test_data(200); let mut wal = WriteAheadLog::create(options.clone()).unwrap(); for (key, value) in data { wal.append(key, value); } // initializing database should fail due to exustence of wal let mut db_result: Result, Errors> = Dharma::create(options.clone()); assert!(db_result.is_err()); } #[test] fn test_database_recovery_from_existing_wal() { let options = DharmaOpts::default(); cleanup_paths(&options); let data = get_test_data(200); let expected_data = get_test_data(200); let mut wal = WriteAheadLog::create(options.clone()).unwrap(); for (key, value) in data { wal.append(key, value); } // initializing database should fail due to exustence of wal let mut db_result: Result, Errors> = Dharma::create(options.clone()); assert!(db_result.is_err()); // attempt database recovery let new_db_result = Dharma::::recover::(options); assert!(new_db_result.is_ok()); let mut new_db = new_db_result.unwrap(); for (key, expected_value) in expected_data { let value_result = new_db.get(&key); assert!(value_result.is_ok()); let maybe_value = value_result.unwrap(); assert!(maybe_value.is_some()); assert_eq!(maybe_value.unwrap(), expected_value); } }