mod common;
use linkrs_core::types::{CompactConfig, VertexId};
use linkrs_storage::{StorageAdmin, StoragePersistenceOps, StorageReader, StorageWriter};
fn compact_and_reopen<F>(dir: &std::path::Path, fixup: F) -> linkrs_storage::GraphStorage
where
F: FnOnce(&mut linkrs_storage::GraphStorage),
{
let mut storage = common::create_persistent_storage(dir);
common::setup_basic_schema(&mut storage);
common::insert_test_data(&mut storage, "test_space");
fixup(&mut storage);
storage.save_to_disk().unwrap();
storage.create_checkpoint().unwrap();
let compact_config = CompactConfig::with_fixed_ratio(true, 0.8);
storage.compact(&compact_config).unwrap();
storage.save_to_disk().unwrap();
storage.create_checkpoint().unwrap();
drop(storage);
common::open_persistent_storage(dir)
}
#[test]
fn test_compact_reclaims_deleted_vertex_space() {
let temp_dir = common::create_test_workdir();
let dir = temp_dir.path();
let storage = compact_and_reopen(dir, |s| {
s.delete_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(1).expect("test vertex id"),
)
.unwrap();
});
assert!(storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(1).expect("test vertex id")
)
.unwrap()
.is_none());
assert!(storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(2).expect("test vertex id")
)
.unwrap()
.is_some());
}
#[test]
fn test_compact_after_multiple_operations() {
let temp_dir = common::create_test_workdir();
let dir = temp_dir.path();
let storage = compact_and_reopen(dir, |s| {
for i in 3..=10 {
let v = common::create_person_vertex(i, &format!("Person{}", i), 20 + i);
s.insert_vertex("test_space", v).unwrap();
}
for i in (1..=10).step_by(2) {
s.delete_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(i).expect("test vertex id"),
)
.unwrap();
}
});
for i in (2..=10).step_by(2) {
assert!(
storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(i).expect("test vertex id")
)
.unwrap()
.is_some(),
"Vertex {} should survive",
i
);
}
for i in (1..=10).step_by(2) {
assert!(
storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(i).expect("test vertex id")
)
.unwrap()
.is_none(),
"Vertex {} should be gone",
i
);
}
}
#[test]
fn test_compact_clean_state() {
let temp_dir = common::create_test_workdir();
let dir = temp_dir.path();
let storage = compact_and_reopen(dir, |_| {});
common::verify_test_data(&storage, "test_space");
}
#[test]
fn test_compact_persistent_roundtrip() {
let temp_dir = common::create_test_workdir();
let dir = temp_dir.path();
let storage = compact_and_reopen(dir, |s| {
s.delete_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(2).expect("test vertex id"),
)
.unwrap();
});
assert!(storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(1).expect("test vertex id")
)
.unwrap()
.is_some());
assert!(storage
.get_vertex(
"test_space",
"Person",
&VertexId::try_from_int64(2).expect("test vertex id")
)
.unwrap()
.is_none());
let _ = storage
.get_edge(
"test_space",
&VertexId::try_from_int64(1).expect("test vertex id"),
&VertexId::try_from_int64(2).expect("test vertex id"),
"KNOWS",
0,
)
.unwrap();
}