tests: fast host suites

The timing rules are in two tests (upgrade_and_discovery_deadlines,
stop_deadlines). All other tests use a grace period of 0 or core.stop,
poll with deadlines instead of sleeping, and use the persistent cache in
CARGO_TARGET_TMPDIR. The 128-cycle singleton test is an ignored stress
test that nix flake check runs; the normal run has a 4-cycle sample.
Warm, the activation suite takes 12 s (was 47 s), and cargo test
--workspace takes 65 s.
This commit is contained in:
2026-10-23 08:20:49 +01:00
parent 1386acc924
commit 41818107a2
7 changed files with 134 additions and 73 deletions
+40 -10
View File
@@ -9,7 +9,7 @@ fn fixture() -> PathBuf {
.parent()
.unwrap()
.to_path_buf();
let target = root.join("target/core/guests");
let target = PathBuf::from(concat!(env!("CARGO_TARGET_TMPDIR"), "/guests"));
let status = std::process::Command::new("cargo")
.args([
"build",
@@ -38,7 +38,12 @@ impl TestWorld {
Self(p)
}
async fn start(&self) -> Host {
Host::start(&self.0).await.unwrap()
Host::start_with_cache(
&self.0,
std::path::Path::new(concat!(env!("CARGO_TARGET_TMPDIR"), "/cache")),
)
.await
.unwrap()
}
}
impl Drop for TestWorld {
@@ -902,8 +907,17 @@ async fn native_kill_drops_future_and_releases_locks() {
h.stop().await;
}
/// PROTOCOL 3.6: shutdown stops busy processes in parallel after five seconds.
/// PROTOCOL 3.6: host shutdown stops busy processes together after five seconds.
/// PROTOCOL 3.6: core.stop terminates an attached tree within the same five-second bound.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn stop_deadlines() {
tokio::join!(
shutdown_stops_busy_processes_in_parallel_after_five_seconds(),
attached_tree_stops_in_parallel(),
);
}
/// Checks the shutdown half of the shared deadline test.
async fn shutdown_stops_busy_processes_in_parallel_after_five_seconds() {
let w = TestWorld::new();
let h = w.start().await;
@@ -1132,16 +1146,31 @@ async fn two_plugins_execute_calls_at_the_same_time() {
std::fs::create_dir_all(&other).unwrap();
std::fs::copy(fixture(), other.join("plugin.wasm")).unwrap();
let hc = h.clone();
let slow = tokio::spawn(async move { hc.call("probe.sleep", json!({"ms":1500})).await });
while !h.processes().values().any(|p| p.method == "sleep") {
tokio::task::yield_now().await;
}
let slow = tokio::spawn(async move { hc.call("probe.wait_eof", json!({})).await });
let pid = tokio::time::timeout(std::time::Duration::from_secs(10), async {
while !w.0.join("state/waiting").exists() {
tokio::task::yield_now().await;
}
loop {
if let Some((pid, _)) = h
.processes()
.into_iter()
.find(|(_, p)| p.method == "wait_eof")
{
break pid;
}
tokio::task::yield_now().await;
}
})
.await
.unwrap();
assert_eq!(
call(&h, "other.echo", json!({"ready":true})).await,
json!({"ready":true})
);
assert!(!slow.is_finished());
slow.await.unwrap().unwrap();
call(&h, "core.stop", json!({"pid":pid})).await;
assert_eq!(slow.await.unwrap().unwrap_err()["code"], -32002);
h.stop().await;
}
@@ -1809,8 +1838,7 @@ async fn notification_core_call_forgets_detached_child() {
h.stop().await;
}
/// PROTOCOL 3.6: three generations that ignore EOF stop together within one five-second deadline.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
/// Checks the attached-tree half of the shared deadline test.
async fn attached_tree_stops_in_parallel() {
let w = TestWorld::new();
let h = w.start().await;
@@ -1941,6 +1969,8 @@ async fn core_exit_sets_executable_status_75() {
std::time::Duration::from_secs(30),
tokio::process::Command::new(env!("CARGO_BIN_EXE_sausage"))
.arg("--headless")
.arg("--cache-dir")
.arg(concat!(env!("CARGO_TARGET_TMPDIR"), "/cache"))
.arg("run")
.arg(&w.0)
.stdin(std::process::Stdio::null())