blue-lang-cli 0.0.90

The blue command line: run, fmt, ast, erase, check.
use std::path::PathBuf;
use std::process::{Command, Output};

const PROGRAM: &str = "def go()\n  ledger_add(\"a\")\n  ledger_count\nend\n";

const SURFACE: &str = r#"{
  "functions": [
    { "name": "ledger_add", "params": ["entry"], "required": 1, "doc": "" },
    { "name": "ledger_count", "params": [], "required": 0, "doc": "" }
  ]
}
"#;

fn scratch(name: &str) -> PathBuf {
    let dir = std::env::temp_dir().join(format!("blue-host-surface-{name}-{}", std::process::id()));
    let _ = std::fs::remove_dir_all(&dir);
    std::fs::create_dir_all(dir.join("rules")).expect("scratch dir");
    dir
}

fn check(file: &std::path::Path) -> Output {
    Command::new(env!("CARGO_BIN_EXE_blue"))
        .args(["check", file.to_str().expect("utf-8 path")])
        .output()
        .expect("spawn blue")
}

fn text(o: &Output) -> String {
    format!(
        "{}{}",
        String::from_utf8_lossy(&o.stdout),
        String::from_utf8_lossy(&o.stderr)
    )
}

#[test]
fn a_host_program_checks_against_the_nearest_surface_file() {
    let dir = scratch("found");
    let file = dir.join("rules").join("go.b");
    std::fs::write(&file, PROGRAM).expect("program");

    let without = check(&file);
    assert!(!without.status.success(), "{}", text(&without));
    assert!(text(&without).contains("B0001"), "{}", text(&without));

    std::fs::write(dir.join("blue-host.json"), SURFACE).expect("surface");
    let with = check(&file);
    assert!(with.status.success(), "{}", text(&with));
    let _ = std::fs::remove_dir_all(&dir);
}

#[test]
fn a_nullary_host_function_is_called_bare() {
    let dir = scratch("nullary");
    std::fs::write(dir.join("blue-host.json"), SURFACE).expect("surface");
    let file = dir.join("rules").join("go.b");
    std::fs::write(&file, "def go()\n  ledger_count()\nend\n").expect("program");
    let o = check(&file);
    assert!(text(&o).contains("B0023"), "{}", text(&o));
    let _ = std::fs::remove_dir_all(&dir);
}

#[test]
fn a_malformed_surface_file_is_refused_by_name() {
    let dir = scratch("malformed");
    std::fs::write(dir.join("blue-host.json"), "{\"functions\": [{}]}").expect("surface");
    let file = dir.join("rules").join("go.b");
    std::fs::write(&file, PROGRAM).expect("program");
    let o = check(&file);
    assert!(!o.status.success());
    assert!(text(&o).contains("blue-host.json"), "{}", text(&o));
    let _ = std::fs::remove_dir_all(&dir);
}