From 49fb1b1b356e88b64a6d5e5a90543146e482c18a Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 9 Oct 2026 09:21:57 -0400 Subject: [PATCH] Tests: one wgpu device compiles shaders at a time in fill_sign.rs (WARP ARM64 crash) (#395) The image-signature tests (#335, #355) render pixels in parallel; on the Windows 11 ARM64 runner WARP's pixel-shader JIT then crashes the test process with STATUS_ACCESS_VIOLATION (3 of the last 4 main runs). Take the same GPU lock tests/view.rs uses (d341651) in every fill_sign test that renders. Co-authored-by: Claude Opus 5.5 --- crates/ui-egui/tests/fill_sign.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/ui-egui/tests/fill_sign.rs b/crates/ui-egui/tests/fill_sign.rs index 2e85ff76..87dc0d59 100644 --- a/crates/ui-egui/tests/fill_sign.rs +++ b/crates/ui-egui/tests/fill_sign.rs @@ -13,6 +13,16 @@ const FIXTURE: &[u8] = b"%PDF-1.7 trailer << /Root 1 0 R >> %%EOF"; +/// Tests that render pixels (`h.render()`) take this first, so only one wgpu device compiles +/// shaders at a time: WARP's ARM64 pixel-shader JIT crashes when two do (see `tests/view.rs`). +/// Declared before the harness, so it is released after the device is dropped. +static GPU: std::sync::Mutex<()> = std::sync::Mutex::new(()); + +fn gpu() -> std::sync::MutexGuard<'static, ()> { + // A test that panicked while holding it leaves nothing to clean up. + GPU.lock().unwrap_or_else(std::sync::PoisonError::into_inner) +} + fn harness() -> Harness<'static, PdfCraftApp> { harness_bytes(FIXTURE) } @@ -361,6 +371,7 @@ fn browse_image(h: &mut Harness<'static, PdfCraftApp>, path: &std::path::Path) { #[test] fn image_signatures_and_initials_can_be_imported_placed_and_remembered() { + let _gpu = gpu(); let path = signature_file("import"); let mut h = harness(); for (command, y, initials) in [("sign.fill.signature", 250.0, false), ("sign.fill.initials", 150.0, true)] { @@ -426,6 +437,7 @@ fn image_signatures_and_initials_can_be_imported_placed_and_remembered() { #[test] fn image_signature_preview_follows_pointer_at_page_size_with_zoom_and_rotation() { + let _gpu = gpu(); // The block above the stroke is at its right end, away from the pointer's own cursor. let path = signature_file_with_mark("pointer", 100..110); let image = pdfcraft_engine::SignatureImage::read(std::fs::File::open(&path).unwrap()).unwrap(); @@ -495,6 +507,7 @@ fn image_signature_preview_follows_pointer_at_page_size_with_zoom_and_rotation() #[test] fn image_signature_placement_selects_resize_handles_and_requires_reselecting_to_repeat() { + let _gpu = gpu(); let path = signature_file("resize"); let image = pdfcraft_engine::SignatureImage::read(std::fs::File::open(&path).unwrap()).unwrap(); let mut h = harness(); @@ -568,6 +581,7 @@ fn has_blue_near(pixels: &image::RgbaImage, p: Pos2) -> bool { #[test] fn image_signature_live_resize_and_move_preserve_background_and_hide_moving_handles() { + let _gpu = gpu(); // Original synthetic page content; a white patch over the old image would fail this test. const GREEN_PAGE: &[u8] = b"%PDF-1.7\n1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 /MediaBox [0 0 300 400] >> endobj\n3 0 obj << /Type /Page /Parent 2 0 R /Contents 4 0 R >> endobj\n4 0 obj << /Length 36 >> stream\n0.8 1 0.7 rg 0 0 300 400 re f\nendstream\nendobj\ntrailer << /Root 1 0 R >>\n%%EOF"; let mut h = harness_bytes(GREEN_PAGE); @@ -680,6 +694,7 @@ fn image_signature_live_resize_and_move_preserve_background_and_hide_moving_hand #[test] fn embedded_image_signature_live_gestures_follow_document_and_view_rotation() { + let _gpu = gpu(); let path = signature_file("live-rotations"); let image = pdfcraft_engine::SignatureImage::read(std::fs::File::open(&path).unwrap()).unwrap(); for (document_rotation, view_rotation) in [(90, 0), (0, 90), (90, 270)] { @@ -745,6 +760,7 @@ fn embedded_image_signature_live_gestures_follow_document_and_view_rotation() { #[test] fn image_signature_corners_restore_original_aspect_after_edge_resize_and_reopen() { + let _gpu = gpu(); let path = signature_file("aspect"); let image = pdfcraft_engine::SignatureImage::read(std::fs::File::open(&path).unwrap()).unwrap(); let mut h = harness();