From db84293af1cce7ac33a3bc512051be534db9b886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20T=C3=B6rcsv=C3=A1ri?= Date: Fri, 14 Aug 2026 21:46:24 +0200 Subject: [PATCH] tests: fix two-tab collab baseline race + build the jspi harnesses in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) pcbnew/eeschema two-tab 'a local move propagates A->B' read the pre-move baseline AFTER kicadCollabTestMoveFirst. The move is queued through CallAfter + the apply coroutine, and the drain can land between two consecutive page.evaluate round-trips — when it does (~50% under CI load, reproduced locally with --repeat-each) orig captures the ALREADY-MOVED position and the not-toBe poll waits on itself. Wire tracing showed the bridge working: the moved delta emits, nothing reverts. Fix: baseline from kicadCollabSnapshot BEFORE the move. 12/12 green at --repeat-each=4 (was ~50% red). 2) jspi-firefox suites 404'd their harness modules: jspi-stack and jspi-coroutine build via ad-hoc build.sh (Phase 3 Makefile wiring TODO) which CI never ran. Wire both into build-wasm-test.sh (its hash is already in the testapps cache key), and add the _pt pthread variant that index.html?pt=1 loads but nothing built. jspi-firefox 8/8 green locally. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01PmR6goSk7JC17h7fkgGvHG --- scripts/build-wasm-test.sh | 13 +++++++++ tests/apps/standalone/jspi-coroutine/build.sh | 28 +++++++++++++------ tests/kicad/eeschema-collab.spec.ts | 12 +++++++- tests/kicad/pcbnew-collab.spec.ts | 12 +++++++- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/scripts/build-wasm-test.sh b/scripts/build-wasm-test.sh index e951b0a..101325c 100755 --- a/scripts/build-wasm-test.sh +++ b/scripts/build-wasm-test.sh @@ -117,6 +117,19 @@ fi echo "" echo "=== Build complete ===" +# JSPI micro-harnesses (jspi-stack, jspi-coroutine): still on their ad-hoc +# per-directory build.sh scripts (Makefile.wasm wiring is the Phase 3 TODO). +# Without this the jspi/ Playwright suites 404 their built .mjs modules on any +# machine that never ran the scripts by hand — which is exactly what CI is. +if [ -z "$TARGET" ]; then + echo "" + echo "=== JSPI micro-harnesses ===" + for harness in jspi-stack jspi-coroutine; do + echo "Building $harness..." + "$STANDALONE_DIR/$harness/build.sh" + done +fi + if [ -n "$TARGET" ]; then # Show just the built target echo "" diff --git a/tests/apps/standalone/jspi-coroutine/build.sh b/tests/apps/standalone/jspi-coroutine/build.sh index 1c70b0f..4598312 100755 --- a/tests/apps/standalone/jspi-coroutine/build.sh +++ b/tests/apps/standalone/jspi-coroutine/build.sh @@ -7,14 +7,24 @@ ROOT="$(cd ../../../.. && pwd)" EMXX="${EMXX:-$ROOT/tools/emsdk/upstream/emscripten/em++}" LIBCTX="$ROOT/kicad/thirdparty/libcontext" -"$EMXX" coroutine_jspi_test.cpp "$LIBCTX/libcontext.cpp" \ - -I"$LIBCTX" \ - \ - -O1 \ - -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -sWASM_LEGACY_EXCEPTIONS=1 \ - -sJSPI -sJSPI_EXPORTS=pcbjam_libctx_entry,main \ - -sMODULARIZE=1 -sEXPORT_ES6=1 -sENVIRONMENT=node,web \ - -sALLOW_MEMORY_GROWTH=1 \ +COMMON=( + -I"$LIBCTX" + -O1 + -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -sWASM_LEGACY_EXCEPTIONS=1 + -sJSPI -sJSPI_EXPORTS=pcbjam_libctx_entry,main + -sMODULARIZE=1 -sEXPORT_ES6=1 + -sALLOW_MEMORY_GROWTH=1 +) + +"$EMXX" coroutine_jspi_test.cpp "$LIBCTX/libcontext.cpp" "${COMMON[@]}" \ + -sENVIRONMENT=node,web \ -o coroutine_jspi_test.mjs -echo "built: coroutine_jspi_test.mjs" +# pthread variant (index.html?pt=1 / run_pt.mjs) — same battery with the +# pthread runtime linked, mirroring jspi-stack's *_pt build. +"$EMXX" coroutine_jspi_test.cpp "$LIBCTX/libcontext.cpp" "${COMMON[@]}" \ + -pthread -sPTHREAD_POOL_SIZE=2 -sPTHREAD_POOL_SIZE_STRICT=0 \ + -sENVIRONMENT=node,web,worker \ + -o coroutine_jspi_test_pt.mjs + +echo "built: coroutine_jspi_test.mjs + coroutine_jspi_test_pt.mjs" diff --git a/tests/kicad/eeschema-collab.spec.ts b/tests/kicad/eeschema-collab.spec.ts index 8689f94..793e7b2 100644 --- a/tests/kicad/eeschema-collab.spec.ts +++ b/tests/kicad/eeschema-collab.spec.ts @@ -254,9 +254,19 @@ test.describe("eeschema collab bridge — two tabs (BroadcastChannel)", () => { await startCollab(tabA); await startCollab(tabB); + // Read the pre-move baseline BEFORE triggering the move: TestMoveFirst + // queues the commit through CallAfter + the apply coroutine, and the drain + // can land between two consecutive page.evaluate round-trips. A GetPos + // taken after the call raced that drain (~50% under CI load) and captured + // the ALREADY-MOVED position, so the not-toBe poll waited on itself. + const preSnap = await tabA.evaluate(() => JSON.parse(window.Module.kicadCollabSnapshot())); + const prePos = new Map( + preSnap.added.map((i: { id: string; x: number; y: number }) => [i.id, `${i.x},${i.y}`]), + ); const uuid = await tabA.evaluate(() => window.Module.kicadCollabTestMoveFirst(2_000_000, 0)); expect(uuid).toMatch(/[0-9a-f-]{36}/); - const orig = await tabA.evaluate((id) => window.Module.kicadCollabGetPos(id), uuid); + const orig = prePos.get(uuid); + expect(orig, "moved item present in pre-move snapshot").toBeTruthy(); // Wait until tab A's item actually moved (guards against a no-op false pass). await expect diff --git a/tests/kicad/pcbnew-collab.spec.ts b/tests/kicad/pcbnew-collab.spec.ts index f1c4130..5506310 100644 --- a/tests/kicad/pcbnew-collab.spec.ts +++ b/tests/kicad/pcbnew-collab.spec.ts @@ -460,9 +460,19 @@ test.describe("pcbnew collab bridge — two tabs (BroadcastChannel)", () => { await startCollab(tabA); await startCollab(tabB); + // Read the pre-move baseline BEFORE triggering the move: TestMoveFirst + // queues the commit through CallAfter + the apply coroutine, and the drain + // can land between two consecutive page.evaluate round-trips. A GetPos + // taken after the call raced that drain (~50% under CI load) and captured + // the ALREADY-MOVED position, so the not-toBe poll waited on itself. + const preSnap = await tabA.evaluate(() => JSON.parse(window.Module.kicadCollabSnapshot())); + const prePos = new Map( + preSnap.added.map((i: { id: string; x: number; y: number }) => [i.id, `${i.x},${i.y}`]), + ); const uuid = await tabA.evaluate(() => window.Module.kicadCollabTestMoveFirst(2_000_000, 0)); expect(uuid).toMatch(/[0-9a-f-]{36}/); - const orig = await tabA.evaluate((id) => window.Module.kicadCollabGetPos(id), uuid); + const orig = prePos.get(uuid); + expect(orig, "moved item present in pre-move snapshot").toBeTruthy(); await expect .poll(() => tabA.evaluate((id) => window.Module.kicadCollabGetPos(id), uuid), {