use super::super::{Span, Stage, pipeline};
type TestResult = Result<(), Box<dyn std::error::Error>>;
#[test]
fn percentile_grammar_retains_field_number_and_byte_span() -> TestResult {
let text = "patients | percentile ( .reading ; 95.5 ) | count";
let plan = pipeline(text)?;
assert_eq!(
plan.stages[0].value,
Stage::Percentile {
field: "reading".to_owned(),
percentile: serde_json::from_str("95.5")?,
}
);
assert_eq!(plan.stages[0].span, Span { start: 11, end: 41 });
assert_eq!(plan.stages[1].value, Stage::Count);
Ok(())
}
#[test]
fn percentile_out_of_range_is_named_and_marks_the_number() -> TestResult {
for number in ["101", "-1", "100.000000000000000001"] {
let text = format!("patients | percentile(.reading; {number})");
let error = pipeline(&text).err().ok_or("invalid percentile accepted")?;
assert_eq!(error.code(), "query_percentile_range");
assert!(error.to_string().contains("percentile"));
assert_eq!(
text.get(error.span().start..error.span().end)
.ok_or("invalid percentile span")?,
number
);
}
Ok(())
}
#[test]
fn percentile_malformed_arguments_and_stage_position_are_refused() -> TestResult {
for text in [
"patients | percentile",
"patients | percentile()",
"patients | percentile(.reading)",
"patients | percentile(reading; 95)",
"patients | percentile(.reading.inner; 95)",
"patients | percentile(.reading; true)",
"patients | percentile(.reading; NaN)",
"patients | percentile(.reading; 95; 99)",
"patients | percentile(.reading; 95",
"percentile(.reading; 95)",
"patients | '.' | percentile(.reading; 95)",
] {
let error = pipeline(text)
.err()
.ok_or("invalid percentile grammar accepted")?;
assert_eq!(error.code(), "query_parse", "{text}");
assert!(error.to_string().contains("percentile"), "{error}");
}
Ok(())
}
#[test]
fn percentile_in_quotes_remains_jq_with_exact_text() -> TestResult {
let plan = pipeline("patients | 'percentile(.reading; 95)'")?;
assert_eq!(plan.stages.len(), 1);
assert_eq!(
plan.stages[0].value,
Stage::Jq("percentile(.reading; 95)".to_owned())
);
Ok(())
}