Files
cubelinux-2/cube-mvw/tests/backend.rs
T

65 lines
2.6 KiB
Rust

use cube_mvw::MvwBackend;
use cubecoords::{CubeHeader, Czyx};
use cubestore::{CubeBackend, CubeStore};
use std::path::{Path, PathBuf};
use std::fs;
use std::thread;
use std::sync::Arc;
fn base(name: &str) -> PathBuf { std::env::temp_dir().join(name) }
fn cleanup(b: &Path) { for i in 0..16 { let _=fs::remove_file(format!("{}-s{}.log",b.display(),i)); let _=fs::remove_file(format!("{}-s{}.ckpt",b.display(),i)); } }
#[test]
fn backend_durable_mvcc_and_concurrent() {
let b = base("mvw-backend"); cleanup(&b);
{
let back = MvwBackend::open(16, &b).unwrap();
back.put_shared(Czyx::new(1,1,1,1), b"hello".to_vec());
// MVCC: a later write is the latest visible version
back.put_shared(Czyx::new(1,1,1,1), b"world".to_vec());
assert_eq!(back.get(&Czyx::new(1,1,1,1)), Some(b"world".to_vec()));
}
// durability: drop (no graceful shard flush), reopen from per-shard WALs
let back = MvwBackend::open(16, &b).unwrap();
let latest = back.get(&Czyx::new(1,1,1,1)).unwrap();
assert!(latest == b"world".to_vec(), "WAL recovery must restore the latest MVCC version");
// keys enumeration
back.put_shared(Czyx::new(2,2,2,2), b"a".to_vec());
assert!(back.keys().contains(&Czyx::new(2,2,2,2)));
// true concurrent multi-writer (shared &self put_shared), 8 threads x 2000
let shared = Arc::new(MvwBackend::open(16, &b).unwrap());
let mut handles = Vec::new();
for t in 0..8u64 {
let s = shared.clone();
handles.push(thread::spawn(move || for i in 0..2000u64 {
let k = Czyx::unpack_u32(((t * 2000 + i) as u32) << 8 | 1);
s.put_shared(k, vec![(i as u8); 8]);
}));
}
for h in handles { h.join().unwrap(); }
// all writes readable
for t in 0..8u64 { for i in 0..2000u64 {
assert!(shared.get(&Czyx::unpack_u32(((t*2000+i) as u32) << 8 | 1)).is_some());
}}
// compact folds memtable to checkpoint and truncates WALs; values still readable
shared.compact().unwrap();
assert!(shared.get(&Czyx::new(1,1,1,1)).is_some());
cleanup(&b);
let _ = thread::current(); // silence
}
#[test]
fn cubestore_record_api_over_mvw_backend() {
let b = base("mvw-cubestore"); cleanup(&b);
let mut store = CubeStore::new(MvwBackend::open(16, &b).unwrap());
let mut h = CubeHeader::new();
h.title = Some("t".into());
h.refresh_flags();
store.put_record(Czyx::new(3,3,3,3), &h, b"body");
let (h2, body) = store.get_record(&Czyx::new(3,3,3,3)).expect("record roundtrip");
assert_eq!(body, b"body");
assert_eq!(h2.title.as_deref(), Some("t"));
cleanup(&b);
}