host: preserve bundle symlinks and finish integration test isolation

This commit is contained in:
2026-11-07 20:58:33 +00:00
parent 7bd8bfe4d2
commit cab9ceb6f6
7 changed files with 35 additions and 16 deletions
+3 -1
View File
@@ -24,7 +24,9 @@ fn copy_tree(source: &Path, destination: &Path) -> std::io::Result<()> {
for entry in std::fs::read_dir(source)? {
let entry = entry?;
let target = destination.join(entry.file_name());
if entry.file_type()?.is_dir() {
if entry.file_type()?.is_symlink() {
std::os::unix::fs::symlink(std::fs::read_link(entry.path())?, &target)?;
} else if entry.file_type()?.is_dir() {
copy_tree(&entry.path(), &target)?;
} else {
std::fs::copy(entry.path(), target)?;
+9 -1
View File
@@ -11,9 +11,17 @@ cargo test -p sausage --test it -- --test-threads=1
Use `nix develop -c` and the required build slot wrapper for these commands.
Set `CARGO_TARGET_DIR` to your executor's target directory.
The journal timing benchmark keeps its 10% threshold but does not run in the default suite.
Run it by hand on an idle machine:
```sh
cargo test --release -p sausage --test it -- --ignored undo_cost
```
Add new modules under `host/tests/it/` and declare them in `it/main.rs`.
Cargo does not discover separate test executables in `host/tests/`.
Fixture sources remain in `builder-fixture/`.
The bundle-copy regression preserves relative symlink targets, including broken links.
`common.rs` shares the target lookup and the cached userland Git build.
A shared mutex protects the cwd-init output and the brush checkout during fixture builds.
@@ -24,5 +32,5 @@ Child processes receive environment variables through `Command`, not through cha
SIGKILL parents use fully qualified test filters with `--exact`.
The `hook::hook_git` and `hook_git` registrations both existed before this move.
Both remain to preserve the test count.
Both remain as wrappers around one shared helper to preserve the test count.
The shared `hook_guest` module now builds its fixture once per process.
+7 -2
View File
@@ -1,6 +1,11 @@
//! Real guest HTTP requests pass through caller identity, credential injection, and streaming transport.
#[path = "hook_git.rs"]
mod hook_git;
mod hook_git {
//! Preserve the Git push registration that also ran inside the former hook executable.
#[tokio::test]
async fn several_mb_git_push() {
crate::hook_git::push().await;
}
}
use super::hook_guest;
use sausage::{
cred::{
+4 -6
View File
@@ -4,12 +4,7 @@ use sausage::{
process::Runtime,
world::World,
};
use std::{
io::Write,
path::Path,
process::Stdio,
sync::Arc,
};
use std::{io::Write, path::Path, process::Stdio, sync::Arc};
fn git(cwd: &Path, args: &[&str]) {
assert!(
std::process::Command::new("git")
@@ -22,6 +17,9 @@ fn git(cwd: &Path, args: &[&str]) {
}
#[tokio::test]
async fn several_mb_git_push() {
push().await;
}
pub async fn push() {
let component = crate::common::build_git().join("wasm32-wasip2/release/git.wasm");
let temp = tempfile::tempdir().unwrap();
let world = World::open(temp.path()).unwrap();
+1 -6
View File
@@ -48,12 +48,7 @@ fn prepare(dir: &Path, all_extensions: bool) -> anyhow::Result<()> {
)?;
if !target.join("wasm32-wasip2/release/brush.wasm").exists() {
anyhow::ensure!(
Command::new("nu")
.arg("brush/build.nu")
.env("CARGO_TARGET_DIR", target)
.current_dir(&userland)
.status()?
.success(),
crate::common::build_brush()?.success(),
"brush build failed"
);
}
+9
View File
@@ -21,6 +21,9 @@ fn world_copies_programs_and_nested_source_only_once() -> anyhow::Result<()> {
b"ref: refs/heads/main\n",
)?;
std::fs::write(bundle.join("src/sausage/README.md"), b"source")?;
for (name, target) in [("readme-link", "README.md"), ("broken-link", "missing.wasm")] {
std::os::unix::fs::symlink(target, bundle.join("src/sausage").join(name))?;
}
let path = temp.path().join("world");
let _world = World::open_with_userland(&path, Some(&bundle))?;
assert_eq!(
@@ -32,6 +35,12 @@ fn world_copies_programs_and_nested_source_only_once() -> anyhow::Result<()> {
b"source"
);
assert!(path.join("world/src/sausage/.git/HEAD").is_file());
for (name, target) in [("readme-link", "README.md"), ("broken-link", "missing.wasm")] {
assert_eq!(
std::fs::read_link(path.join("world/src/sausage").join(name))?,
Path::new(target)
);
}
std::fs::write(path.join("world/src/sausage/README.md"), b"agent patch")?;
let _world = World::open_with_userland(&path, Some(Path::new("/missing-bundle")))?;
assert_eq!(
+2
View File
@@ -6,7 +6,9 @@ use sausage::{
};
use sausage_vfs::{Host, Mounts, Process};
use std::{path::PathBuf, sync::Arc, time::Instant};
// This timing benchmark has a 10% threshold and is flaky on a loaded machine.
#[tokio::test(flavor = "multi_thread")]
#[ignore = "Run this timing benchmark by hand on an idle machine"]
async fn status_cost() {
let target = PathBuf::from(std::env::var("CARGO_TARGET_DIR").unwrap());
if !target.join("wasm32-wasip2/release/git.wasm").is_file() {