use std::path::PathBuf;
use io_harness::{Error, ExecGuard, Policy, Store, Verification};
#[tokio::test]
async fn a_compile_gate_rejects_a_subject_that_deletes_its_own_items() {
let deletes_itself = "#![cfg(any())]\npub fn hello() -> u32 { \"not a u32\" }\n";
let dir = tempfile::tempdir().unwrap();
tokio::fs::write(dir.path().join("a.rs"), deletes_itself)
.await
.unwrap();
assert!(
!Verification::EachCompilesRust(vec![PathBuf::from("a.rs")])
.passes_in(dir.path())
.await
.unwrap(),
"a crate-level attribute stripped the file's body, so code that does not type-check \
passed the compile gate"
);
}
#[tokio::test]
async fn an_honest_file_still_passes_the_compile_gates() {
let dir = tempfile::tempdir().unwrap();
tokio::fs::write(dir.path().join("a.rs"), "pub fn hello() -> u32 { 42 }\n")
.await
.unwrap();
tokio::fs::write(dir.path().join("b.rs"), "pub fn b() -> u32 { 1 }\n")
.await
.unwrap();
let each = Verification::EachCompilesRust(vec![PathBuf::from("a.rs"), PathBuf::from("b.rs")]);
assert!(each.passes_in(dir.path()).await.unwrap());
tokio::fs::write(dir.path().join("b.rs"), "pub fn b")
.await
.unwrap();
assert!(!each.passes_in(dir.path()).await.unwrap());
tokio::fs::write(
dir.path().join("b.rs"),
"#![allow(dead_code)]\npub fn b() -> u32 { 1 }\n",
)
.await
.unwrap();
assert!(
each.passes_in(dir.path()).await.unwrap(),
"an honest file opening with an inner attribute was failed by the F9 guard"
);
}
#[tokio::test]
async fn the_added_subject_compile_is_still_policy_checked() {
let dir = tempfile::tempdir().unwrap();
tokio::fs::write(dir.path().join("a.rs"), "pub fn hello() -> u32 { 42 }\n")
.await
.unwrap();
let policy = Policy::default().layer("locked").deny_exec("rustc");
let out = Verification::EachCompilesRust(vec![PathBuf::from("a.rs")])
.passes_in_guarded(dir.path(), &ExecGuard::new(&policy))
.await;
assert!(
matches!(out, Err(Error::Refused { ref target, .. }) if target == "rustc"),
"the subject compile bypassed the exec policy, got {out:?}"
);
}
#[tokio::test]
async fn the_trace_names_a_subject_that_deleted_its_own_items() {
async fn phase_of(subject: &str) -> Vec<String> {
let dir = tempfile::tempdir().unwrap();
tokio::fs::write(dir.path().join("a.rs"), subject)
.await
.unwrap();
let store = Store::open(dir.path().join("s.db")).unwrap();
let run = store.start_run("goal", "a.rs").unwrap();
let policy = Policy::default();
let guard = ExecGuard::new(&policy).tracing(&store, run, 1);
let _ = Verification::EachCompilesRust(vec![PathBuf::from("a.rs")])
.passes_in_guarded(dir.path(), &guard)
.await
.unwrap();
store
.sandbox_events(run)
.unwrap()
.into_iter()
.filter(|e| e.kind == "gate_phase_failed")
.filter_map(|e| e.detail)
.collect()
}
assert_eq!(
phase_of("#![cfg(any())]\npub fn hello() -> u32 { \"not a u32\" }\n").await,
vec!["subject-emptied"],
"a compile gate defeated by self-deletion is not attributable in the trace"
);
assert_eq!(phase_of("fn hello").await, vec!["subject-compile"]);
assert!(phase_of("pub fn hello() -> u32 { 42 }\n").await.is_empty());
}
#[tokio::test]
async fn a_subject_cannot_shadow_a_macro_a_command_criterion_never_compiles_with() {
let dir = tempfile::tempdir().unwrap();
let root = dir.path();
std::fs::create_dir(root.join("src")).unwrap();
std::fs::write(
root.join("Cargo.toml"),
"[package]\nname = \"fixture\"\nversion = \"0.0.0\"\nedition = \"2021\"\n",
)
.unwrap();
std::fs::write(
root.join("src/lib.rs"),
"#[macro_export] macro_rules! assert { ($c:expr $(, $r:tt)*) => {{ let _ = &$c; }}; }\n\
pub fn hello() -> u32 { 0 }\n\
#[test] fn gate() { ::core::assert!(hello() == 42, \"this gate can never pass\"); }\n",
)
.unwrap();
let gate = Verification::Command {
argv: vec!["cargo".into(), "test".into(), "--offline".into()],
expect_exit: 0,
};
assert!(
!gate.passes_in(root).await.unwrap(),
"the shadowing subject defeated a criterion it does not share a crate with"
);
std::fs::write(
root.join("src/lib.rs"),
"pub fn hello() -> u32 { 42 }\n\
#[test] fn gate() { ::core::assert!(hello() == 42); }\n",
)
.unwrap();
assert!(gate.passes_in(root).await.unwrap());
}