use std::fmt::Write;
use super::super::{Refused, Span, Stage};
use super::{Direction, read};
type TestResult = Result<(), String>;
#[test]
fn match_two_hops_keep_every_node_relation_and_byte_span() -> TestResult {
let query = "match (a:patients)-[:admitted_to]->(w:wards)<-[:staffed_by]-(n:nurses)";
let parsed = read(query, 11).map_err(|error| error.to_string())?;
assert_eq!(
parsed.span,
Span {
start: 11,
end: 11 + query.len()
}
);
let Stage::Match { nodes, relations } = parsed.value else {
return Err("chain returned another stage".into());
};
assert_eq!(nodes.len(), 3);
assert_eq!(relations.len(), 2);
for (node, binding, label, start, end) in [
(&nodes[0], "a", "patients", 6, 18),
(&nodes[1], "w", "wards", 35, 44),
(&nodes[2], "n", "nurses", 60, 70),
] {
assert_eq!(node.binding.value, binding);
assert_eq!(node.label.value, label);
assert_eq!(
node.span,
Span {
start: 11 + start,
end: 11 + end
}
);
assert_eq!(
query
.get(node.binding.span.start - 11..node.binding.span.end - 11)
.ok_or("span outside query")?,
binding
);
assert_eq!(
query
.get(node.label.span.start - 11..node.label.span.end - 11)
.ok_or("span outside query")?,
label
);
}
for (relation, kind, direction, start, end) in [
(&relations[0], "admitted_to", Direction::Outgoing, 18, 35),
(&relations[1], "staffed_by", Direction::Incoming, 44, 60),
] {
assert_eq!(relation.kind.value, kind);
assert_eq!(relation.direction, direction);
assert_eq!(
relation.span,
Span {
start: 11 + start,
end: 11 + end
}
);
assert_eq!(
query
.get(relation.kind.span.start - 11..relation.kind.span.end - 11)
.ok_or("span outside query")?,
kind
);
}
Ok(())
}
#[test]
fn match_seven_hops_are_accepted_and_eighth_is_refused_at_its_arrow() -> TestResult {
let mut query = "match (a0:patients)".to_owned();
for index in 1..=7 {
write!(query, "-[:admitted_to]->(a{index}:patients)").map_err(|error| error.to_string())?;
}
let parsed = read(&query, 23).map_err(|error| error.to_string())?;
let Stage::Match { nodes, relations } = parsed.value else {
return Err("chain returned another stage".into());
};
assert_eq!(nodes.len(), 8);
assert_eq!(relations.len(), 7);
let arrow_start = 23 + query.len();
query.push_str("<-[:staffed_by]-(a8:patients)");
let refusal = read(&query, 23).err().ok_or("eighth hop accepted")?;
assert!(matches!(
refusal,
Refused::NotYet("more than seven hops in `match`", _)
));
assert_eq!(refusal.code(), "query_stage_not_available");
assert_eq!(
refusal.span(),
Span {
start: arrow_start,
end: arrow_start + 16
}
);
Ok(())
}