use std::error::Error;
use super::{Attributed, Collection, Document, Edge, Vector, attribution_key};
use crate::serve::contracts::{MutationRequest, ResolvedMutation, attribution::Row};
use crate::serve::protocol::Version;
use crate::serve::storage::Failure;
use serde_json::{Value, json};
type TestResult = Result<(), Box<dyn Error>>;
const fn version(sequence: u64) -> Version {
Version {
generation: 7,
sequence,
}
}
fn request(id: &str, change: &Value) -> Result<ResolvedMutation, Box<dyn Error>> {
Ok(MutationRequest::decode(&serde_json::to_vec(&json!({
"request_id":id, "branch":"clinical", "caller":{"issuer":"lys", "subject":"doctor-a"},
"contract":{"kind":"dependencies", "origin":version(1), "reads":[]},
"change":change
}))?)?
.resolve("operator-not-the-author")?)
}
fn put() -> Value {
json!({"kind":"document.put", "value":{"collection":"charts", "document_id":"child", "document":{"allergy":"penicillin"}}})
}
fn edge() -> Value {
json!({"kind":"edge.put", "value":{"relation":"assigned", "from":{"collection":"charts", "document_id":"child"}, "to":{"collection":"doctors", "document_id":"doctor-a"}, "properties":{"role":"primary"}}})
}
fn vector() -> Value {
json!({"kind":"vector.put", "value":{"collection":"charts", "document_id":"child", "field":"embedding", "vector":[1.0,-2.5]}})
}
fn samples() -> Result<Vec<Value>, Box<dyn Error>> {
Ok(vec![
serde_json::to_value(Document::for_request(
&request("write", &put())?,
version(2),
"schema-branch".to_owned(),
version(0),
)?)?,
serde_json::to_value(Collection::for_request(
&request(
"write",
&json!({"kind":"collection.put", "value":{"collection":"charts", "schema":null}}),
)?,
version(2),
)?)?,
serde_json::to_value(Edge::for_request(&request("write", &edge())?, version(2))?)?,
serde_json::to_value(
&Vector::for_request(&request("write", &vector())?, version(2))?.header,
)?,
])
}
fn decode_key(kind: usize, bytes: &[u8]) -> Result<Vec<u8>, Failure> {
match kind {
0 => attribution_key(&Document::decode(bytes)?),
1 => attribution_key(&Collection::decode(bytes)?),
2 => attribution_key(&Edge::decode(bytes)?),
3 => {
let mut framed = bytes.to_vec();
framed.push(b'\n');
for member in [1.0_f32, -2.5] {
framed.extend_from_slice(&member.to_le_bytes());
}
attribution_key(&Vector::decode(&framed)?)
}
_ => Err(Failure::new("test_kind", "unknown test envelope kind")),
}
}
#[test]
fn all_four_round_trips_use_the_attribution_rows_key_builder() -> TestResult {
let expected = crate::serve::contracts::attribution::key(version(2), "write")?;
for (kind, value) in samples()?.into_iter().enumerate() {
assert_eq!(decode_key(kind, &serde_json::to_vec(&value)?)?, expected);
}
Ok(())
}
#[test]
fn every_envelope_refuses_either_missing_or_null_pointer_value() -> TestResult {
for (kind, sample) in samples()?.into_iter().enumerate() {
let stamp = if kind == 1 {
"changed_at"
} else {
"written_at"
};
for field in [stamp, "request_id"] {
let mut missing = sample.clone();
missing
.as_object_mut()
.ok_or("not an object")?
.remove(field);
assert_eq!(
decode_key(kind, &serde_json::to_vec(&missing)?)
.err()
.ok_or("missing pointer accepted")?
.code,
"stored_envelope_pointer_missing"
);
missing[field] = Value::Null;
assert_eq!(
decode_key(kind, &serde_json::to_vec(&missing)?)
.err()
.ok_or("null pointer accepted")?
.code,
"stored_envelope_pointer_missing"
);
}
}
Ok(())
}
#[test]
fn every_envelope_refuses_unknown_format_and_unknown_members() -> TestResult {
for (kind, mut value) in samples()?.into_iter().enumerate() {
value["format"] = json!(2);
assert_eq!(
decode_key(kind, &serde_json::to_vec(&value)?)
.err()
.ok_or("new format accepted")?
.code,
"stored_envelope_format_unsupported"
);
value["format"] = json!(1);
value["caller"] = json!({"subject":"current-operator"});
assert_eq!(
decode_key(kind, &serde_json::to_vec(&value)?)
.err()
.ok_or("unknown member accepted")?
.code,
if kind == 3 {
"vector_envelope_header_invalid"
} else {
"stored_envelope_corrupt"
}
);
}
Ok(())
}
#[test]
fn todays_document_collection_edge_and_binary_vector_shapes_are_refused() -> TestResult {
let values = [
serde_json::to_vec(
&json!({"collection_branch":"main", "collection_version":version(0), "written_in":"main", "written_at":version(1)}),
)?,
serde_json::to_vec(
&json!({"name":"charts", "schema":null, "changed_in":"main", "changed_at":version(1)}),
)?,
serde_json::to_vec(&json!({"role":"primary"}))?,
[1.0_f32, 2.0]
.into_iter()
.flat_map(f32::to_le_bytes)
.collect(),
];
for (kind, bytes) in values.into_iter().enumerate() {
let result = if kind == 3 {
Vector::decode(&bytes).map(|_| Vec::new())
} else {
decode_key(kind, &bytes)
};
let error = result.err().ok_or("old shape accepted")?;
let expected = if kind == 3 {
"vector_envelope_header_missing"
} else {
"stored_envelope_format_unsupported"
};
assert_eq!(error.code, expected);
}
Ok(())
}
#[test]
fn invalid_pointer_identifiers_are_refused_without_an_operator_fallback() -> TestResult {
for (kind, sample) in samples()?.into_iter().enumerate() {
for id in [String::new(), "\0".to_owned(), "x".repeat(513)] {
let mut value = sample.clone();
value["request_id"] = json!(id);
assert_eq!(
decode_key(kind, &serde_json::to_vec(&value)?)
.err()
.ok_or("invalid pointer accepted")?
.code,
"stored_envelope_pointer_invalid"
);
}
}
Ok(())
}
#[test]
fn invalid_versions_and_duplicate_pointer_members_are_refused() -> TestResult {
for (kind, sample) in samples()?.into_iter().enumerate() {
let stamp = if kind == 1 {
"changed_at"
} else {
"written_at"
};
let mut value = sample.clone();
value[stamp] = json!({"generation":"7"});
assert_eq!(
decode_key(kind, &serde_json::to_vec(&value)?)
.err()
.ok_or("partial version accepted")?
.code,
if kind == 3 {
"vector_envelope_header_invalid"
} else {
"stored_envelope_corrupt"
}
);
let text = serde_json::to_string(&sample)?;
let members = text.strip_prefix('{').ok_or("not a serialized object")?;
let duplicate = format!("{{\"request_id\":\"other\",{members}");
assert_eq!(
decode_key(kind, duplicate.as_bytes())
.err()
.ok_or("duplicate pointer accepted")?
.code,
if kind == 3 {
"vector_envelope_header_invalid"
} else {
"stored_envelope_corrupt"
}
);
}
Ok(())
}
#[test]
fn document_preserves_schema_provenance_and_the_writing_branch() -> TestResult {
let request = request("allergy-update", &put())?;
let envelope =
Document::for_request(&request, version(9), "schema-branch".to_owned(), version(0))?;
let decoded = Document::decode(&envelope.encode()?)?;
assert_eq!(decoded.collection_branch(), "schema-branch");
assert_eq!(decoded.collection_version(), version(0));
assert_eq!(decoded.written_in(), "clinical");
assert_eq!(decoded.written_at(), version(9));
assert_eq!(decoded.request_id(), "allergy-update");
assert_eq!(
attribution_key(&decoded)?,
Row::for_request(&request, version(9))?.key()?
);
assert!(!String::from_utf8(decoded.encode()?)?.contains("penicillin"));
Ok(())
}
#[test]
fn collection_preserves_its_schema_and_changed_branch() -> TestResult {
let schema = json!({"type":"object", "required":["allergy"]});
let request = request(
"schema-update",
&json!({"kind":"collection.put", "value":{"collection":"charts", "schema":schema}}),
)?;
let envelope = Collection::for_request(&request, version(2))?;
let decoded = Collection::decode(&envelope.encode()?)?;
assert_eq!(decoded.name(), "charts");
assert_eq!(decoded.schema(), Some(&schema));
assert_eq!(decoded.changed_in(), "clinical");
assert_eq!(decoded.changed_at(), version(2));
assert_eq!(
attribution_key(&decoded)?,
Row::for_request(&request, version(2))?.key()?
);
Ok(())
}
#[test]
fn edge_preserves_properties_and_rejects_non_object_payloads() -> TestResult {
let envelope = Edge::for_request(&request("edge-update", &edge())?, version(2))?;
let decoded = Edge::decode(&envelope.encode()?)?;
assert_eq!(decoded.properties(), &json!({"role":"primary"}));
assert_eq!(decoded.written_in(), "clinical");
let mut invalid = serde_json::to_value(envelope)?;
invalid["properties"] = json!([]);
assert_eq!(
Edge::decode(&serde_json::to_vec(&invalid)?)
.err()
.ok_or("array properties accepted")?
.code,
"stored_envelope_payload_invalid"
);
Ok(())
}
#[test]
fn vector_round_trip_preserves_float_bits_including_negative_zero() -> TestResult {
let mut change = vector();
change["value"]["vector"] = json!([0.0, -0.0, f32::MIN_POSITIVE, f32::MAX]);
let envelope = Vector::for_request(&request("vector-update", &change)?, version(2))?;
let decoded = Vector::decode(&envelope.encode()?)?;
assert_eq!(
decoded
.vector()
.iter()
.copied()
.map(f32::to_bits)
.collect::<Vec<_>>(),
envelope
.vector()
.iter()
.copied()
.map(f32::to_bits)
.collect::<Vec<_>>()
);
assert_eq!(decoded.written_in(), "clinical");
assert_eq!(decoded.dimension(), 4);
Ok(())
}
fn framed_vector(header: &Value, tail: &[u8]) -> Result<Vec<u8>, Box<dyn Error>> {
let mut bytes = serde_json::to_vec(header)?;
bytes.push(b'\n');
bytes.extend_from_slice(tail);
Ok(bytes)
}
fn vector_header() -> Result<Value, Box<dyn Error>> {
Ok(serde_json::to_value(
&Vector::for_request(&request("vector-update", &vector())?, version(2))?.header,
)?)
}
#[test]
fn vector_refuses_missing_separator_and_non_object_or_multiline_headers() -> TestResult {
let header = vector_header()?;
let no_separator = serde_json::to_vec(&header)?;
assert_eq!(
Vector::decode(&no_separator)
.err()
.ok_or("missing LF accepted")?
.code,
"vector_envelope_header_missing"
);
for bytes in [
b"[]\n".as_slice(),
b"null\n",
b"false\n",
b"{\n}",
b"{}\r\n",
b"not-json\n",
] {
assert_eq!(
Vector::decode(bytes)
.err()
.ok_or("invalid header accepted")?
.code,
"vector_envelope_header_invalid"
);
}
Ok(())
}
#[test]
fn vector_refuses_zero_or_overflowing_dimensions_and_wrong_tail_lengths() -> TestResult {
let sample = vector_header()?;
for dimensions in [0, usize::MAX] {
let mut header = sample.clone();
header["dimensions"] = json!(dimensions);
assert_eq!(
Vector::decode(&framed_vector(&header, &[])?)
.err()
.ok_or("invalid dimensions accepted")?
.code,
"vector_envelope_dimensions_invalid"
);
}
for tail in [vec![], vec![0; 7], vec![0; 9], vec![0; 12]] {
assert_eq!(
Vector::decode(&framed_vector(&sample, &tail)?)
.err()
.ok_or("wrong tail accepted")?
.code,
"vector_envelope_tail_invalid"
);
}
let mut extra_lf = vec![b'\n'];
extra_lf.extend_from_slice(&[0; 8]);
assert_eq!(
Vector::decode(&framed_vector(&sample, &extra_lf)?)
.err()
.ok_or("second separator accepted")?
.code,
"vector_envelope_tail_invalid"
);
Ok(())
}
#[test]
fn vector_refuses_non_finite_binary_members() -> TestResult {
let mut header = vector_header()?;
header["dimensions"] = json!(1);
for member in [f32::INFINITY, f32::NEG_INFINITY, f32::NAN] {
assert_eq!(
Vector::decode(&framed_vector(&header, &member.to_le_bytes())?)
.err()
.ok_or("nonfinite binary member accepted")?
.code,
"vector_envelope_non_finite"
);
}
Ok(())
}
#[test]
fn vector_rejects_invalid_dimension_headers_and_the_replaced_json_payload_shape() -> TestResult {
let sample = vector_header()?;
for dimensions in [Value::Null, json!(-1), json!(1.5), json!("2")] {
let mut header = sample.clone();
header["dimensions"] = dimensions;
assert_eq!(
Vector::decode(&framed_vector(&header, &[0; 8])?)
.err()
.ok_or("invalid dimension shape accepted")?
.code,
"vector_envelope_header_invalid"
);
}
let mut missing = sample.clone();
missing
.as_object_mut()
.ok_or("not an object")?
.remove("dimensions");
assert_eq!(
Vector::decode(&framed_vector(&missing, &[0; 8])?)
.err()
.ok_or("missing dimensions accepted")?
.code,
"vector_envelope_header_invalid"
);
let mut old = sample;
old["vector"] = json!([1.0, -2.5]);
assert_eq!(
Vector::decode(&framed_vector(&old, &[0; 8])?)
.err()
.ok_or("JSON payload accepted")?
.code,
"vector_envelope_header_invalid"
);
Ok(())
}
#[test]
fn vector_keeps_newline_bytes_inside_its_binary_tail() -> TestResult {
let mut header = vector_header()?;
header["dimensions"] = json!(1);
let member = f32::from_bits(10);
let bytes = framed_vector(&header, &member.to_le_bytes())?;
let envelope = Vector::decode(&bytes)?;
assert_eq!(envelope.vector()[0].to_bits(), member.to_bits());
let encoded = envelope.encode()?;
assert_eq!(
Vector::decode(&encoded)?.vector()[0].to_bits(),
member.to_bits()
);
let bare = member.to_le_bytes();
assert_eq!(
Vector::decode(&bare)
.err()
.ok_or("bare float with LF accepted")?
.code,
"vector_envelope_header_invalid"
);
Ok(())
}
#[test]
fn vector_binary_tail_is_exactly_the_original_little_endian_bits() -> TestResult {
let mut change = vector();
change["value"]["vector"] = json!([0.0, -0.0, f32::MIN_POSITIVE, f32::MAX]);
let envelope = Vector::for_request(&request("vector-update", &change)?, version(2))?;
let bytes = envelope.encode()?;
let newline = bytes
.iter()
.position(|byte| *byte == b'\n')
.ok_or("missing separator")?;
let (header, remainder) = bytes.split_at(newline);
let header: Value = serde_json::from_slice(header)?;
assert_eq!(header["dimensions"], 4);
assert!(header.get("vector").is_none());
let expected = envelope
.vector()
.iter()
.copied()
.flat_map(f32::to_le_bytes)
.collect::<Vec<_>>();
assert_eq!(remainder.first(), Some(&b'\n'));
assert_eq!(remainder.get(1..).ok_or("missing tail")?, expected);
assert_eq!(expected.len(), 16);
Ok(())
}
#[test]
fn constructors_refuse_empty_vectors_and_non_object_edges() -> TestResult {
let mut change = vector();
change["value"]["vector"] = json!([]);
assert_eq!(
Vector::for_request(&request("vector", &change)?, version(2))
.err()
.ok_or("empty vector constructor accepted")?
.code,
"vector_envelope_dimensions_invalid"
);
change["value"]["vector"] = json!([1e100]);
assert!(
request("vector", &change)
.err()
.ok_or("unrepresentable member accepted")?
.to_string()
.contains("invalid_mutation")
);
let mut change = edge();
change["value"]["properties"] = json!([]);
assert_eq!(
Edge::for_request(&request("edge", &change)?, version(2))
.err()
.ok_or("invalid edge constructor accepted")?
.code,
"stored_envelope_payload_invalid"
);
Ok(())
}
#[test]
fn envelope_constructors_refuse_a_request_for_another_kind() -> TestResult {
let request = request("document", &put())?;
assert_eq!(
Collection::for_request(&request, version(2))
.err()
.ok_or("wrong collection request accepted")?
.code,
"stored_envelope_request_kind"
);
assert_eq!(
Edge::for_request(&request, version(2))
.err()
.ok_or("wrong edge request accepted")?
.code,
"stored_envelope_request_kind"
);
assert_eq!(
Vector::for_request(&request, version(2))
.err()
.ok_or("wrong vector request accepted")?
.code,
"stored_envelope_request_kind"
);
assert_eq!(
Document::for_request(
&self::request("vector", &vector())?,
version(2),
"main".to_owned(),
version(1)
)
.err()
.ok_or("wrong document request accepted")?
.code,
"stored_envelope_request_kind"
);
Ok(())
}
#[test]
fn invalid_branch_metadata_is_not_a_valid_envelope() -> TestResult {
for (kind, sample) in samples()?.into_iter().enumerate() {
let field = if kind == 1 {
"changed_in"
} else {
"written_in"
};
let mut value = sample.clone();
value[field] = json!("");
assert_eq!(
decode_key(kind, &serde_json::to_vec(&value)?)
.err()
.ok_or("anonymous branch accepted")?
.code,
"stored_envelope_payload_invalid"
);
}
assert!(
Document::for_request(
&request("write", &put())?,
version(2),
String::new(),
version(0)
)
.is_err()
);
Ok(())
}