use crate::error::GraphError;
use crate::store::RowIndex;
fn derive_row(len: u64, kind: &'static str) -> Result<RowIndex, GraphError> {
u32::try_from(len)
.ok()
.filter(|&row| row != u32::MAX)
.map(RowIndex::new)
.ok_or(GraphError::RowSpaceExhausted {
kind,
rows: len,
max_rows: u32::MAX as u64,
})
}
#[test]
fn row_below_tombstone_boundary_is_accepted() {
let len = u32::MAX as u64 - 2;
assert_eq!(
derive_row(len, "node").unwrap(),
RowIndex::new(u32::MAX - 2),
);
}
#[test]
fn last_real_row_just_below_tombstone_is_accepted() {
let len = u32::MAX as u64 - 1;
let row = derive_row(len, "node").unwrap();
assert_eq!(row, RowIndex::new(u32::MAX - 1));
assert_ne!(
row,
RowIndex::TOMBSTONE,
"the last real row is not the sentinel"
);
}
#[test]
fn row_at_tombstone_value_is_rejected() {
let len = u32::MAX as u64;
let err = derive_row(len, "node").expect_err("a row equal to TOMBSTONE must be rejected");
assert!(
matches!(
err,
GraphError::RowSpaceExhausted { kind, rows, max_rows }
if kind == "node" && rows == u32::MAX as u64 && max_rows == u32::MAX as u64
),
"expected RowSpaceExhausted at the TOMBSTONE boundary, got {err:?}",
);
}
#[test]
fn row_beyond_u32_range_is_rejected() {
let len = u32::MAX as u64 + 1;
let err = derive_row(len, "edge").expect_err("a row beyond u32 range must be rejected");
assert!(
matches!(
err,
GraphError::RowSpaceExhausted { kind, rows, .. }
if kind == "edge" && rows == u32::MAX as u64 + 1
),
"expected RowSpaceExhausted past the u32 range, got {err:?}",
);
}
#[test]
fn tombstone_sentinel_is_the_excluded_value() {
assert_eq!(RowIndex::TOMBSTONE.get(), u32::MAX);
assert!(derive_row(u32::MAX as u64 - 1, "node").is_ok());
assert!(derive_row(u32::MAX as u64, "node").is_err());
}