From a4e200731a4dec9f712b1dbedf79c28d53ca8b06 Mon Sep 17 00:00:00 2001 From: skylartaylor Date: Sun, 8 Nov 2026 19:54:11 +0100 Subject: [PATCH] ci: limit concurrent GPU tests in nextest --- .config/nextest.toml | 11 +++++++++++ crates/ui-egui/tests/it/ui_unreadable_footage.rs | 4 ++++ docs/testing.md | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/.config/nextest.toml b/.config/nextest.toml index 2a4cd2cb9..38f939c31 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -1,3 +1,14 @@ # Minimum cargo-nextest for this repository: GHSA-vc25-qg58-w57c is fixed in 0.9.150 and CI # installs exactly that version, so an older nextest refuses to run (exit 92 REQUIRED_VERSION_NOT_MET). nextest-version = "0.9.150" + +[test-groups] +gpu = { max-threads = 1 } + +# Coverage runs each test in a separate process, so the GPU suite's in-process lock +# cannot protect software adapters from competing devices and readback timeouts. +# UI harnesses can create a device lazily when rendering a screenshot, so include +# the whole UI package instead of an incomplete list of GPU-named tests. +[[profile.default.overrides]] +filter = 'package(effectcraft-gpu) | package(effectcraft-ui-egui) | package(effectcraft-sam2) | (package(effectcraft-cli) & test(/^cli::gpu_adapter_name_/))' +test-group = 'gpu' diff --git a/crates/ui-egui/tests/it/ui_unreadable_footage.rs b/crates/ui-egui/tests/it/ui_unreadable_footage.rs index 21ca1e7c9..4d283d62d 100644 --- a/crates/ui-egui/tests/it/ui_unreadable_footage.rs +++ b/crates/ui-egui/tests/it/ui_unreadable_footage.rs @@ -184,11 +184,15 @@ fn restored_original_and_active_proxy_render_new_pixels_through_media_and_disk_c let cached = s.render(comp, Tick::ZERO, RenderOpts::default()); assert_eq!(cached.data, before.data); assert!(cache.stats().hits > 0, "the same media was read back through the disk cache"); + let changed_time = std::fs::metadata(&active).unwrap().modified().unwrap() + std::time::Duration::from_secs(7); std::fs::remove_file(&active).unwrap(); assert_eq!(s.execute("footage.reloadChanged", json!({})).unwrap()["reloaded"], 0, "availability alone drives recovery in this fixture"); let offline = s.render(comp, Tick::ZERO, RenderOpts::default()); assert_eq!(offline.data[8 * 16 + 8], [0.0, 0.0, 0.0, 0.0]); image::RgbaImage::from_pixel(16, 16, image::Rgba([0, 0, 255, 255])).save(&active).unwrap(); + // Changed media needs a distinct stamp, even when both writes land in one filesystem + // clock tick. Same-size, same-stamp replacements require explicit Reload Footage. + std::fs::File::options().append(true).open(&active).unwrap().set_modified(changed_time).unwrap(); assert_eq!(s.execute("footage.reloadChanged", json!({})).unwrap()["reloaded"], 0, "availability alone drives recovery in this fixture"); let restored = s.render(comp, Tick::ZERO, RenderOpts::default()); assert_eq!(restored.data[8 * 16 + 8], [0.0, 0.0, 1.0, 1.0], "restored pixels replace decoded and composited cached frames"); diff --git a/docs/testing.md b/docs/testing.md index e84a9a23b..6091fe7a8 100644 --- a/docs/testing.md +++ b/docs/testing.md @@ -28,6 +28,15 @@ profile: `cargo run --profile dev-full -p effectcraft -- --demo` (see `CONTRIBUT runs `missing_translations_report` with `--nocapture`, which prints the interface strings each language has no translation for. Those strings show in English; the report always passes. +Direct nextest runs, including archived coverage shards, serialise `effectcraft-gpu`, +`effectcraft-ui-egui`, `effectcraft-sam2` and the CLI adapter tests through the `gpu` test group +in `.config/nextest.toml`. Their process-local mutexes cannot coordinate nextest's separate +processes; competing software devices can time out during readback. UI harnesses can also +create a device lazily when rendering a screenshot. This also reduces UI and SAM2 test +parallelism in the normal gate. `cargo xtask ci` still runs the GPU library suite in one +process to reuse its device. Group limits apply within one nextest invocation, not across +separate invocations, and cannot prevent timeouts from other host workloads. + Each crate with several integration-test files has one test binary, `tests/it/main.rs`, whose modules are the files in `tests/it/`. Run one file with `cargo test -p --test it ::` or `cargo nextest run -p -E 'binary(it) and test(/^::/)'`.