haematite-cli 0.21.1

The haematite command: serve a store, its door and Studio, answer MCP, query with jq, and host the store's assistant seat
Documentation
use crate::serve::query::stages_tests_support as support;

use crate::serve::protocol::Version;
use serde_json::{Value, json};
use std::num::NonZeroU64;
use support::{Fixture, TestResult, patients, request, values};

#[test]
fn window_service_uses_each_stored_revision_and_preserves_the_origin() -> TestResult {
    let mut fixture = Fixture::new(None, &patients())?;
    fixture.vectors(&[[1.0, 0.0], [4.0, 0.0], [3.0, 0.0], [2.0, 0.0]])?;
    let all = fixture.run(
        &request("patients | limit(4)", NonZeroU64::MIN.saturating_add(3)),
        &[],
    )?;
    let rows = all
        .get("rows")
        .and_then(Value::as_array)
        .ok_or("missing rows")?;
    let row = rows.get(1).ok_or("missing second patient")?;
    let origin = row.get("origin").ok_or("missing origin")?;
    let written: Version =
        serde_json::from_value(origin.get("version").ok_or("missing revision")?.clone())?;
    let to = written.sequence.checked_add(1).ok_or("sequence overflow")?;
    let query = format!("patients | window({}; {to})", written.sequence);
    let answer = fixture.run(&request(&query, NonZeroU64::MIN.saturating_add(3)), &[])?;
    assert_eq!(values(&answer)?, vec![patients()[1].clone()]);
    assert_eq!(
        answer
            .get("rows")
            .and_then(Value::as_array)
            .ok_or("missing rows")?[0]
            .get("origin"),
        Some(origin)
    );
    let query = format!(
        "patients | window({to}; {})",
        to.checked_add(1).ok_or("sequence overflow")?
    );
    let excluded = fixture.run(&request(&query, NonZeroU64::MIN.saturating_add(3)), &[])?;
    assert_eq!(values(&excluded)?, vec![patients()[2].clone()]);
    Ok(())
}

#[test]
fn window_service_continuation_keeps_now_and_does_not_skip_or_repeat_records() -> TestResult {
    let mut fixture = Fixture::new(None, &patients())?;
    fixture.scan(NonZeroU64::MIN.saturating_add(1));
    let mut ask = request("patients | window(0; $now)", NonZeroU64::MIN);
    let mut found = Vec::new();
    loop {
        let answer = fixture.run(&ask, &[])?;
        found.extend(values(&answer)?);
        let next = answer.get("next").ok_or("missing continuation field")?;
        if next.is_null() {
            break;
        }
        ask.continuation = Some(next.as_str().ok_or("continuation is not text")?.to_owned());
        assert!(found.len() <= 4, "continuation repeated records");
    }
    assert_eq!(found, patients());
    Ok(())
}

#[test]
fn window_service_count_keeps_access_filtering() -> TestResult {
    let fixture = Fixture::new(None, &patients())?;
    let answer = fixture.run(
        &request(
            "patients | window(0; $now) | count",
            NonZeroU64::MIN.saturating_add(3),
        ),
        &[("patients", "p1")],
    )?;
    assert_eq!(values(&answer)?, vec![json!(3)]);
    Ok(())
}

#[test]
fn window_service_reversed_span_is_refused_before_the_worker() -> TestResult {
    let mut fixture = Fixture::new(None, &patients())?;
    fixture.no_worker();
    let refused = fixture
        .run(
            &request("patients | window(1400; 1300)", NonZeroU64::MIN),
            &[],
        )
        .err()
        .ok_or("reversed window accepted")?;
    assert_eq!(refused.code, "query_window_reversed");
    Ok(())
}