test(wasm): close mutation package gate

Run browser-backed mutest sequentially without a parent jobserver, disable Firefox background work, batch replay projections while preserving ordered application, and elect a 250 ms budget for the durable 64-command browser fixture. All four hemx-wasm shards pass with 59 mutants and no survivors, closing the mutation matrix.

req: test/004

req: test/020

req: test/021

req: performance/005

req: performance/007

req: v1_release/006
This commit is contained in:
slhx agent
2026-07-17 17:11:19 +02:00
parent 0be05f4432
commit e7ca6d2350
7 changed files with 123 additions and 49 deletions
+67 -10
View File
@@ -1308,6 +1308,33 @@ fn mutation_shard(shard: Option<&str>) -> Result<Option<String>, String> {
Ok(Some(format!("{}/{total}", index - 1)))
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct MutationConcurrency {
jobs: usize,
test_threads: usize,
jobserver: bool,
}
fn mutation_concurrency(package: &str, budget: Budget) -> MutationConcurrency {
if package == "hemx-wasm" {
// Browser tests spawn nested Cargo builds plus Firefox. A parent jobserver can
// retain every token while those builds wait, and parallel browser sessions
// make timing assertions meaningless. Keep this package sequential and let
// its nested Cargo commands own the detected machine budget.
MutationConcurrency {
jobs: 1,
test_threads: 1,
jobserver: false,
}
} else {
MutationConcurrency {
jobs: budget.jobs,
test_threads: budget.test_threads,
jobserver: true,
}
}
}
fn run_mutation_plan(package: Option<&str>, shard: Option<&str>) -> ExitCode {
let packages = match mutation_packages(package) {
Ok(packages) => packages,
@@ -1356,17 +1383,24 @@ fn run_mutation_plan(package: Option<&str>, shard: Option<&str>) -> ExitCode {
return ExitCode::FAILURE;
}
}
let jobs = budget.jobs.to_string();
let concurrency = mutation_concurrency(package, budget);
let jobs = concurrency.jobs.to_string();
let mut command = Command::new(&mutest);
command
.current_dir(workspace_root())
// Mutest runs several cargo-test processes concurrently. Bound each nested
// harness by the same resource budget so browser-backed packages cannot
// multiply into Cargo's unconstrained default thread count.
// req: test/004 req: test/020
.env("RUST_TEST_THREADS", concurrency.test_threads.to_string())
.args(["-p", package, "-j", &jobs]);
if concurrency.jobserver {
command.args(["--jobserver-tasks", &jobs]);
} else {
command.args(["--jobserver", "false"]);
}
command
.args([
"-p",
package,
"-j",
&jobs,
"--jobserver-tasks",
&jobs,
"--colors",
"never",
"--annotations",
@@ -1623,9 +1657,10 @@ fn is_executable(path: impl AsRef<Path>) -> bool {
mod tests {
use super::{
android_twa_release_json, create_app_scaffold, create_mobile_app_scaffold,
create_workout_app, mobile_external_blockers, mutation_packages, mutation_shard,
origin_host, verify_workout_mobile_release, workout_mobile_manifest, workspace_root,
write_workout_mobile_release, Budget, WorkoutMobileConfig, MUTATION_PACKAGES,
create_workout_app, mobile_external_blockers, mutation_concurrency, mutation_packages,
mutation_shard, origin_host, verify_workout_mobile_release, workout_mobile_manifest,
workspace_root, write_workout_mobile_release, Budget, MutationConcurrency,
WorkoutMobileConfig, MUTATION_PACKAGES,
};
use std::fs;
use std::path::PathBuf;
@@ -1652,6 +1687,28 @@ mod tests {
// test req: test/022 req: test/023
}
#[test]
fn browser_mutation_runs_one_harness_without_a_parent_jobserver() {
let budget = Budget::from_resources(22, Some(27), None, None, true).with_jobs(4);
assert_eq!(
mutation_concurrency("hemx-wasm", budget),
MutationConcurrency {
jobs: 1,
test_threads: 1,
jobserver: false,
}
);
assert_eq!(
mutation_concurrency("hemx-core", budget),
MutationConcurrency {
jobs: 4,
test_threads: 4,
jobserver: true,
}
);
// test req: test/004 req: test/020
}
#[test]
fn verification_steps_resolve_the_workspace_independent_of_caller_directory() {
assert!(workspace_root().join("Cargo.toml").is_file()); // req: test/004