open-standards/joule-code/joule-code-rs/crates/joule-moq-web/e2e/run.sh
Transaction Science b2460856c7
Some checks failed
wai release binaries build on Windows / the seven release binaries · windows (push) Waiting to run
wai-ledger service / does this change touch it (push) Successful in 19s
wai-quantum studio and desktop / does this change touch it (push) Successful in 20s
wai-audit collector and player integration / does this change touch it (push) Successful in 22s
wai-fleet service / does this change touch it (push) Successful in 21s
wai-quantum studio and desktop / desktop app · windows (push) Waiting to run
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Successful in 49s
wai-sink-android native sink library / does this change touch it (push) Successful in 33s
wai-sink-swift native sink package / does this change touch it (push) Successful in 33s
WAI Studio / does this change touch it (push) Successful in 31s
joule-moq-http live HTTP egress / joule-moq-http · does this change touch it (push) Successful in 1m50s
WAI operation catalogue / does this change touch it (push) Successful in 2m10s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Successful in 3m32s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Successful in 4m14s
wai-app and Create / wai-app · does this change touch it (push) Successful in 4m7s
wai-quantum for JavaScript / does this change touch it (push) Successful in 4m5s
wai-pack / wai-pack · does this change touch it (push) Successful in 4m5s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 11s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Waiting to run
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Waiting to run
WAI examples / WAI examples · does this change touch them (push) Successful in 10s
WAI examples / WAI examples · portable · linux (push) Waiting to run
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Waiting to run
WAI examples / WAI examples · android-app · linux-arm64 (push) Waiting to run
wai web player plugins / the browser run's room compiles · linux (push) Successful in 1m6s
wai tv web application / the tv application, built to its baseline and checked · linux (push) Successful in 4m16s
wai-ledger service / service · linux (push) Successful in 3m27s
wai web player plugins / the plugins' core under Node · linux (push) Successful in 4m50s
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 5m43s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m25s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Successful in 53s
wai-audit collector and player integration / collector · linux (push) Successful in 3m14s
wai-fleet service / service · linux (push) Successful in 3m39s
wai-quantum studio and desktop / studio · browser (push) Successful in 7m2s
wai-pack / wai-pack · linux (push) Successful in 4m45s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 10m23s
wai-quantum for JavaScript / javascript · linux (push) Successful in 11m53s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 21m20s
WAI Studio / Studio in WebKit · linux (push) Failing after 23m24s
joule-code conformance gate / joule-moq-relay, every target (push) Successful in 9m41s
joule-moq-http live HTTP egress / joule-moq-http, every target (push) Successful in 7m32s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Successful in 8m24s
joule-code conformance gate / joule-moq-ingest, every target (push) Successful in 16m32s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 11m13s
wai-pack / wai-pack · dependency licences (push) Successful in 1m35s
wai-ledger service / service · macos (push) Successful in 1m11s
joule-moq-room room service / joule-moq-room, every target (push) Failing after 13m12s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 2m23s
wai-pack / wai-pack · the floor through a media prober (push) Failing after 5m42s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m9s
wai-pack / wai-pack · linux-arm64 (push) Successful in 9m16s
wai-fleet service / service · macos (push) Successful in 43s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 4m12s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 25m43s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 7m44s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Successful in 49s
wai tv web application / the tv application in Chromium, Firefox and WebKit · macos (push) Successful in 13m30s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Failing after 5m56s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Successful in 15m28s
joule-moq-http in browsers / the egress and the protected room in Chromium, Firefox and WebKit · macos (push) Successful in 20m5s
wai-pack / wai-pack · independent verifier (Python) (push) Successful in 24m35s
WAI Studio / Studio in Chromium and Firefox · macos (push) Failing after 11m46s
wai-pack / wai-pack · macos (push) Successful in 7m52s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Successful in 18m41s
wai web player plugins / the three players in Chromium, Firefox and WebKit · macos (push) Successful in 23m52s
joule-moq-web: the room page plays its session's stitched tracks, each Object held to the stitcher's receipts and its stamps
In a stitched room (GET /room's ads, live-ads §14.8) the room page makes a session key,
states its session and its device binding to the room service (web/ads/traffic.js's
bind()), reads its session's catalog in [room, stitcher, video, stitched, D, K], and plays
its composed video and sound in place of the programme (web/room/source.js, SourceView's
stitched). Each Object is held to the stitcher's group receipts under the composed track's
alias, 200 for the video and 201 for the sound, whatever the unsigned catalog states; its
stamps to the composed timeline (ComposedClock, live-ads §14.3: stitch_untimed,
stitch_delay_other, stitch_timing_off), the timeline going on over every Object so that a
refused one refuses nothing after it; a group whose receipts are refused has its Objects
refused with their reason. A refused Object is not presented.

web/room/source.test.mjs holds ComposedClock to the ad-signalling corpus's stitch.timing
cases, a third implementation of the rule. e2e/room.e2e.mjs's scenario stitched plays a
stitched room through two breaks in the installed browser and plants three faults in what
the page is given: a byte of a creative's Object (payload_mismatch), a Group's receipts of
the other composed track (moqt_mismatch), a composed Object with its timing taken off
(stitch_untimed); each must be refused on the page.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 23:05:04 -05:00

172 lines
9.8 KiB
Shell
Executable file

#!/bin/bash
# Build what the browser MoQ client's tests need, and run them.
#
# e2e/run.sh [--only compose,webtransport,websocket,goaway,dvr,service,e2ee,age,co,ageco,binding,cowatch,source,stitched,origin,termination,remote,world,privateworld,messaging,call,offers,conform] [--runs N]
#
# 1. joule-moq-relay, joule-moq-room and joule-moq-remote (each its own workspace) and
# wai_live_web (native, release: the test room, the host's composition, and the remote
# desktop host agent);
# 2. joule-moq-web and wai-live-web for wasm32-unknown-unknown, through wasm-bindgen's web
# target into web/pkg/, each with its own --out-name; and joule-moq-web again with its
# feature e2ee (the member of an end-to-end encrypted room), under the workspace's `wasm`
# profile and with no name section, as joule_moq_web_e2ee, which a page loads for such a
# room alone; and wai-live-web again with its feature int_video, as wai_live_web_decode,
# the decoder on the browser sink's wasm route, which the binding page loads;
# 3. the browser-automation package from e2e/package-lock.json (`npm ci --ignore-scripts`:
# no install script runs), outside the tree unless PLAYWRIGHT_HOST names one installed;
# 4. the Node unit tests of the page's own modules;
# 5. WAI's local stack, `wai dev --check` (`wai`, wai-rs with quickstart and browser_sink, debug):
# the relay and the room service built in step 1, from the configuration wai dev writes, and
# the page and its WebAssembly from web/, each checked through its one origin, then stopped;
# the relay and the room service must be of wai's toolchain, or the stack is refused as stale;
# 6. e2e/room.e2e.mjs, in the installed browser whose executable BROWSER_BIN names (the
# CI job names the host's), otherwise the package's own, which PLAYWRIGHT_BROWSERS_PATH
# must then hold;
# 7. e2e/messaging.e2e.mjs, the messaging view and the call flow (WAI live-messaging), in the
# same browser. `--only` picks scenarios of either file by name;
# 8. `conform`: the page web/binding/sink.html as a browser sink through WAI's conformance
# runner (`wai`, wai-rs with quickstart and browser_sink, debug), by e2e/conform_sink.mjs in
# the same browser: every call of live-conformance/browser answered by the page's wasm and
# its side table, the record signed and admitted (`wai verify --conformant`); and a planted
# page that shows a refused frame as verified, whose run must fail at that case;
# 9. `offers`: web/offers/run.mjs in the same browser, an offer presented and acted on against a
# fixture merchant on loopback (WAI shoppable-events), its intent and the merchant's order
# held to the offer by wai-rs's vectors binary (feature shoppable_events, debug), and its
# planted faults, each refused with its own reason.
#
# Environment: CARGO_TARGET_DIR (one target directory for both workspaces), BROWSER_BIN,
# PLAYWRIGHT_HOST, MOQ_WEB_OUT (where artifacts go), CARGO_LOCKED (default --locked).
# Nothing listens beyond loopback: the relay and the page server bind 127.0.0.1.
set -euo pipefail
HERE=$(cd "$(dirname "$0")" && pwd)
CRATE=$(cd "$HERE/.." && pwd)
JC=$(cd "$CRATE/../.." && pwd)
ROOT=$(cd "$JC/../.." && pwd)
WLW="$ROOT/wai/wai-live-web"
LOCKED=${CARGO_LOCKED---locked}
TARGET=${CARGO_TARGET_DIR:-$JC/target}
export CARGO_TARGET_DIR="$TARGET"
OUT=${MOQ_WEB_OUT:-${TMPDIR:-/tmp}/moq-web-e2e}
mkdir -p "$OUT"
# Each run starts from no results: a scenario writes keys and logs there, and the room
# service's keygen refuses a key file a previous run left.
rm -rf "$OUT/results"
PKG="$CRATE/web/pkg"
mkdir -p "$PKG"
step() { echo "== $*"; }
step "native: wai-relay, wai-room, wai_live_web"
(cd "$JC" && cargo build $LOCKED --release -p joule-moq-relay --bin wai-relay)
(cd "$CRATE/../joule-moq-room" && cargo build $LOCKED --release --bin wai-room)
(cd "$CRATE/../joule-moq-remote" && cargo build $LOCKED --release --bin wai-remote-host)
(cd "$WLW" && cargo build $LOCKED --release --bin wai_live_web)
step "wasm: joule-moq-web, wai-live-web"
command -v wasm-bindgen >/dev/null || { echo "wasm-bindgen CLI 0.2.127 is needed (cargo install --locked wasm-bindgen-cli --version 0.2.127)"; exit 2; }
wasm-bindgen --version | grep -q ' 0\.2\.127$' || { echo "the wasm-bindgen CLI must be 0.2.127, the version both crates pin"; exit 2; }
(cd "$JC" && cargo build $LOCKED --release -p joule-moq-web --lib --target wasm32-unknown-unknown)
wasm-bindgen --target web --out-dir "$PKG" --out-name joule_moq_web "$TARGET/wasm32-unknown-unknown/release/joule_moq_web.wasm"
(cd "$JC" && cargo build $LOCKED --profile wasm -p joule-moq-web --lib --target wasm32-unknown-unknown --features e2ee)
wasm-bindgen --target web --remove-name-section --remove-producers-section --out-dir "$PKG" --out-name joule_moq_web_e2ee "$TARGET/wasm32-unknown-unknown/wasm/joule_moq_web.wasm"
(cd "$WLW" && cargo build $LOCKED --release --lib --target wasm32-unknown-unknown)
wasm-bindgen --target web --out-dir "$PKG" --out-name wai_live_web "$TARGET/wasm32-unknown-unknown/release/wai_live_web.wasm"
(cd "$WLW" && cargo build $LOCKED --release --lib --target wasm32-unknown-unknown --features int_video)
wasm-bindgen --target web --out-dir "$PKG" --out-name wai_live_web_decode "$TARGET/wasm32-unknown-unknown/release/wai_live_web.wasm"
ls -l "$PKG"/*.wasm
step "browser automation"
if [ -z "${PLAYWRIGHT_HOST:-}" ]; then
PW="$OUT/pw"
mkdir -p "$PW"
cp "$HERE/package.json" "$HERE/package-lock.json" "$PW/"
(cd "$PW" && npm ci --ignore-scripts --no-audit --no-fund)
export PLAYWRIGHT_HOST="$PW/node_modules"
fi
BROWSER_BIN=${BROWSER_BIN:-}
step "unit tests of the page's modules"
node --test "$CRATE/e2e/compose.test.mjs" "$CRATE/e2e/remote_input.test.mjs" "$CRATE/web/moq/capsule.test.mjs" "$CRATE/web/moq/media.test.mjs" "$CRATE/web/moq/session.test.mjs" "$CRATE/web/ads/presentation.test.mjs" "$CRATE/web/ads/traffic.test.mjs" "$CRATE/web/offers/offers.test.mjs" "$CRATE/web/room/privacy-pass.test.mjs" "$CRATE/web/room/binding.test.mjs" "$CRATE/web/room/cowatch.test.mjs" "$CRATE/web/room/co.test.mjs" "$CRATE/web/room/remote.test.mjs" "$CRATE/web/room/markup.test.mjs" "$CRATE/web/room/endpoint.test.mjs" "$CRATE/web/room/termination.test.mjs" "$CRATE/web/room/catalog.test.mjs" "$CRATE/web/room/tempo.test.mjs" "$CRATE/web/room/source.test.mjs"
step "the local stack: wai dev --check"
(cd "$ROOT/wai/wai-rs" && cargo build $LOCKED --no-default-features --features quickstart,browser_sink --bin wai)
"$TARGET/debug/wai" dev --check --port 0 --dir "$OUT/results/dev" \
--relay "$TARGET/release/wai-relay" --room "$TARGET/release/wai-room" --web "$CRATE/web"
step "end-to-end"
browser=()
[ -n "$BROWSER_BIN" ] && browser=(--browser "$BROWSER_BIN")
# `--only` names scenarios of room.e2e.mjs and of messaging.e2e.mjs: each file runs its own.
room_args=() msg_only="messaging,call" room_only="" only=0 conform=1 offers=1
while [ $# -gt 0 ]; do
if [ "$1" = "--only" ] && [ $# -ge 2 ]; then
only=1
msg_only=$(echo "$2" | tr ',' '\n' | grep -xE 'messaging|call' | paste -sd, - || true)
room_only=$(echo "$2" | tr ',' '\n' | grep -vxE 'messaging|call|conform|offers' | paste -sd, - || true)
echo "$2" | tr ',' '\n' | grep -qx conform || conform=0
echo "$2" | tr ',' '\n' | grep -qx offers || offers=0
shift 2
else
room_args+=("$1")
shift
fi
done
if [ "$only" = 0 ] || [ -n "$room_only" ]; then
node "$HERE/room.e2e.mjs" \
--relay "$TARGET/release/wai-relay" \
--room "$TARGET/release/wai-room" \
--wai "$TARGET/release/wai_live_web" \
--remote "$TARGET/release/wai-remote-host" \
--web "$CRATE/web" \
--corpus "$ROOT/wai/live-conformance/compose/vectors.json" \
--wai-dir "$ROOT/wai" \
--out "$OUT/results" \
${browser[@]+"${browser[@]}"} \
${room_only:+--only "$room_only"} \
${room_args[@]+"${room_args[@]}"}
fi
if [ -n "$msg_only" ]; then
step "end-to-end: conversations and calls"
node "$HERE/messaging.e2e.mjs" \
--relay "$TARGET/release/wai-relay" \
--room "$TARGET/release/wai-room" \
--web "$CRATE/web" \
--out "$OUT/results/messaging" \
--only "$msg_only" \
${browser[@]+"${browser[@]}"} \
${room_args[@]+"${room_args[@]}"}
fi
if [ "$offers" = 1 ]; then
# web/offers/: an offer presented and acted on against a fixture merchant on loopback (WAI
# shoppable-events), and its planted faults, each refused with its own reason.
step "an offer presented and acted on"
(cd "$ROOT/wai/wai-rs" && cargo build $LOCKED --no-default-features --features shoppable_events --bin wai_shoppable_events_vectors)
mkdir -p "$OUT/results/offers"
NODE_PATH="$PLAYWRIGHT_HOST" node "$CRATE/web/offers/run.mjs" "$TARGET/debug/wai_shoppable_events_vectors" "$OUT/results/offers"
fi
if [ "$conform" = 1 ]; then
step "the page as a browser sink, through wai conform"
C="$OUT/results/conform"
mkdir -p "$C/planted"
node "$HERE/conform_sink.mjs" --web "$CRATE/web" ${BROWSER_BIN:+--browser "$BROWSER_BIN"} \
--wai "$TARGET/debug/wai" --wai-dir "$ROOT/wai" --out "$C/browser-page.wai-conform.json"
# The planted page must fail as a run (exit 1), at the frame it shows wrongly.
set +e
node "$HERE/conform_sink.mjs" --web "$CRATE/web" ${BROWSER_BIN:+--browser "$BROWSER_BIN"} --plant \
--wai "$TARGET/debug/wai" --wai-dir "$ROOT/wai" --out "$C/planted/browser-page.wai-conform.json" > "$C/planted.txt" 2>&1
c=$?
set -e
# Its record still verifies, and admission refuses it at rule 2.
set +e
"$TARGET/debug/wai" verify --conformant --root "$ROOT/wai" "$C/planted" > "$C/planted-admit.txt" 2>&1
a=$?
set -e
if [ "$c" = 1 ] && grep -q '^FAIL frames/object_refused$' "$C/planted.txt" && [ "$a" = 1 ] && grep -q 'FAIL admission rule 2 not_conformant' "$C/planted-admit.txt"; then
echo "conform: the planted page was refused at frames/object_refused, and its record at admission rule 2"
else
cat "$C/planted-admit.txt"
cat "$C/planted.txt"
echo "FAIL conform: the planted page was not refused (exit $c)"
exit 1
fi
fi