use serde_json::{Value, json};
use super::{Subject, subjects};
use crate::serve::protocol::{HelloAgreement, Operation};
type TestResult = Result<(), Box<dyn std::error::Error>>;
fn operation(method: &str, params: &Value) -> Result<Operation, serde_json::Error> {
serde_json::from_str(&json!({"method": method, "params": params}).to_string())
}
fn mutation(kind: &str, value: &Value) -> Result<Operation, serde_json::Error> {
operation(
"mutation.apply",
&json!({
"request_id": "r", "branch": "main",
"expected": {"generation": "1", "sequence": "1"},
"change": {"kind": kind, "value": value},
}),
)
}
fn asked(subjects: &[Subject]) -> Vec<(&str, &str, Option<&str>)> {
subjects
.iter()
.map(|subject| {
(
subject.route.wire,
subject.route.kind,
subject.name.as_deref(),
)
})
.collect()
}
#[test]
fn hello_asks_about_nothing() -> TestResult {
assert!(subjects(&Operation::Hello(HelloAgreement::client()))?.is_empty());
Ok(())
}
#[test]
fn a_document_read_asks_about_its_collection() -> TestResult {
let read = operation(
"documents.get",
&json!({"selection": {"branch": "main"}, "collection": "patients", "document_id": "a"}),
)?;
assert_eq!(
asked(&subjects(&read)?),
vec![("documents.get", "collection", Some("patients"))]
);
Ok(())
}
#[test]
fn a_mutation_is_decided_by_its_change_kind() -> TestResult {
let put = mutation(
"document.put",
&json!({"collection": "patients", "document_id": "a", "document": {}}),
)?;
assert_eq!(
asked(&subjects(&put)?),
vec![
("document.put", "collection", Some("patients")),
("mutation.apply", "branch", Some("main")),
]
);
let fork = mutation(
"branch.fork",
&json!({"name": "trial", "from": {"generation": "1", "sequence": "1"}}),
)?;
assert_eq!(
asked(&subjects(&fork)?),
vec![("branch.fork", "database", None)]
);
Ok(())
}
#[test]
fn an_edge_asks_about_the_collections_at_both_ends() -> TestResult {
let edge = mutation(
"edge.put",
&json!({
"relation": "treats",
"from": {"collection": "clinicians", "document_id": "c"},
"to": {"collection": "patients", "document_id": "p"},
"properties": {},
}),
)?;
assert_eq!(
asked(&subjects(&edge)?),
vec![
("edge.put", "collection", Some("clinicians")),
("edge.put", "collection", Some("patients")),
("mutation.apply", "branch", Some("main")),
]
);
let same = mutation(
"edge.delete",
&json!({
"relation": "refers",
"from": {"collection": "patients", "document_id": "a"},
"to": {"collection": "patients", "document_id": "b"},
}),
)?;
assert_eq!(
asked(&subjects(&same)?),
vec![
("edge.delete", "collection", Some("patients")),
("mutation.apply", "branch", Some("main")),
]
);
Ok(())
}
#[test]
fn an_edge_import_asks_about_every_collection_it_links_once() -> TestResult {
let edge = |from: &str, to: &str| {
json!({
"relation": "r",
"from": {"collection": from, "document_id": "x"},
"to": {"collection": to, "document_id": "y"},
"properties": {},
})
};
let import = mutation(
"edges.put_many",
&json!({"edges": [edge("a", "b"), edge("b", "c"), edge("a", "c")]}),
)?;
assert_eq!(
asked(&subjects(&import)?),
vec![
("edges.put_many", "collection", Some("a")),
("edges.put_many", "collection", Some("b")),
("edges.put_many", "collection", Some("c")),
("mutation.apply", "branch", Some("main")),
]
);
Ok(())
}
#[test]
fn a_branch_route_asks_about_its_branch() -> TestResult {
let merge = operation(
"branch.merge_prepare",
&json!({"branch": "trial", "limit": 10}),
)?;
assert_eq!(
asked(&subjects(&merge)?),
vec![("branch.merge_prepare", "branch", Some("trial"))]
);
Ok(())
}
#[test]
fn a_vector_import_asks_about_every_written_collection_once() -> TestResult {
let vector = |collection: &str, id: &str| json!({"collection":collection, "document_id":id, "field":"supplied", "vector":[1.0]});
let operation = mutation(
"vectors.put_many",
&json!({"vectors":[vector("a", "x"), vector("b", "x"), vector("a", "y")]}),
)?;
assert_eq!(
asked(&subjects(&operation)?),
vec![
("vectors.put_many", "collection", Some("a")),
("vectors.put_many", "collection", Some("b")),
("mutation.apply", "branch", Some("main")),
]
);
Ok(())
}
#[test]
fn a_delete_import_asks_about_its_collection_and_branch() -> TestResult {
let operation = mutation(
"documents.delete_many",
&json!({"collection":"patients", "document_ids":["b", "a"]}),
)?;
assert_eq!(
asked(&subjects(&operation)?),
vec![
("documents.delete_many", "collection", Some("patients")),
("mutation.apply", "branch", Some("main")),
]
);
Ok(())
}