From 6ba35b0683fe86643d98f83f5e23ecabc4b3dd3a Mon Sep 17 00:00:00 2001 From: Surma Date: Sat, 7 Nov 2026 23:12:42 +0000 Subject: [PATCH] tests: give loader fixtures the complete extension tree --- host/tests/README.md | 1 + host/tests/it/common.rs | 16 ++++++++++++++- host/tests/it/goal_questions.rs | 35 ++------------------------------- host/tests/it/harness_api.rs | 35 ++------------------------------- host/tests/it/p3.rs | 14 +------------ 5 files changed, 21 insertions(+), 80 deletions(-) diff --git a/host/tests/README.md b/host/tests/README.md index e319aaf..cd0c7db 100644 --- a/host/tests/README.md +++ b/host/tests/README.md @@ -24,6 +24,7 @@ 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. +The goal/questions and harness API fixtures copy the complete extension tree through its shared helper. A shared mutex protects the cwd-init output and the brush checkout during fixture builds. The cwd-init build runs at most once per process when its output is absent. The first parallel run reproduced a collision when two compiler processes wrote `init.o`. diff --git a/host/tests/it/common.rs b/host/tests/it/common.rs index e8a00b8..77c57dc 100644 --- a/host/tests/it/common.rs +++ b/host/tests/it/common.rs @@ -1,4 +1,4 @@ -//! Shared fixture builds serialize writes to cwd-init and the brush checkout. +//! Shared fixture copies and builds. A mutex protects cwd-init and the brush checkout. use std::{ path::{Path, PathBuf}, process::{Command, ExitStatus}, @@ -6,6 +6,20 @@ use std::{ }; pub static BUILD: Mutex<()> = Mutex::new(()); +pub fn copy_tree(source: &Path, destination: &Path) -> anyhow::Result<()> { + std::fs::create_dir_all(destination)?; + for entry in std::fs::read_dir(source)? { + let entry = entry?; + let target = destination.join(entry.file_name()); + if entry.file_type()?.is_dir() { + copy_tree(&entry.path(), &target)?; + } else { + std::fs::copy(entry.path(), target)?; + } + } + Ok(()) +} + pub fn target_dir() -> PathBuf { std::env::var_os("CARGO_TARGET_DIR") .map(PathBuf::from) diff --git a/host/tests/it/goal_questions.rs b/host/tests/it/goal_questions.rs index 3721dad..9eff431 100644 --- a/host/tests/it/goal_questions.rs +++ b/host/tests/it/goal_questions.rs @@ -17,44 +17,13 @@ fn prepare(dir: &Path) -> anyhow::Result<()> { target.join("wasm32-wasip2/release/git.wasm"), disk.join("bin/git.wasm"), )?; - for directory in [ - "extensions/subagents", - "extensions/messages", - "extensions/lineage", - "extensions/models", - "extensions/goal", - "extensions/questions", - "extensions/automations", - "extensions/core", - "agents", - ] { - std::fs::create_dir_all(repo.join(directory))?; - } - for directory in [ - "extensions/subagents", - "extensions/messages", - "extensions/lineage", - "extensions/models", - "extensions/goal", - "extensions/questions", - "extensions/automations", - ] { - for entry in std::fs::read_dir(source.join(directory))? { - let entry = entry?; - if entry.path().extension().is_some_and(|ext| ext == "ts") { - std::fs::copy(entry.path(), repo.join(directory).join(entry.file_name()))?; - } - } - } + crate::common::copy_tree(&source.join("extensions"), &repo.join("extensions"))?; + std::fs::create_dir_all(repo.join("agents"))?; std::fs::create_dir_all(repo.join("extensions/probe"))?; std::fs::write( repo.join("extensions/probe/server.ts"), "export default host => { globalThis.testHost = host; globalThis.subagentService = host.need({name:'subagents'}); globalThis.messageService = host.need({name:'messages'}); globalThis.lineageService = host.need({name:'lineage'}); host.implement({name:'conversations'}, {summaryModel: async () => globalThis.summaryRef, concludedIn: async () => new Set(), generatedTitle: async () => {}, setStanding: async () => {}, setAutomaticSummaries: async () => {}}); return {name:'probe'}; }", )?; - std::fs::copy( - source.join("extensions/core/agents.ts"), - repo.join("extensions/core/agents.ts"), - )?; std::fs::write( repo.join("agents/models.json"), r#"{"default":{"model":"faux/faux-1"}}"#, diff --git a/host/tests/it/harness_api.rs b/host/tests/it/harness_api.rs index bb73e3b..55f8d3e 100644 --- a/host/tests/it/harness_api.rs +++ b/host/tests/it/harness_api.rs @@ -65,44 +65,13 @@ fn prepare(dir: &Path) -> anyhow::Result<()> { target.join("wasm32-wasip2/release/curl.wasm"), disk.join("bin/curl.wasm"), )?; - for directory in [ - "extensions/subagents", - "extensions/messages", - "extensions/lineage", - "extensions/models", - "extensions/goal", - "extensions/questions", - "extensions/automations", - "extensions/core", - "agents", - ] { - std::fs::create_dir_all(repo.join(directory))?; - } - for directory in [ - "extensions/subagents", - "extensions/messages", - "extensions/lineage", - "extensions/models", - "extensions/goal", - "extensions/questions", - "extensions/automations", - ] { - for entry in std::fs::read_dir(source.join(directory))? { - let entry = entry?; - if entry.path().extension().is_some_and(|ext| ext == "ts") { - std::fs::copy(entry.path(), repo.join(directory).join(entry.file_name()))?; - } - } - } + crate::common::copy_tree(&source.join("extensions"), &repo.join("extensions"))?; + std::fs::create_dir_all(repo.join("agents"))?; std::fs::create_dir_all(repo.join("extensions/probe"))?; std::fs::write( repo.join("extensions/probe/server.ts"), "export default host => { globalThis.testHost = host; globalThis.subagentService = host.need({name:'subagents'}); globalThis.messageService = host.need({name:'messages'}); globalThis.lineageService = host.need({name:'lineage'}); host.implement({name:'conversations'}, {summaryModel: async () => globalThis.summaryRef, concludedIn: async () => new Set(), generatedTitle: async () => {}, setStanding: async () => {}, setAutomaticSummaries: async () => {}}); return {name:'probe'}; }", )?; - std::fs::copy( - source.join("extensions/core/agents.ts"), - repo.join("extensions/core/agents.ts"), - )?; std::fs::write( repo.join("agents/models.json"), r#"{"default":{"model":"faux/faux-1"}}"#, diff --git a/host/tests/it/p3.rs b/host/tests/it/p3.rs index 62c2d0e..c2cc520 100644 --- a/host/tests/it/p3.rs +++ b/host/tests/it/p3.rs @@ -1,4 +1,5 @@ //! P3 exit scenario across worker, check, and recorded fast-forward SIGKILL boundaries. +use crate::common::copy_tree; use sausage::{harness::run_module, world::World}; use std::{ path::Path, @@ -22,19 +23,6 @@ fn git(repo: &Path, args: &[&str]) -> anyhow::Result { ); Ok(String::from_utf8(output.stdout)?.trim().into()) } -fn copy_tree(source: &Path, destination: &Path) -> anyhow::Result<()> { - std::fs::create_dir_all(destination)?; - for entry in std::fs::read_dir(source)? { - let entry = entry?; - let target = destination.join(entry.file_name()); - if entry.file_type()?.is_dir() { - copy_tree(&entry.path(), &target)?; - } else { - std::fs::copy(entry.path(), target)?; - } - } - Ok(()) -} fn prepare(dir: &Path, all_extensions: bool) -> anyhow::Result<()> { World::open(dir)?; let disk = dir.join("world");