use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
struct TempRepo(PathBuf);
impl TempRepo {
fn new() -> Self {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let root = std::env::temp_dir().join(format!(
"tc-e2e-verify-e2e-{}-{}",
std::process::id(),
COUNTER.fetch_add(1, Ordering::Relaxed),
));
std::fs::create_dir_all(&root).unwrap();
git(&root, &["init", "-q"]);
git(&root, &["config", "user.email", "test@example.com"]);
git(&root, &["config", "user.name", "Test"]);
git(&root, &["config", "commit.gpgsign", "false"]);
std::fs::write(root.join("README.md"), "seed\n").unwrap();
git(&root, &["add", "."]);
git(
&root,
&["-c", "commit.gpgsign=false", "commit", "-q", "-m", "seed"],
);
TempRepo(root)
}
fn commit_code(&self, name: &str, contents: &str) {
std::fs::write(self.0.join(name), contents).unwrap();
git(&self.0, &["add", name]);
git(
&self.0,
&["-c", "commit.gpgsign=false", "commit", "-q", "-m", "code"],
);
}
}
impl Drop for TempRepo {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.0);
}
}
fn git(dir: &Path, args: &[&str]) {
let status = Command::new("git")
.args(args)
.current_dir(dir)
.status()
.expect("git should run");
assert!(status.success(), "git {args:?} failed");
}
fn run_cli(repo: &Path, args: &[&str]) -> (i32, String) {
let out = Command::new(env!("CARGO_BIN_EXE_testing-conventions"))
.args(args)
.current_dir(repo)
.output()
.expect("the built binary should run");
(
out.status
.code()
.expect("the process should exit with a code"),
String::from_utf8_lossy(&out.stderr).into_owned(),
)
}
#[test]
fn verify_exits_zero_when_the_attestation_is_fresh() {
let repo = TempRepo::new();
assert_eq!(
run_cli(&repo.0, &["e2e", "attest", "true"]).0,
0,
"attest should record the run"
);
let (code, _) = run_cli(&repo.0, &["e2e", "verify"]);
assert_eq!(code, 0, "a fresh attestation should pass verify");
}
#[test]
fn verify_exits_nonzero_with_the_attest_hint_when_stale() {
let repo = TempRepo::new();
run_cli(&repo.0, &["e2e", "attest", "true"]);
repo.commit_code("widget.rs", "pub fn widget() {}\n");
let (code, stderr) = run_cli(&repo.0, &["e2e", "verify"]);
assert_ne!(code, 0, "a stale attestation should fail verify");
assert!(
stderr.contains("attest"),
"the failure should hint to re-run attest; got: {stderr}"
);
}