use selene_core::{
CancellationChecker, CancellationToken, GraphId, JsonPathSelector, JsonValue, LabelSet, NodeId,
PropertyMap, Value, db_string,
};
use crate::{JsonPathContainmentCandidateOptions, SharedGraph};
fn label(value: &str) -> selene_core::DbString {
db_string(value).expect("test string fits DB string cap")
}
fn json(value: serde_json::Value) -> Value {
Value::Json(JsonValue::new(value).expect("JSON is valid"))
}
fn seed_docs(graph: &SharedGraph, doc: &selene_core::DbString, payload: &selene_core::DbString) {
let mut txn = graph.begin_write();
let mut mutator = txn.mutator();
for value in [
json(serde_json::json!({
"memory": {"facts": [{"title": "old"}, {"title": "current"}]}
})),
json(serde_json::json!({"memory": {"facts": [{"title": "only"}]}})),
Value::String(label("not json")),
json(serde_json::json!(["agent", {"memory": {"facts": [{"title": "current"}]}}])),
] {
mutator
.create_node(
LabelSet::single(doc.clone()),
PropertyMap::from_pairs([(payload.clone(), value)]).expect("properties are valid"),
)
.expect("node inserts");
}
txn.commit().expect("seed commits");
}
#[test]
fn exact_json_contains_nodes_matches_nested_candidates() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(1));
let mut txn = graph.begin_write();
let mut mutator = txn.mutator();
for value in [
json(serde_json::json!({"memory": {"kind": "episodic", "score": 7}})),
json(serde_json::json!({"memory": {"kind": "semantic"}})),
Value::String(label("not json")),
json(serde_json::json!(["agent", {"memory": {"kind": "episodic"}}])),
] {
mutator
.create_node(
LabelSet::single(doc.clone()),
PropertyMap::from_pairs([(payload.clone(), value)]).expect("properties are valid"),
)
.expect("node inserts");
}
txn.commit().expect("seed commits");
let candidate = JsonValue::new(serde_json::json!({"memory": {"kind": "episodic"}})).unwrap();
let hits = graph
.exact_json_contains_nodes(&doc, &payload, &candidate, 10)
.expect("search succeeds");
assert_eq!(
hits.into_iter().map(|hit| hit.node_id).collect::<Vec<_>>(),
vec![NodeId::new(1), NodeId::new(4)]
);
}
#[test]
fn exact_json_contains_nodes_observes_zero_k_and_cancellation() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(2));
let mut txn = graph.begin_write();
txn.mutator()
.create_node(
LabelSet::single(doc.clone()),
PropertyMap::from_pairs([(
payload.clone(),
json(serde_json::json!({"kind": "memory"})),
)])
.expect("properties are valid"),
)
.expect("node inserts");
txn.commit().expect("seed commits");
let candidate = JsonValue::new(serde_json::json!({"kind": "memory"})).unwrap();
assert!(
graph
.exact_json_contains_nodes(&doc, &payload, &candidate, 0)
.expect("zero-k search succeeds")
.is_empty()
);
let token = CancellationToken::new();
token.cancel();
let err = graph
.exact_json_contains_nodes_checked(
&doc,
&payload,
&candidate,
10,
CancellationChecker::new(Some(&token), None),
)
.expect_err("cancelled search reports cancellation");
assert!(matches!(err, crate::JsonSearchError::Cancelled));
}
#[test]
fn exact_json_path_exists_nodes_matches_nested_paths() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(3));
seed_docs(&graph, &doc, &payload);
let path = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
JsonPathSelector::Index(1),
JsonPathSelector::Key(label("title")),
];
let hits = graph
.exact_json_path_exists_nodes(&doc, &payload, &path, 10)
.expect("search succeeds");
assert_eq!(
hits.into_iter().map(|hit| hit.node_id).collect::<Vec<_>>(),
vec![NodeId::new(1)]
);
}
#[test]
fn exact_json_path_exists_nodes_supports_reverse_array_index() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(4));
seed_docs(&graph, &doc, &payload);
let path = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
JsonPathSelector::Index(-1),
JsonPathSelector::Key(label("title")),
];
let hits = graph
.exact_json_path_exists_nodes(&doc, &payload, &path, 10)
.expect("search succeeds");
assert_eq!(
hits.into_iter().map(|hit| hit.node_id).collect::<Vec<_>>(),
vec![NodeId::new(1), NodeId::new(2)]
);
}
#[test]
fn exact_json_path_contains_nodes_matches_selected_subvalues() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(8));
seed_docs(&graph, &doc, &payload);
let path = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
];
let candidate = JsonValue::new(serde_json::json!({"title": "current"})).unwrap();
let hits = graph
.exact_json_path_contains_nodes(&doc, &payload, &path, &candidate, 10)
.expect("search succeeds");
assert_eq!(
hits.into_iter().map(|hit| hit.node_id).collect::<Vec<_>>(),
vec![NodeId::new(1)]
);
}
#[test]
fn exact_json_path_contains_nodes_observes_zero_k_and_cancellation() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(9));
seed_docs(&graph, &doc, &payload);
let path = [JsonPathSelector::Key(label("memory"))];
let candidate = JsonValue::new(serde_json::json!({"facts": []})).unwrap();
assert!(
graph
.exact_json_path_contains_nodes(&doc, &payload, &path, &candidate, 0)
.expect("zero-k search succeeds")
.is_empty()
);
let token = CancellationToken::new();
token.cancel();
let err = graph
.exact_json_path_contains_nodes_checked(
&doc,
&payload,
&path,
&candidate,
10,
CancellationChecker::new(Some(&token), None),
)
.expect_err("cancelled search reports cancellation");
assert!(matches!(err, crate::JsonSearchError::Cancelled));
}
#[test]
fn exact_json_path_value_nodes_returns_selected_values() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(6));
seed_docs(&graph, &doc, &payload);
let path = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
JsonPathSelector::Index(-1),
JsonPathSelector::Key(label("title")),
];
let hits = graph
.exact_json_path_value_nodes(&doc, &payload, &path, 10)
.expect("search succeeds");
assert_eq!(hits.len(), 2);
assert_eq!(hits[0].node_id, NodeId::new(1));
assert_eq!(hits[0].value.as_serde(), &serde_json::json!("current"));
assert_eq!(hits[1].node_id, NodeId::new(2));
assert_eq!(hits[1].value.as_serde(), &serde_json::json!("only"));
}
#[test]
fn exact_json_path_value_nodes_observes_zero_k_and_cancellation() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(7));
seed_docs(&graph, &doc, &payload);
let path = [JsonPathSelector::Key(label("memory"))];
assert!(
graph
.exact_json_path_value_nodes(&doc, &payload, &path, 0)
.expect("zero-k search succeeds")
.is_empty()
);
let token = CancellationToken::new();
token.cancel();
let err = graph
.exact_json_path_value_nodes_checked(
&doc,
&payload,
&path,
10,
CancellationChecker::new(Some(&token), None),
)
.expect_err("cancelled search reports cancellation");
assert!(matches!(err, crate::JsonSearchError::Cancelled));
}
#[test]
fn exact_json_path_exists_nodes_observes_zero_k_and_cancellation() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(5));
seed_docs(&graph, &doc, &payload);
let path = [JsonPathSelector::Key(label("memory"))];
assert!(
graph
.exact_json_path_exists_nodes(&doc, &payload, &path, 0)
.expect("zero-k search succeeds")
.is_empty()
);
let token = CancellationToken::new();
token.cancel();
let err = graph
.exact_json_path_exists_nodes_checked(
&doc,
&payload,
&path,
10,
CancellationChecker::new(Some(&token), None),
)
.expect_err("cancelled search reports cancellation");
assert!(matches!(err, crate::JsonSearchError::Cancelled));
}
#[test]
fn exact_json_checked_matches_disabled_scan_ordering() {
let doc = label("DocParallel");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(11));
{
let mut txn = graph.begin_write();
let mut mutator = txn.mutator();
for idx in 0..24 {
let value = match idx % 6 {
0 | 1 => json(serde_json::json!({
"memory": {"kind": "episodic", "score": idx},
"state": "current"
})),
2 => json(serde_json::json!({
"memory": {"kind": "semantic", "score": idx},
"state": "current"
})),
3 => json(serde_json::json!({
"memory": {"kind": "episodic", "score": idx},
"state": "stale"
})),
4 => Value::String(label("not-json")),
_ => json(serde_json::json!([
"agent",
{"memory": {"kind": "episodic", "score": idx}, "state": "current"}
])),
};
mutator
.create_node(
LabelSet::single(doc.clone()),
PropertyMap::from_pairs([(payload.clone(), value)])
.expect("properties are valid"),
)
.expect("node inserts");
}
txn.commit().expect("seed commits");
}
let candidate = JsonValue::new(serde_json::json!({
"memory": {"kind": "episodic"},
"state": "current"
}))
.expect("candidate JSON parses");
let path = [
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("score")),
];
let contains_path = [JsonPathSelector::Key(label("memory"))];
let path_candidate =
JsonValue::new(serde_json::json!({"kind": "episodic"})).expect("candidate JSON parses");
let token = CancellationToken::new();
let checked_checker = CancellationChecker::new(Some(&token), None);
let contains_disabled = graph
.exact_json_contains_nodes(&doc, &payload, &candidate, 11)
.expect("disabled containment scan succeeds");
let contains_checked = graph
.exact_json_contains_nodes_checked(&doc, &payload, &candidate, 11, checked_checker)
.expect("checked containment scan succeeds");
assert_eq!(contains_disabled, contains_checked);
let exists_disabled = graph
.exact_json_path_exists_nodes(&doc, &payload, &path, 11)
.expect("disabled path-exists scan succeeds");
let exists_checked = graph
.exact_json_path_exists_nodes_checked(&doc, &payload, &path, 11, checked_checker)
.expect("checked path-exists scan succeeds");
assert_eq!(exists_disabled, exists_checked);
let path_contains_disabled = graph
.exact_json_path_contains_nodes(&doc, &payload, &contains_path, &path_candidate, 11)
.expect("disabled path-containment scan succeeds");
let path_contains_checked = graph
.exact_json_path_contains_nodes_checked(
&doc,
&payload,
&contains_path,
&path_candidate,
11,
checked_checker,
)
.expect("checked path-containment scan succeeds");
assert_eq!(path_contains_disabled, path_contains_checked);
let values_disabled = graph
.exact_json_path_value_nodes(&doc, &payload, &path, 11)
.expect("disabled path-value scan succeeds");
let values_checked = graph
.exact_json_path_value_nodes_checked(&doc, &payload, &path, 11, checked_checker)
.expect("checked path-value scan succeeds");
assert_eq!(values_disabled, values_checked);
}
#[test]
fn exact_json_contains_candidate_nodes_filters_sorted_unique_candidates() {
let doc = label("Doc");
let other = label("Other");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(8));
seed_docs(&graph, &doc, &payload);
let mut txn = graph.begin_write();
txn.mutator()
.create_node(
LabelSet::single(other),
PropertyMap::from_pairs([(
payload.clone(),
json(serde_json::json!({"memory": {"facts": [{"title": "current"}]}})),
)])
.expect("properties are valid"),
)
.expect("other-label node inserts");
txn.commit().expect("other-label node commits");
let candidate = JsonValue::new(serde_json::json!({"memory": {"facts": {"title": "current"}}}))
.expect("candidate JSON parses");
let hits = graph
.exact_json_contains_candidate_nodes(
&doc,
&payload,
&candidate,
&[
NodeId::new(5),
NodeId::new(4),
NodeId::new(1),
NodeId::new(1),
NodeId::new(999),
],
10,
)
.expect("candidate search succeeds");
assert_eq!(
hits.into_iter().map(|hit| hit.node_id).collect::<Vec<_>>(),
vec![NodeId::new(1), NodeId::new(4)]
);
}
#[test]
fn exact_json_path_candidate_nodes_match_global_path_semantics() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(9));
seed_docs(&graph, &doc, &payload);
let path_to_second_title = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
JsonPathSelector::Index(1),
JsonPathSelector::Key(label("title")),
];
let path_to_facts = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
];
let title_candidate =
JsonValue::new(serde_json::json!({"title": "current"})).expect("candidate JSON parses");
let exists_hits = graph
.exact_json_path_exists_candidate_nodes(
&doc,
&payload,
&path_to_second_title,
&[NodeId::new(4), NodeId::new(2), NodeId::new(1)],
10,
)
.expect("path-exists candidate search succeeds");
assert_eq!(
exists_hits
.into_iter()
.map(|hit| hit.node_id)
.collect::<Vec<_>>(),
vec![NodeId::new(1)]
);
let contains_hits = graph
.exact_json_path_contains_candidate_nodes(
&doc,
&payload,
JsonPathContainmentCandidateOptions::new(
&path_to_facts,
&title_candidate,
&[NodeId::new(4), NodeId::new(2), NodeId::new(1)],
10,
),
)
.expect("path-containment candidate search succeeds");
assert_eq!(
contains_hits
.into_iter()
.map(|hit| hit.node_id)
.collect::<Vec<_>>(),
vec![NodeId::new(1)]
);
}
#[test]
fn exact_json_path_value_candidate_nodes_return_selected_values() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(10));
seed_docs(&graph, &doc, &payload);
let path = vec![
JsonPathSelector::Key(label("memory")),
JsonPathSelector::Key(label("facts")),
JsonPathSelector::Index(-1),
JsonPathSelector::Key(label("title")),
];
let hits = graph
.exact_json_path_value_candidate_nodes(
&doc,
&payload,
&path,
&[NodeId::new(2), NodeId::new(1), NodeId::new(4)],
10,
)
.expect("path-value candidate search succeeds");
assert_eq!(hits.len(), 2);
assert_eq!(hits[0].node_id, NodeId::new(1));
assert_eq!(hits[0].value.as_serde(), &serde_json::json!("current"));
assert_eq!(hits[1].node_id, NodeId::new(2));
assert_eq!(hits[1].value.as_serde(), &serde_json::json!("only"));
}
#[test]
fn exact_json_candidate_nodes_observe_zero_k_and_cancellation() {
let doc = label("Doc");
let payload = label("payload");
let graph = SharedGraph::new(GraphId::new(11));
seed_docs(&graph, &doc, &payload);
let candidate = JsonValue::new(serde_json::json!({"memory": {}})).expect("candidate JSON");
assert!(
graph
.exact_json_contains_candidate_nodes(&doc, &payload, &candidate, &[NodeId::new(1)], 0)
.expect("zero-k candidate search succeeds")
.is_empty()
);
let token = CancellationToken::new();
token.cancel();
let err = graph
.exact_json_contains_candidate_nodes_checked(
&doc,
&payload,
&candidate,
&[NodeId::new(1)],
10,
CancellationChecker::new(Some(&token), None),
)
.expect_err("cancelled candidate search reports cancellation");
assert!(matches!(err, crate::JsonSearchError::Cancelled));
}