Merge branch 'v3' into v3-t93

# Conflicts:
#	docs/RUNNING.md
This commit is contained in:
2026-11-12 09:37:05 +00:00
11 changed files with 197 additions and 84 deletions
+19 -15
View File
@@ -1,19 +1,24 @@
//! Assert the native build script's namespace boundaries.
fn main() {
assert!(!std::path::Path::new("/home/surma/.ssh").exists());
assert!(
!std::path::Path::new(&std::env::var("HOME").unwrap())
.join(".ssh")
.exists()
);
assert!(std::fs::write("/outside-probe", b"no").is_err());
assert!(
std::net::TcpStream::connect_timeout(
&"1.1.1.1:443".parse().unwrap(),
std::time::Duration::from_millis(100)
)
.is_err()
);
if std::env::var("SAUSAGE_TEST_NO_BUILDER_SANDBOX").as_deref() == Ok("1") {
println!("cargo:warning=namespace assertions skipped: builder sandbox disabled");
} else {
assert!(!std::path::Path::new("/home/surma/.ssh").exists());
assert!(
!std::path::Path::new(&std::env::var("HOME").unwrap())
.join(".ssh")
.exists()
);
assert!(std::fs::write("/outside-probe", b"no").is_err());
assert!(
std::net::TcpStream::connect_timeout(
&"1.1.1.1:443".parse().unwrap(),
std::time::Duration::from_millis(100)
)
.is_err()
);
println!("cargo:warning=namespace assertions passed");
}
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
let object = out.join("add.o");
assert!(
@@ -35,5 +40,4 @@ fn main() {
);
println!("cargo:rustc-link-search=native={}", out.display());
println!("cargo:rustc-link-lib=static=add");
println!("cargo:warning=namespace assertions passed");
}
+22 -6
View File
@@ -16,7 +16,14 @@ fn programs() -> PathBuf {
crate::common::cwd_init();
assert!(
std::process::Command::new("cargo")
.args(["build", "--release", "-p", "world-cargo"])
.args([
"build",
"--release",
"--target",
"wasm32-wasip2",
"-p",
"world-cargo"
])
.current_dir(root.join("userland"))
.status()
.unwrap()
@@ -63,7 +70,7 @@ async fn cargo_scaffold_and_human_output() -> anyhow::Result<()> {
std::fs::create_dir_all(&bin)?;
std::fs::copy(binaries.join("cargo.wasm"), bin.join("cargo.wasm"))?;
std::fs::copy(binaries.join("brush.wasm"), bin.join("sh.wasm"))?;
let runtime = Runtime::new(world)?;
let runtime = Runtime::new_with_options(world, crate::common::runtime_options())?;
for (script, cwd, expected, success) in [
(
"cargo new hello && cd hello && cargo run",
@@ -201,10 +208,15 @@ async fn cargo_build_test_and_source_changes() -> anyhow::Result<()> {
] {
std::fs::write(source.join(path), bytes)?;
}
let runtime = Runtime::new(world)?;
let runtime = Runtime::new_with_options(world, crate::common::runtime_options())?;
let (code, out) = cargo(&runtime, &["build"]).await?;
assert_eq!(code, 0, "{out}");
assert!(out.contains("namespace assertions passed"), "{out}");
if crate::common::runtime_options().no_builder_sandbox {
println!("SKIP namespace isolation assertions: SAUSAGE_TEST_NO_BUILDER_SANDBOX=1");
assert!(out.contains("namespace assertions skipped"), "{out}");
} else {
assert!(out.contains("namespace assertions passed"), "{out}");
}
assert!(out.contains("(/project)"), "{out}");
assert!(!out.contains("/host/builds/"), "{out}");
assert_eq!(
@@ -349,7 +361,11 @@ async fn timeout_and_cancellation() -> anyhow::Result<()> {
source.join("build.rs"),
"fn main() { std::process::Command::new(\"sh\").args([\"-c\", \"echo $$ > child.pid; exec sleep 1000\"]).status().unwrap(); }",
)?;
let builder = Arc::new(Builder::new(world.root.clone(), &world.host_dir)?);
let builder = Arc::new(Builder::new_with_options(
world.root.clone(),
&world.host_dir,
crate::common::runtime_options().no_builder_sandbox,
)?);
let (tx, mut rx) = tokio::sync::mpsc::channel(16);
let task = tokio::spawn(async move {
builder
@@ -375,7 +391,7 @@ async fn timeout_and_cancellation() -> anyhow::Result<()> {
let bin = temp.path().join("world/bin");
std::fs::create_dir_all(&bin)?;
std::fs::copy(binaries.join("cargo.wasm"), bin.join("cargo.wasm"))?;
let runtime = Runtime::new(world)?;
let runtime = Runtime::new_with_options(world, crate::common::runtime_options())?;
let error = runtime
.exec(
Command::Argv(vec!["/bin/cargo.wasm".into(), "build".into()]),
+6
View File
@@ -8,6 +8,12 @@ use std::{
};
pub static BUILD: Mutex<()> = Mutex::new(());
pub fn runtime_options() -> sausage::process::RuntimeOptions {
sausage::process::RuntimeOptions {
no_builder_sandbox: std::env::var("SAUSAGE_TEST_NO_BUILDER_SANDBOX").as_deref() == Ok("1"),
}
}
/// Keep the real shared prompt in every roster fixture, with an ephemeral approval port.
pub fn write_config(dir: &Path, standing: &str, roster: serde_json::Value) -> anyhow::Result<()> {
let mut config: serde_json::Value =