From bfcd71e2f4e3ae08491bf268164b1cb6c1db9851 Mon Sep 17 00:00:00 2001 From: Sausage Agent Date: Sat, 17 Oct 2026 16:25:14 +0000 Subject: [PATCH] test packaged host cargo runtime with an empty PATH --- flake.nix | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 538486d..a09f1bf 100644 --- a/flake.nix +++ b/flake.nix @@ -21,9 +21,11 @@ targets = [ "wasm32-wasip2" ]; extensions = [ "rust-src" ]; }; - # Crane builds the dependencies once (`cargoArtifacts`, keyed only on - # Cargo.toml/Cargo.lock), so a change to our own crates rebuilds - # just them. + # The runtime cargo actor needs Cargo, rustc (with wasm32-wasip2), and + # the native linker, even when the host itself is started with a bare + # PATH. Keep this same runtime path in the packaged host and exercise + # the installed binary below with PATH deliberately empty. + runtimePath = pkgs.lib.makeBinPath [ rust pkgs.stdenv.cc ]; craneLib = (crane.mkLib pkgs).overrideToolchain rust; common = { pname = "sausage"; @@ -47,7 +49,7 @@ nativeBuildInputs = [ pkgs.makeWrapper ]; # The `cargo` actor runs cargo at runtime. Build scripts need a C linker. postInstall = '' - wrapProgram $out/bin/sausage --prefix PATH : ${pkgs.lib.makeBinPath [ rust pkgs.stdenv.cc ]} + wrapProgram $out/bin/sausage --prefix PATH : ${runtimePath} ''; meta.mainProgram = "sausage"; }); @@ -91,6 +93,67 @@ rm -f cli/tests/actors/toolbox/Cargo.lock ''; }); + # Exercise the installed host exactly as the loop launches it: the + # caller has no Cargo on PATH, so only the packaged runtime toolchain + # can run the native tests and the wasm32-wasip2 build. + checks.runtime-toolchain = pkgs.runCommand "sausage-runtime-toolchain" { + nativeBuildInputs = [ pkgs.expect ]; + } '' + set -eu + root="$TMPDIR/runtime-toolchain" + world="$root/world" + emptyPath="$root/empty-bin" + mkdir -p "$emptyPath" "$root/home" "$root/cargo-home" + for actor in broker console cargo fs; do + mkdir -p "$world/actor/$actor/public" "$world/actor/$actor/data" + done + source="$world/actor/console/public/probe" + mkdir -p "$source/src" "$source/tests" + cat > "$source/Cargo.toml" <<'TOML' + [package] + name = "runtime-probe" + version = "0.1.0" + edition = "2024" + TOML + printf 'fn main() {}\n' > "$source/src/main.rs" + cat > "$source/tests/probe.rs" <<'RUST' + #[test] + fn native_test_harness_runs() { + assert_eq!(2 + 2, 4); + } + RUST + export SAUSAGE_BIN=${sausage}/bin/sausage + export WORLD="$world" + export EMPTY_PATH="$emptyPath" + expect <<'EOF' + log_user 1 + set timeout 300 + set env(PATH) $::env(EMPTY_PATH) + set env(HOME) $::env(WORLD) + set env(TMPDIR) [file dirname $::env(WORLD)] + set env(CARGO_HOME) [file join [file dirname $::env(WORLD)] cargo-home] + spawn $::env(SAUSAGE_BIN) run $::env(WORLD) + send -- "@cargo {\"type\":\"build\",\"source\":\"/actor/console/public/probe\"}\r" + expect { + -re {"type":"build_failed"} { + puts stderr "packaged cargo actor build failed with an empty caller PATH" + exit 1 + } + -re {"type":"built"} { + expect { + -re {"passed":1} { send -- "/quit\r" } + timeout { puts stderr "native cargo test did not pass"; exit 1 } + } + } + timeout { puts stderr "packaged host did not build the probe"; exit 1 } + } + expect eof + set result [wait] + if {[lindex $result 3] != 0} { exit [lindex $result 3] } + EOF + mkdir -p "$out" + touch "$out/passed" + ''; apps.default = { type = "app"; program = "${sausage}/bin/sausage"; }; apps.loop = { type = "app"; program = "${loop}/bin/sausage-loop"; };