use std::collections::HashMap;
use std::fs::File;
use std::path::{Path, PathBuf};
use csv::{Reader, StringRecord};
use polodb_core::LsmKv;
use polodb_core::test_utils::mk_db_path;
#[test]
fn test_insert_db() {
vec![
LsmKv::open_file(mk_db_path("test-insert-kv").as_path()).unwrap(),
LsmKv::open_memory().unwrap(),
].iter().for_each(|db| {
db.put("Hello", "World").unwrap();
db.put(vec![1u8], vec![2u8]).unwrap();
let value = db.get_string("Hello").unwrap().unwrap();
assert_eq!(value, "World");
let value = db.get(&[1u8]).unwrap().unwrap();
assert_eq!(value.as_ref(), &[2u8]);
});
}
fn clean_path(path: &Path) {
let str = path.to_str().unwrap().to_string();
let str_wal = str + ".wal";
let _ = std::fs::remove_file(path);
let _ = std::fs::remove_file(PathBuf::from(str_wal));
}
#[test]
fn test_persist() {
let db_path = mk_db_path("test-kv-persist");
clean_path(db_path.as_path());
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
db.put("Hello", "World").unwrap();
db.put("name", "Vincent").unwrap();
}
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let value = db.get_string("Hello").unwrap().unwrap();
assert_eq!(value, "World");
let value = db.get_string("name").unwrap().unwrap();
assert_eq!(value, "Vincent");
}
}
#[test]
fn test_order() {
vec![
LsmKv::open_file(mk_db_path("test-kv-order").as_path()).unwrap(),
LsmKv::open_memory().unwrap(),
].iter().for_each(|db| {
for i in 0..10 {
db.put(vec![i as u8], vec![i as u8]).unwrap();
}
let cursor = db.open_cursor();
cursor.seek(vec![5 as u8]).unwrap();
assert_eq!(cursor.value().unwrap().unwrap()[0], 5);
cursor.next().unwrap();
assert_eq!(cursor.value().unwrap().unwrap()[0], 6);
});
}
#[test]
fn test_delete() {
vec![
LsmKv::open_file(mk_db_path("test-kv-delete").as_path()).unwrap(),
LsmKv::open_memory().unwrap(),
].iter().for_each(|db| {
for i in 0..10 {
db.put(vec![i as u8], vec![i as u8]).unwrap();
}
db.delete(&[5u8]).unwrap();
let cursor = db.open_cursor();
cursor.seek(vec![4 as u8]).unwrap();
assert_eq!(cursor.value().unwrap().unwrap()[0], 4);
cursor.next().unwrap();
assert_eq!(cursor.value().unwrap().unwrap()[0], 6);
});
}
fn find_crime_desc(header: &StringRecord) -> usize {
let mut index: usize = 0;
for h in header {
if h == "Crm Cd Desc" {
break;
}
index += 1;
}
index
}
fn insert_csv_to_db(db: &LsmKv, rdr: &mut Reader<&File>, mem_table: &mut HashMap<String, String>, count: usize) {
let header = rdr.headers().unwrap();
let index: usize = find_crime_desc(header);
let mut counter: usize = 0;
for result in rdr.records() {
let record = result.unwrap();
let key = record.get(0).unwrap();
let content = record.get(index).unwrap();
db.put(key, content).unwrap();
mem_table.insert(key.into(), content.into());
counter += 1;
if counter >= count {
break;
}
}
}
#[test]
fn test_dataset_1500() {
let dir = env!("CARGO_MANIFEST_DIR");
let data_set_path = dir.to_string() + "/tests/dataset/CrimeDataFrom2020.csv";
let file = File::open(data_set_path).unwrap();
let db_path = mk_db_path("test-kv-dataset-1500");
clean_path(db_path.as_path());
let mut mem_table: HashMap<String, String> = HashMap::new();
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let metrics = db.metrics();
metrics.enable();
let mut rdr = Reader::from_reader(&file);
insert_csv_to_db(&db, &mut rdr, &mut mem_table, 1500);
assert_eq!(metrics.sync_count(), 1);
}
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let test0 = db.get_string("200100509").unwrap().unwrap();
assert_eq!(test0, "BURGLARY FROM VEHICLE");
let test1 = db.get_string("201108111").unwrap().unwrap();
assert_eq!(test1, "BATTERY - SIMPLE ASSAULT");
let mut counter = 0;
for (key, value) in &mem_table {
let test_value = String::from_utf8(
db.get(key.as_str())
.unwrap()
.expect(format!("no value: {}, key: {}", counter, key).as_str())
.to_vec()
).unwrap();
assert_eq!(test_value.as_str(), value.as_str(), "key: {}, counter: {}", key, counter);
counter += 1;
}
}
#[test]
fn test_dataset_3500() {
let dir = env!("CARGO_MANIFEST_DIR");
let data_set_path = dir.to_string() + "/tests/dataset/CrimeDataFrom2020.csv";
let file = std::fs::File::open(data_set_path).unwrap();
let db_path = mk_db_path("test-kv-dataset-3500");
clean_path(db_path.as_path());
let mut mem_table: HashMap<String, String> = HashMap::new();
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let metrics = db.metrics();
metrics.enable();
let mut rdr = Reader::from_reader(&file);
insert_csv_to_db(&db, &mut rdr, &mut mem_table, 3500);
assert_eq!(metrics.sync_count(), 3);
}
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let test0 = db.get_string("200100509").unwrap().unwrap();
assert_eq!(test0, "BURGLARY FROM VEHICLE");
let test1 = db.get_string("201108111").unwrap().unwrap();
assert_eq!(test1, "BATTERY - SIMPLE ASSAULT");
let mut counter = 0;
for (key, value) in &mem_table {
let test_value = db.get_string(key.as_str())
.unwrap()
.expect(format!("no value: {}, key: {}", counter, key).as_str());
assert_eq!(test_value.as_str(), value.as_str(), "key: {}, counter: {}", key, counter);
counter += 1;
}
}
#[test]
fn test_dataset_7500() {
let dir = env!("CARGO_MANIFEST_DIR");
let data_set_path = dir.to_string() + "/tests/dataset/CrimeDataFrom2020.csv";
let file = std::fs::File::open(data_set_path).unwrap();
let db_path = mk_db_path("test-kv-dataset-7500");
clean_path(db_path.as_path());
let mut mem_table: HashMap<String, String> = HashMap::new();
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let metrics = db.metrics();
metrics.enable();
let mut rdr = Reader::from_reader(&file);
insert_csv_to_db(&db, &mut rdr, &mut mem_table, 7500);
assert_eq!(metrics.minor_compact(), 1);
}
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let metrics = db.metrics();
assert_eq!(1, metrics.free_segments_count());
let test0 = db.get_string("200100509").unwrap().unwrap();
assert_eq!(test0, "BURGLARY FROM VEHICLE");
let test1 = db.get_string("201108111").unwrap().unwrap();
assert_eq!(test1, "BATTERY - SIMPLE ASSAULT");
let mut counter = 0;
for (key, value) in &mem_table {
let test_value = db.get_string(key.as_str())
.unwrap()
.expect(format!("no value: {}, key: {}", counter, key).as_str());
assert_eq!(test_value.as_str(), value.as_str(), "key: {}, counter: {}", key, counter);
counter += 1;
}
}
#[test]
fn test_dataset_18k() {
let dir = env!("CARGO_MANIFEST_DIR");
let data_set_path = dir.to_string() + "/tests/dataset/CrimeDataFrom2020.csv";
let file = File::open(data_set_path).unwrap();
let db_path = mk_db_path("test-kv-dataset-18k");
println!("18k data: {}", db_path.to_str().unwrap());
clean_path(db_path.as_path());
let mut mem_table: HashMap<String, String> = HashMap::new();
{
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let metrics = db.metrics();
metrics.enable();
let mut rdr = Reader::from_reader(&file);
insert_csv_to_db(&db, &mut rdr, &mut mem_table, 18000);
assert_eq!(metrics.minor_compact(), 4);
assert_eq!(metrics.major_compact(), 1);
assert_eq!(metrics.use_free_segment_count(), 11);
}
let db = LsmKv::open_file(db_path.as_path()).unwrap();
let test0 = db.get_string("200100509").unwrap().unwrap();
assert_eq!(test0, "BURGLARY FROM VEHICLE");
let test1 = db.get_string("201108111").unwrap().unwrap();
assert_eq!(test1, "BATTERY - SIMPLE ASSAULT");
let mut counter = 0;
for (key, value) in &mem_table {
let test_value = db.get_string(key.as_str())
.unwrap()
.expect(format!("no value: {}, key: {}", counter, key).as_str());
assert_eq!(test_value.as_str(), value.as_str(), "key: {}, counter: {}", key, counter);
counter += 1;
}
}