use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
fn ev() -> Command {
Command::new(env!("CARGO_BIN_EXE_ev"))
}
fn git_repo() -> (std::path::PathBuf, String) {
static N: AtomicU64 = AtomicU64::new(0);
let p = std::env::temp_dir().join(format!(
"ev-jurisdiction-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::Relaxed)
));
let _ = std::fs::remove_dir_all(&p);
std::fs::create_dir_all(&p).unwrap();
for args in [
["init"].as_slice(),
["config", "user.email", "t@e.st"].as_slice(),
["config", "user.name", "Tester"].as_slice(),
["commit", "--allow-empty", "-m", "init"].as_slice(),
] {
Command::new("git")
.args(args)
.current_dir(&p)
.output()
.unwrap();
}
let head = String::from_utf8(
Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(&p)
.output()
.unwrap()
.stdout,
)
.unwrap()
.trim()
.to_string();
assert!(ev()
.arg("init")
.current_dir(&p)
.output()
.unwrap()
.status
.success());
(p, head)
}
const ALWAYS_RED_CHECK: &str = "false";
const ALWAYS_RED_COUNTER_TEST: &str = "true";
fn decide_tagged(repo: &std::path::Path, head: &str, jurisdiction: &str) -> String {
let out = ev()
.args([
"decide",
"import the gateway #1194 ruling (detect-only)",
"--observe",
"backfilled from the gateway history",
"--jurisdiction",
jurisdiction,
"--assume",
"the imported invariant holds",
"--assume-test",
ALWAYS_RED_CHECK,
"--counter-test",
ALWAYS_RED_COUNTER_TEST,
"--on-platform",
"local",
"--triggered-by",
"src/lib.rs",
"--surface",
"imported-invariant",
"--verified-at-sha",
head,
"--blame",
"Wang Yu",
])
.current_dir(repo)
.output()
.unwrap();
assert!(
out.status.success(),
"decide failed: {}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout)
.split_whitespace()
.nth(1)
.unwrap()
.to_string()
}
#[test]
#[allow(non_snake_case)] fn check_should_not_flip_exit_on_red_when_a_C_tagged_decision_is_not_green() {
let (r, head) = git_repo();
let _id = decide_tagged(&r, &head, "C");
let out = ev()
.args(["check", "--run", "--platform", "local", "--exit-on-red"])
.current_dir(&r)
.output()
.unwrap();
assert!(
out.status.success(),
"C-tagged not-green flipped the gate: stdout: {}\nstderr: {}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
);
assert!(
String::from_utf8_lossy(&out.stdout)
.lines()
.any(|l| l.starts_with("memo\t")),
"expected a memo row; got: {}",
String::from_utf8_lossy(&out.stdout)
);
}
#[test]
fn check_should_still_flip_exit_on_red_when_an_untagged_decision_is_not_green() {
let (r, head) = git_repo();
let out = ev()
.args([
"decide",
"ordinary gating decision",
"--assume",
"the invariant holds",
"--assume-test",
ALWAYS_RED_CHECK,
"--counter-test",
ALWAYS_RED_COUNTER_TEST,
"--on-platform",
"local",
"--triggered-by",
"src/lib.rs",
"--surface",
"invariant",
"--verified-at-sha",
&head,
"--blame",
"Wang Yu",
])
.current_dir(&r)
.output()
.unwrap();
assert!(out.status.success());
let out = ev()
.args(["check", "--run", "--platform", "local", "--exit-on-red"])
.current_dir(&r)
.output()
.unwrap();
assert!(!out.status.success());
assert!(String::from_utf8_lossy(&out.stdout)
.lines()
.any(|l| l.starts_with("red\t")));
}
#[test]
fn list_should_render_the_jurisdiction_when_a_decision_is_tagged() {
let (r, head) = git_repo();
let _id = decide_tagged(&r, &head, "C");
let out = ev().arg("list").current_dir(&r).output().unwrap();
assert!(out.status.success());
assert!(
String::from_utf8_lossy(&out.stdout).contains("jurisdiction=C"),
"list did not render jurisdiction: {}",
String::from_utf8_lossy(&out.stdout)
);
}