use std::process::{Command, Stdio};
fn bazet_binary() -> &'static str {
env!("CARGO_BIN_EXE_baztet")
}
fn run_bazet(args: &[&str]) -> std::process::Output {
let ws = concat!(env!("CARGO_MANIFEST_DIR"), "/../../fixtures/simple");
Command::new(bazet_binary())
.args(["--workspace", ws])
.args(args)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output()
.expect("baztet binary")
}
fn bazel_available() -> bool {
Command::new("bazel")
.arg("--version")
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
fn fixture_exists() -> bool {
let ws = concat!(env!("CARGO_MANIFEST_DIR"), "/../../fixtures/simple");
std::path::Path::new(ws).join("MODULE.bazel").is_file()
}
struct CacheEnv {
_prev: Option<std::ffi::OsString>,
dir: std::path::PathBuf,
}
impl Drop for CacheEnv {
fn drop(&mut self) {
match &self._prev {
Some(v) => std::env::set_var("BAZTET_CACHE_DIR", v),
None => std::env::remove_var("BAZTET_CACHE_DIR"),
}
let _ = std::fs::remove_dir_all(&self.dir);
}
}
#[test]
#[ignore = "requires bazel; run with `cargo test -p baztet -- --ignored`"]
fn full_sync_and_execution() {
if !bazel_available() || !fixture_exists() {
return;
}
let cache = std::env::temp_dir().join(format!("baztet-test-cache-{}", std::process::id()));
let _ = std::fs::remove_dir_all(&cache);
let _env = CacheEnv {
_prev: std::env::var("BAZTET_CACHE_DIR")
.ok()
.map(std::ffi::OsString::from),
dir: cache.clone(),
};
std::env::set_var("BAZTET_CACHE_DIR", &cache);
let out = run_bazet(&["sync"]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(out.status.success(), "sync failed:\n{stderr}");
assert!(
stderr.contains("3 target(s)"),
"unexpected output:\n{stderr}"
);
let out = run_bazet(&["targets"]);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("//:hello [sh_binary]"),
"missing hello in:\n{stdout}"
);
assert!(
stdout.contains("//:unit_test [sh_test]"),
"missing unit_test in:\n{stdout}"
);
assert!(
stdout.contains("//:failing_test [sh_test]"),
"missing failing_test in:\n{stdout}"
);
let out = run_bazet(&["build"]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(out.status.success(), "build failed:\n{stderr}");
let out = run_bazet(&["recipes"]);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("simple unit test: test //:unit_test"),
"recipes:\n{stdout}"
);
let out = run_bazet(&["recipes", "--run", "simple unit test"]);
assert!(out.status.success());
let out = run_bazet(&["test", "--pattern", "unit"]);
assert!(out.status.success(), "passing test failed");
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(
stdout.contains("1 of 1 target(s) passed"),
"quiet-ok line missing:\n{stdout}"
);
assert!(
!stdout.contains("PASSED "),
"per-target detail leaked on a green run:\n{stdout}"
);
let out = run_bazet(&["test", "--pattern", "failing"]);
assert!(!out.status.success(), "failing test must fail");
assert_eq!(out.status.code(), Some(3), "failing test exit code");
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("FAILED"), "missing FAILED in:\n{stdout}");
let out = run_bazet(&["test", "--pattern", "unit", "--json"]);
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("\"PASSED\""), "json report:\n{stdout}");
let out = run_bazet(&["run", "//:hello"]);
assert!(out.status.success(), "run failed");
let stdout = String::from_utf8_lossy(&out.stdout);
assert!(stdout.contains("hello"), "run output:\n{stdout}");
let build = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../fixtures/simple/BUILD.bazel"
);
std::fs::File::options()
.append(true)
.open(build)
.unwrap()
.set_modified(std::time::SystemTime::now())
.unwrap();
let out = run_bazet(&["sync"]);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(out.status.success(), "second sync failed:\n{stderr}");
assert!(
stderr.contains("3 target(s)"),
"unexpected output:\n{stderr}"
);
}