rete-cli 0.4.2

CLI to build and inspect Rete graph files.
use std::process::Command;

fn temp_path(name: &str, ext: &str) -> std::path::PathBuf {
    std::env::temp_dir().join(format!(
        "rete_why_cli_{}_{}.{}",
        std::process::id(),
        name,
        ext
    ))
}

#[test]
fn why_cli_reports_result_provenance_as_json() {
    let bin = env!("CARGO_BIN_EXE_rete");
    let data = temp_path("data", "nt");
    let file = temp_path("data", "rete");

    std::fs::write(
        &data,
        r#"<http://ex/Alice> <http://ex/knows> <http://ex/Bob> .
<http://ex/Bob> <http://ex/knows> <http://ex/Alice> .
<http://ex/Alice> <http://ex/age> "30" .
"#,
    )
    .unwrap();

    let build = Command::new(bin)
        .args([
            "build",
            data.to_str().unwrap(),
            "-o",
            file.to_str().unwrap(),
        ])
        .output()
        .unwrap();
    assert!(
        build.status.success(),
        "{}",
        String::from_utf8_lossy(&build.stderr)
    );

    let why = Command::new(bin)
        .args([
            "why",
            file.to_str().unwrap(),
            "--predicate",
            "<http://ex/knows>",
            "--json",
        ])
        .output()
        .unwrap();
    assert!(
        why.status.success(),
        "{}",
        String::from_utf8_lossy(&why.stderr)
    );

    let json: serde_json::Value = serde_json::from_slice(&why.stdout).unwrap();
    assert_eq!(json["pattern"]["predicate"], "<http://ex/knows>");
    assert_eq!(json["results"].as_array().unwrap().len(), 2);

    let first = &json["results"][0];
    assert_eq!(first["terms"]["predicate"], "<http://ex/knows>");
    assert_eq!(first["provenance"]["graph"], "default");
    assert_eq!(first["provenance"]["index_permutation"], "POS");
    assert!(first["provenance"]["index_range"]["len"].as_u64().unwrap() > 0);
    assert!(
        first["provenance"]["index_section_range"]["offset"]
            .as_u64()
            .unwrap()
            > first["provenance"]["index_range"]["offset"]
                .as_u64()
                .unwrap()
    );
    assert!(
        first["provenance"]["index_section_range"]["len"]
            .as_u64()
            .unwrap()
            > 0
    );
    assert!(
        first["provenance"]["index_section_range"]["end"]
            .as_u64()
            .unwrap()
            <= first["provenance"]["index_range"]["end"].as_u64().unwrap()
    );
    assert!(
        first["provenance"]["dictionary_range"]["len"]
            .as_u64()
            .unwrap()
            > 0
    );
    // Tiled (v0.2) files report the physical tile and its byte range, nested
    // inside the selected permutation section.
    assert_eq!(first["provenance"]["tile"]["available"], true);
    assert!(first["provenance"]["tile"]["id"]
        .as_str()
        .unwrap()
        .contains('/'));
    let tile_off = first["provenance"]["tile"]["range"]["offset"]
        .as_u64()
        .unwrap();
    let tile_end = first["provenance"]["tile"]["range"]["end"]
        .as_u64()
        .unwrap();
    let sec_off = first["provenance"]["index_section_range"]["offset"]
        .as_u64()
        .unwrap();
    let sec_end = first["provenance"]["index_section_range"]["end"]
        .as_u64()
        .unwrap();
    assert!(sec_off <= tile_off && tile_end <= sec_end);
}