use super::*;
struct Fixture {
directory: PathBuf,
label: LabelId,
property: String,
value: Value,
expected: u64,
}
impl Fixture {
fn new(property: String, value: Value) -> Self {
let directory = std::env::temp_dir().join(format!(
"hawdb-canonical-bloom-memory-{}",
hawdb_core::generate_uuidv7().unwrap()
));
std::fs::create_dir(&directory).unwrap();
let label = LabelId(7);
let mut reference = Vec::new();
reference.extend_from_slice(&label.0.to_le_bytes());
encode_string(&property, &mut reference).unwrap();
encode_value(&value, &mut reference, 0).unwrap();
assert!(reference.len() > 257 * 1024);
let expected = content_digest(&reference).0;
let node = NodeRecord {
id: NodeId(17),
labels: BTreeSet::from([label]),
properties: BTreeMap::from([(property.clone(), value.clone())]),
};
let path = directory.join("canonical.hawdb");
let manifest = CanonicalSegmentWriter::new(CanonicalSegmentConfig::default())
.write(
&path,
ManifestGeneration(23),
[&node],
std::iter::empty::<&RelRecord>(),
)
.unwrap();
let reader = CanonicalSegmentReader::open(
&path,
manifest,
Arc::new(SegmentCache::new(0)),
StoreId(23),
NonZeroU64::new(32 * 1024 * 1024).unwrap(),
)
.unwrap();
assert_eq!(reader.get_node(node.id).unwrap().unwrap(), node);
let mut selected = Vec::new();
let (_, control) = reader
.scan_nodes_by_property_control(label, &property, &value, |node| {
selected.push(node);
Ok(CanonicalScanControl::Continue)
})
.unwrap();
assert_eq!(control, CanonicalScanControl::Continue);
assert_eq!(selected, vec![node]);
Self {
directory,
label,
property,
value,
expected,
}
}
}
impl Drop for Fixture {
fn drop(&mut self) {
std::fs::remove_dir_all(&self.directory).unwrap();
}
}
fn assert_without_large_encoding_buffer(fixture: &Fixture) {
let observation = crate::test_allocator::AllocationObservation::start();
let actual = node_property_bloom_key(fixture.label, &fixture.property, &fixture.value).unwrap();
let allocations = observation.finish();
assert_eq!(actual, fixture.expected);
assert_eq!(
allocations, 0,
"Bloom hashing must not materialize the complete variable-width key/value encoding"
);
}
#[test]
fn checkpoint_units_canonical_bloom_memory_wide_name_does_not_materialize_hash_input() {
let fixture = Fixture::new(format!("{}🦀\0\t\n", "界".repeat(87_723)), Value::Int(19));
assert_without_large_encoding_buffer(&fixture);
}
#[test]
fn checkpoint_units_canonical_bloom_memory_wide_binary_does_not_materialize_hash_input() {
let fixture = Fixture::new("payload".into(), Value::Binary(vec![0x9f; 257 * 1024 + 3]));
assert_without_large_encoding_buffer(&fixture);
}