AkurAI Build
Menu

AkurAI-Build

public

Latest change fe39ce51fc9c202d5411f39fd9a8a2feeca4a85e - Harden test suite: 16→179 hermetic tests, race-free integration harness by Ólafur Búi Ólafsson

use std::{fs, path::Path, process::Command};

use anyhow::{Context, Result, ensure};
use serde_json::Value;

/// Verify the CLI produces a valid JSON envelope for every command.
#[test]
fn cli_json_contract_across_lifecycle() -> Result<()> {
    let work = tempfile::tempdir()?;
    let data = work.path().join("data");
    let key = work.path().join("key.bin");
    let repo = work.path().join("repo");
    fs::create_dir(&repo)?;

    // init a bare git repo
    let init = Command::new("git")
        .arg("init")
        .args(["-b", "main"])
        .arg(&repo)
        .output()?;
    ensure!(init.status.success(), "git init failed");

    // keygen
    let out = cli_raw(&data, &key, &["keygen", "--out", path(&key)?])?;
    assert!(out["ok"] == true, "keygen envelope: {out}");
    assert!(out["data"]["created"] == true, "key should be created");

    // migrate
    let out = cli_raw(&data, &key, &["migrate"])?;
    assert!(out["ok"] == true, "migrate envelope: {out}");
    assert!(
        out["data"]["migrations_applied"]
            .as_i64()
            .is_some_and(|n| n >= 0),
        "migrate should report applied count"
    );

    // repo add
    let out = cli_raw(
        &data,
        &key,
        &["repo", "add", "test-app", path(&repo)?, "--branch", "main"],
    )?;
    assert!(out["ok"] == true, "repo add envelope: {out}");
    assert_eq!(out["data"]["name"], "test-app");

    // repo list
    let out = cli_raw(&data, &key, &["repo", "list"])?;
    assert!(out["ok"] == true, "repo list envelope: {out}");
    let repos = out["data"]
        .as_array()
        .context("repo list should be array")?;
    assert_eq!(repos.len(), 1);

    // workers (empty)
    let out = cli_raw(&data, &key, &["workers"])?;
    assert!(out["ok"] == true, "workers envelope: {out}");
    let workers = out["data"].as_array().context("workers should be array")?;
    assert!(workers.is_empty(), "no workers registered yet");

    // runs (empty)
    let out = cli_raw(&data, &key, &["runs"])?;
    assert!(out["ok"] == true, "runs envelope: {out}");
    let runs = out["data"].as_array().context("runs should be array")?;
    assert!(runs.is_empty(), "no runs executed yet");

    Ok(())
}

/// Run the CLI expecting success and return parsed JSON.
fn cli_raw(data: &Path, key: &Path, arguments: &[&str]) -> Result<Value> {
    let output = Command::new(env!("CARGO_BIN_EXE_akurai"))
        .args(["--data", path(data)?, "--key-file", path(key)?])
        .args(arguments)
        .output()?;
    let value: Value = serde_json::from_slice(&output.stdout).with_context(|| {
        format!(
            "invalid CLI JSON: {}",
            String::from_utf8_lossy(&output.stdout)
        )
    })?;
    ensure!(
        output.status.success(),
        "CLI failed ({value}): {}",
        String::from_utf8_lossy(&output.stderr)
    );
    Ok(value)
}

fn path(path: &Path) -> Result<&str> {
    path.to_str().context("test path is not UTF-8")
}