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::{path::Path, process::Command};

use anyhow::{Result, ensure};

pub(crate) fn command(cwd: &Path) -> Command {
    let mut command = Command::new("git");
    command
        .current_dir(cwd)
        .env("GIT_TERMINAL_PROMPT", "0")
        .env("GIT_CONFIG_NOSYSTEM", "1");
    command
}

pub(crate) fn output<const N: usize>(cwd: &Path, arguments: [&str; N]) -> Result<String> {
    let output = command(cwd).args(arguments).output()?;
    ensure!(
        output.status.success(),
        "git failed: {}",
        String::from_utf8_lossy(&output.stderr)
            .chars()
            .take(16 * 1024)
            .collect::<String>()
            .trim()
    );
    Ok(String::from_utf8_lossy(&output.stdout)
        .trim_end()
        .to_owned())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use tempfile::tempdir;

    #[test]
    fn reads_git_version_successfully() {
        let dir = tempdir().expect("create temp dir");
        let version = output(dir.path(), ["version"]).expect("git version should succeed");
        assert!(
            version.starts_with("git version"),
            "should start with 'git version'"
        );
    }

    #[test]
    fn errors_on_bad_arguments() {
        let dir = tempdir().expect("create temp dir");
        let result = output(dir.path(), ["--invalid-flag-that-does-not-exist"]);
        assert!(result.is_err(), "bad arguments should error, not panic");
    }

    #[test]
    fn errors_on_non_repository() {
        let dir = tempdir().expect("create temp dir");
        let result = output(dir.path(), ["rev-parse", "HEAD"]);
        assert!(result.is_err(), "non-repo should produce Err");
    }

    #[test]
    fn reads_commit_sha_in_valid_repo() -> Result<()> {
        let dir = tempdir()?;
        let repo = dir.path().join("repo");
        fs::create_dir(&repo)?;
        let init = std::process::Command::new("git")
            .arg("init")
            .args(["-b", "main"])
            .arg(&repo)
            .output()?;
        ensure!(init.status.success(), "git init failed");
        let commit = std::process::Command::new("git")
            .arg("-C")
            .arg(&repo)
            .args([
                "-c",
                "user.name=test",
                "-c",
                "user.email=test@test",
                "commit",
                "--allow-empty",
                "-m",
                "init",
            ])
            .output()?;
        ensure!(commit.status.success(), "git commit failed");
        let sha = output(repo.as_path(), ["rev-parse", "HEAD"])?;
        assert_eq!(sha.len(), 40, "SHA should be 40 hex chars");
        assert!(
            sha.chars().all(|c| c.is_ascii_hexdigit()),
            "SHA should be hex"
        );
        Ok(())
    }
}