use haematite::SyncCounts;
use serde_json::json;
use super::batch_test_support::{ONE_WRITE, TestResult, apply, at, record_id, store};
use super::{Storage, reads};
use crate::serve::protocol::{Cardinality, Change, Edge, EdgeImport, Node, Relation};
fn node(id: &str) -> Node {
Node {
collection: "records".to_owned(),
document_id: id.to_owned(),
}
}
fn edge(index: usize) -> Edge {
Edge {
relation: "links".to_owned(),
from: node(&record_id(index)),
to: node("anchor"),
properties: json!({"index":index}),
}
}
fn declare(storage: &mut Storage) -> TestResult {
apply(
storage,
"relation",
Change::RelationPut(Relation {
relation: "links".to_owned(),
from_collection: "records".to_owned(),
to_collection: "records".to_owned(),
cardinality: Cardinality::ManyToMany,
}),
)?;
Ok(())
}
#[test]
fn five_hundred_edges_share_one_commit_and_the_control_flushes() -> TestResult {
let (_directory, mut storage) = store(500)?;
declare(&mut storage)?;
let before = at(&storage)?.version;
let counts = storage.sync_counts();
let receipt = apply(
&mut storage,
"edges",
Change::EdgePutMany(EdgeImport {
edges: (0..500).map(edge).collect(),
}),
)?;
assert_eq!(receipt.version.sequence, before.sequence + 1);
assert_eq!(storage.sync_counts().since(counts), ONE_WRITE);
let captured = at(&storage)?;
for prefix in [b"e\0".as_slice(), b"i\0".as_slice()] {
assert_eq!(
reads::test_support::count_keys(&storage.reader, &captured, prefix, 5)?,
500,
);
}
let access = crate::serve::access::request(&crate::serve::access::Standalone)?;
let audit = serde_json::to_value(Storage::audit_counts(&access, &storage.reader, &captured)?)?;
assert!(
audit["buckets"]
.as_array()
.ok_or("no count buckets")?
.iter()
.all(|row| row["result"] == "agree")
);
Ok(())
}
#[test]
fn missing_endpoint_at_137_refuses_five_hundred_edges_without_flushes() -> TestResult {
let (_directory, mut storage) = store(500)?;
declare(&mut storage)?;
let before = at(&storage)?.version;
let counts = storage.sync_counts();
let mut edges: Vec<_> = (0..500).map(edge).collect();
edges[137].to = node("unknown");
let failure = apply(
&mut storage,
"edges",
Change::EdgePutMany(EdgeImport { edges }),
)
.err()
.ok_or("missing endpoint accepted")?;
assert_eq!(failure.code, "document_missing");
assert_eq!(failure.path.as_deref(), Some("/edges/137/to"));
assert_eq!(at(&storage)?.version, before);
assert_eq!(storage.sync_counts().since(counts), SyncCounts::default());
let captured = at(&storage)?;
for prefix in [b"e\0".as_slice(), b"i\0".as_slice()] {
assert_eq!(
reads::test_support::count_keys(&storage.reader, &captured, prefix, 5)?,
0,
);
}
Ok(())
}