diff --git a/.github/workflows/wai-conformance.yml b/.github/workflows/wai-conformance.yml index aa18b7300..4668fa7b9 100644 --- a/.github/workflows/wai-conformance.yml +++ b/.github/workflows/wai-conformance.yml @@ -188,6 +188,39 @@ on: - 'wai/extensions/co-watch.md' # The co-watch step runs the browser client's co-watch module against the corpus. - 'joule-code/joule-code-rs/crates/joule-moq-web/web/room/cowatch*' + # tests/dred_exact.rs requires this extension's §8 to list the codes the reference + # reports and its §4 to state the reference's digests, tests/dred_exact_measure.rs its §6 + # table, dred_verify.py reads §4 and §8, and the registry's tests read SPEC §5 against it. + - 'wai/extensions/opus-dred.md' + # tests/telemetry_aggregate.rs requires this extension's §11 to list the codes the + # reference reports, telemetry_aggregate_verify.py reads that table, and the registry's + # wire identifiers test reads its sections. + - 'wai/extensions/telemetry-aggregation.md' + # tests/telemetry_aggregate.rs requires §3.4's table to class the keys the reference + # classes, and telemetry_aggregate_verify.py reads that table and §4.1 and §4.2's shards. + - 'wai/extensions/delivery-telemetry.md' + # tests/exact_tonemap.rs requires this extension's §9 to list the codes the reference + # reports and its §6 to state the corpus's measurement, tonemap_verify.py reads §3.3's + # table, §5.4's constant and §9, and the registry's wire identifiers test reads its + # sections. + - 'wai/extensions/exact-tonemap.md' + # tests/robustness.rs requires this extension's §12 to list the codes the reference + # reports and its §4 to register the reference's transforms, robustness_verify.py reads + # both, and the registry's wire identifiers test reads its sections. + - 'wai/extensions/robustness-evidence.md' + # tests/splat_exact.rs requires this extension's §10 to list the codes the reference + # reports and the draft schema under extensions/gltf/ to name §3.2's members, + # splat_exact_verify.py reads §10, and the registry's wire identifiers test reads its + # sections. + - 'wai/extensions/splat-exact.md' + - 'wai/extensions/gltf/**' + # splat_exact_verify.py decodes each payload with this tool's whm1/1 lowering and + # interpreter. + - 'wai/tools/wai_ops_check.py' + # tests/pq_signatures.rs requires this extension's §8 to list the codes the reference + # reports, pq_verify.py reads that table, and the registry's wire identifiers test reads + # its §2. + - 'wai/extensions/pq-signatures.md' - 'wai/wai-web/**' # The audio provenance check below reads the corpora above with this tool. - 'wai/tools/wai_audio_provenance_check.py' @@ -560,7 +593,7 @@ jobs: working-directory: wai/wai-rs run: | set -euo pipefail - F=world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest + F=world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest,pq_signatures v() { echo "::group::$1"; cargo run -q --no-default-features --features "$F" --bin "$2" -- verify "$3"; echo "::endgroup::"; } v worlds wai_world_vectors ../world-conformance v spatial-audio wai_audio_vectors ../audio-conformance @@ -583,6 +616,7 @@ jobs: v http wai_http_vectors ../http-conformance v staged-measure wai_stage_measure ../staged-measure-conformance v telemetry wai_telemetry ../telemetry-conformance + v pq-signatures wai_pq_vectors ../pq-conformance # The pin corpus's second implementation: Python standard library only, sharing no # code with wai-rs. One leg is enough — it checks digests and listing rules, which # do not depend on the architecture — and the macOS host has python3. @@ -629,7 +663,7 @@ jobs: shell: pwsh working-directory: wai/wai-rs run: | - $F = "world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest" + $F = "world,audio_scene,haptic,splat4d,score,provenance,neural_int,film,quantum,quantum_ops,oer,receipt_claims,key_discovery,video_int,audio_int,splat_int,staged,stage_measure,telemetry,http,video_manifest,pq_signatures" function v($grp, $bin, $path) { Write-Output "::group::$grp" cargo run -q --no-default-features --features $F --bin $bin -- verify $path @@ -657,6 +691,7 @@ jobs: v http wai_http_vectors ../http-conformance v staged-measure wai_stage_measure ../staged-measure-conformance v telemetry wai_telemetry ../telemetry-conformance + v pq-signatures wai_pq_vectors ../pq-conformance # wai-quantum and the quantum corpus under wasm32-wasip2, run by wasmtime. On wasm32 # usize is 32 bits, so arithmetic that cannot overflow on a 64-bit host can there: a @@ -1169,6 +1204,33 @@ jobs: (cd wai-rs && cargo test --no-default-features --features live_moderation --lib live_moderation::) (cd wai-rs && cargo test --no-default-features --features live_moderation --test live_moderation) python3 -I live-conformance/live_moderation_verify.py live-conformance/moderation + # wai.audio.opus.dred.int (extensions/opus-dred.md): first the draft's weights file and + # test vectors, which the corpus names by SHA-256 and does not hold, fetched from the + # draft's locations and checked against its digests (live-conformance/dred/fetch.sh). + # Then the reference module's unit tests (the range decoder against its encoder, the + # extension draft's worked examples, payloads round-trip, weights quantized from their + # bits, the activation tables, the driver on a synthetic set), tests/dred_exact.rs (the + # corpus regenerates byte for byte from its seeds and the weights and no other file is + # there, every payload and case reaches its outcome, §8 lists exactly the module's codes, + # §4 states its digests), and in release tests/dred_exact_measure.rs (every record of the + # draft's test vectors decoded through the profile and through the floating-point + # network: the profile passes the draft's feature test, and §6's table is what it + # measures). Then the corpus's second implementation, dred_verify.py, written from the + # extension's text and sharing no code with wai-rs, which recomputes every outcome, + # digest and row in its own integer arithmetic and requires every mutated copy of the + # corpus to fail; standard library only, run isolated (-I). + - name: opus deep redundancy · wai-rs and dred_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + d="${RUNNER_TEMP:-/tmp}/dred" + bash live-conformance/dred/fetch.sh "$d" vectors + w="$d/dred_unquantized_weights.bin" + (cd wai-rs && cargo test --no-default-features --features dred_exact --lib dred_exact::) + (cd wai-rs && WAI_DRED_WEIGHTS="$w" cargo test --release --no-default-features --features dred_exact --test dred_exact) + (cd wai-rs && WAI_DRED_WEIGHTS="$w" WAI_DRED_VECTORS="$d" cargo test --release --no-default-features --features dred_exact --test dred_exact_measure) + python3 -I live-conformance/dred_verify.py live-conformance/dred "$w" # wai.live.ads (extensions/live-ads.md): the reference module's unit tests (policies and # annotations round-trip and their rules refuse, a break's identity, tags, events and # asset lists written exactly), the break form of wai.video.ssai's receipt (its JSON @@ -1255,20 +1317,23 @@ jobs: (cd wai-rs && cargo test --no-default-features --features synthesis --lib synthesis::) (cd wai-rs && cargo test --no-default-features --features synthesis --test synthesis) python3 -I live-conformance/synthesis_verify.py live-conformance/synthesis - # The registered watermark scheme wai-mark:tent64 (extensions/synthesis.md §7.4 to §7.8): - # the reference's unit tests (the code corrects 29 errors and its generator is the - # definition's, the layout, the embedding and the detector in every orientation, the - # battery's resampling, rotation and keyframe), then tests/synthesis_mark.rs in release, - # since it embeds and attacks every picture of the measurement sets (every file of - # live-conformance/synthesis-mark/ regenerates byte for byte, the measurement among them, - # and no other file is there; every embedding, detection and case gets what it states; - # the extension's definition, generator polynomial and shuffle are the reference's; - # §7.5.8 claims only attacks the measurement shows survived, and §7.5.6's figures are the - # measurement's); then the second implementation, synthesis_mark_verify.py with + # The registered watermark schemes wai-mark:tent64 and wai-mark:tent64s + # (extensions/synthesis.md §7.4 to §7.9): the reference's unit tests (the code corrects 29 + # errors and its generator is the definition's, the layouts, the embedding and the + # detector in every orientation, the tiled detector's exact autocorrelation and its + # recovery from a crop and a rotation, the battery's resampling, rotation and keyframe), + # then tests/synthesis_mark.rs in release, since it embeds and attacks every picture of + # the measurement sets under both schemes (every file of live-conformance/synthesis-mark/ + # regenerates byte for byte, both measurements among them, and no other file is there; + # every embedding, detection and case gets what it states; the extension's definitions, + # generator polynomial and shuffles are the reference's; §7.5.8 and §7.9.7 claim only + # attacks the measurements show survived, and §7.5.6's and §7.9.5's figures are the + # measurements'); then the second implementation, synthesis_mark_verify.py with # _wai_mark.py, written from the extension's text and sharing no code with wai-rs, which - # embeds, detects and decodes itself, runs the battery's picture attacks, verifies every - # case with synthesis_verify.py, mutates copies of the corpus and weakens its own verifier - # in turn; standard library only, run isolated (-I). + # embeds, detects and decodes itself, both stages of the tiled detector among them, runs + # the battery's picture attacks, derives the frames the vectors name, verifies every case + # with synthesis_verify.py, mutates copies of the corpus and weakens its own verifier in + # turn; standard library only, run isolated (-I). - name: synthesis watermark · wai-rs and synthesis_mark_verify.py working-directory: wai shell: bash @@ -1300,6 +1365,29 @@ jobs: (cd wai-rs && cargo test --no-default-features --features exact_upscale --lib exact_upscale::) (cd wai-rs && cargo test --no-default-features --features exact_upscale --test exact_upscale) python3 -I live-conformance/upscale_verify.py live-conformance/upscale + # Robustness evidence for soft bindings (extensions/robustness-evidence.md): the + # reference's unit tests (gamma is the rounded power, rates are exact and reduced, every + # attack of synthesis §7.5.7's battery is a transform that gives its bytes, parameters + # outside their ranges are refused), then tests/robustness.rs in release, since + # regenerating the corpus runs the harness over the measurement sets of synthesis §7.5.8 + # (every file of live-conformance/robustness/ regenerates byte for byte and no other file + # is there; every case gets what it states; §12 lists exactly the reference's codes and + # the corpus refuses a case for each; §4 registers exactly the reference's transforms; + # the tent64 records' tables are the synthesis corpus's battery.json; the tent64 claim is + # synthesis §7.5.8's list; jwp-receipts §3.1 lists the span reasons); then the second + # implementation, robustness_verify.py with _wai_mark.py, written from the extension's + # text and sharing no code with wai-rs, which reruns the conformance record's battery end + # to end and requires the same table, checks the tent64 records against battery.json and + # the claim against synthesis §7.5.8, mutates copies of the corpus and weakens its own + # verifier in turn; standard library only, run isolated (-I). + - name: robustness evidence · wai-rs and robustness_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features robustness --lib robustness::) + (cd wai-rs && cargo test --release --no-default-features --features robustness --test robustness) + python3 -I live-conformance/robustness_verify.py live-conformance/robustness # wai.ai.usage (extensions/ai-usage.md): the reference module's unit tests (RFC 9651's # Dictionary parser against the vocabulary's examples and the RFC's edges, statements # read and refused in their steps' order, the precedence rule, HTTP fields compared by @@ -1582,6 +1670,78 @@ jobs: (cd wai-rs && cargo test --no-default-features --features co_watch --test co_watch) python3 -I live-conformance/co_watch_verify.py live-conformance/cowatch node --test ../joule-code/joule-code-rs/crates/joule-moq-web/web/room/cowatch.test.mjs + # wai.telemetry.aggregate (extensions/telemetry-aggregation.md): the reference module's unit + # tests (the fields against a wide-arithmetic-free product, the generators' orders, + # TurboSHAKE128 against RFC 9861, HPKE against RFC 9180 A.1.1, the FLP accepting a valid + # measurement and refusing an invalid one, delivery-telemetry's key classes) and + # tests/telemetry_aggregate.rs (vectors.json regenerates byte for byte from its fixed seeds and + # no other file is there, vdaf-22/ is the draft's test vectors as published and wai-rs passes + # every one, every receipt, cell and delivery-only report gets its stated outcome, every + # reason of §11 and every reused code refuses a vector, §11 lists exactly the reference's + # codes, delivery-telemetry §3.4 classes exactly the reference's keys); then the corpus's + # second implementation, telemetry_aggregate_verify.py, written from the extension's text and + # the drafts it cites and sharing no code with wai-rs, which evaluates Prio3 itself and passes + # the draft's vectors, opens every report with its own X25519, HKDF, AES-128-GCM and HPKE, + # re-runs every flow (both aggregators' verification, the aggregation job byte for byte, the + # batch buckets, every refusal, the collection), verifies every receipt and cell with WAI's + # strict Ed25519 rule from claim-conformance, reads the key classes and the reason table from + # the texts, requires every mutated copy of the corpus to fail, and drops each of its own + # checks in turn and requires the corpus to catch the weakened verifier; standard library + # only, run isolated (-I). + - name: QoE aggregation · wai-rs and telemetry_aggregate_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features telemetry_aggregate --lib -- telemetry_aggregate:: telemetry::) + (cd wai-rs && cargo test --no-default-features --features telemetry_aggregate --test telemetry_aggregate) + python3 -I live-conformance/telemetry_aggregate_verify.py live-conformance/aggregate + # wai.media.tonemap, wai.meta.gainmap and wai.meta.st2094_50 (extensions/exact-tonemap.md): + # the reference module's unit tests (the fixed-point log2 and exp2 at known points, the + # table of K against its rule, the sRGB table, tan through its series, PCHIP slopes of a + # line, rounding of halves for both signs) and the PNG reader's, then tests/exact_tonemap.rs + # (the committed corpus regenerates byte for byte, no other file is there, every case and + # envelope gets its stated outcome, §9 lists exactly the reference's codes, §6 states the + # corpus's measurement against binary64, and frames.rgb8 is the int_video clip's decode + # whose digests its sidecar publishes); then the corpus's second implementation, + # tonemap_verify.py, written from the extension's text and sharing no code with wai-rs, + # which computes both derivations in integer arithmetic of its own, reads PNG, envelopes + # (with staged_verify.py) and both companions itself, recomputes §6's measurement, verifies + # every record with WAI's strict Ed25519 rule and BLAKE3 from claim-conformance, requires + # every mutated copy of the corpus to fail, and drops each of its own checks in turn and + # requires the corpus to catch the weakened verifier; standard library only, run isolated + # (-I). + - name: exact tone mapping · wai-rs and tonemap_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features exact_tonemap --lib -- exact_tonemap:: png_still::) + (cd wai-rs && cargo test --no-default-features --features exact_tonemap --test exact_tonemap) + python3 -I live-conformance/tonemap_verify.py live-conformance/tonemap + # wai.splat.exact (extensions/splat-exact.md): the reference module's unit tests + # (exp_neg_q16 against the exponential, binary32 ranges rounded half up exactly, the + # signed integers' grammar, the identity set carrying every byte, and tiles that leave a + # frame unchanged) and tests/splat_exact.rs (live-conformance/splat/ regenerates byte for + # byte and no other file is there, every case gets its stated outcome, §10 lists exactly the + # reference's codes, the tiles leave every view of every scene unchanged, and the draft + # schema names §3.2's members); then the corpus's second implementation, + # splat_exact_verify.py, written from the extension's text and sharing no code with wai-rs: + # it reads each glTF asset, decodes each payload with int_payload_verify.py's parser and + # rANS decoder and tools/wai_ops_check.py's whm1/1 interpreter, renders every view with its + # own integer renderer, verifies every record with WAI's strict Ed25519 rule and BLAKE3 + # from claim-conformance, reads the extension's reason table, requires every mutated copy + # of the corpus to fail, drops each of its own checks in turn and changes each rule of its + # renderer in turn, and requires the corpus to catch every one; standard library only, run + # isolated (-I). + - name: exact splats · wai-rs and splat_exact_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features splat_exact --lib splat_exact::) + (cd wai-rs && cargo test --no-default-features --features splat_exact --test splat_exact) + python3 -I live-conformance/splat_exact_verify.py live-conformance/splat # wai.live.e2ee (extensions/confidentiality.md): the corpus's second implementation, # e2ee_verify.py, written from the extension's text and the documents it reads and # sharing no code with the reference (joule-moq's secure_objects and joule-moq-mls, @@ -1659,6 +1819,30 @@ jobs: # delivered shuffled, withheld and walked back with rewritten links and forks; both # require wai_jwp_vectors and jwp_verify.py to give every chain the same verdict. Two # fixed seeds each, so a run is reproducible. + # Hybrid signatures (extensions/pq-signatures.md): the reference module's unit tests (its + # ML-DSA-65 against FIPS 204's ACVP vectors — keyGen, deterministic sigGen and sigVer — + # vendored in pq-conformance/acvp and pinned by SHA-256, and the composite against the + # draft's own vector, before anything is built on them), the synthesis reader's hybrid + # records, and tests/pq_signatures.rs (vectors.json regenerates byte for byte, every case + # reaches its verdict, §8 lists exactly the reference's codes, each given); then the + # corpus's second implementation, pq_verify.py, written from the extension's text and + # sharing no code with wai-rs, which verifies ML-DSA-65 from FIPS 204's text in pure + # Python (_mldsa.py), checks every ACVP verification vector and signature and the draft's + # vector, every case, the sizes §9 states and §8's table, requires every mutated case to be + # refused and the corpus to catch it with any one of its checks dropped; run isolated (-I). + # Last, the two give every case the same verdict. + - name: hybrid signatures · wai-rs and pq_verify.py + working-directory: wai + shell: bash + run: | + set -euo pipefail + (cd wai-rs && cargo test --no-default-features --features pq_signatures --lib pq_sig::) + (cd wai-rs && cargo test --no-default-features --features synthesis,pq_signatures --lib synthesis::pq_tests) + (cd wai-rs && cargo test --no-default-features --features pq_signatures --test pq_signatures) + python3 -I pq-conformance/pq_verify.py pq-conformance + python3 -I pq-conformance/pq_verify.py verdicts pq-conformance/vectors.json > "$RUNNER_TEMP/pq-py.tsv" + (cd wai-rs && cargo run -q --no-default-features --features pq_signatures --bin wai_pq_vectors -- verdicts ../pq-conformance/vectors.json) > "$RUNNER_TEMP/pq-rs.tsv" + diff "$RUNNER_TEMP/pq-py.tsv" "$RUNNER_TEMP/pq-rs.tsv" - name: claim_verify.py, differential.py, jwp_verify.py, chain_differential.py, chain_gap_differential.py, signer_verify.py working-directory: wai shell: bash diff --git a/.github/workflows/wai-ops-gpu.yml b/.github/workflows/wai-ops-gpu.yml index dfea03d12..44950e816 100644 --- a/.github/workflows/wai-ops-gpu.yml +++ b/.github/workflows/wai-ops-gpu.yml @@ -15,7 +15,8 @@ name: wai-ops-gpu integer operators on GPUs # compiler. WAI_OPS_GPU_EXPECT declares the one adapter the host must offer, and # WAI_OPS_GPU_REQUIRE makes an absent adapter a failure, never a skip; each step # then requires the report lines with their counts, so a filtered or empty run -# fails too. +# fails too. The splat renderer's compositing (extensions/splat-exact.md) runs there +# too: every view of the splat corpus equal to the CPU's frame, and its mutants caught. # - checks (`linux`, a container with no GPU): the crate and its tests build, the # device tests print SKIPPED and pass, and the same tests under # WAI_OPS_GPU_REQUIRE=1 fail: an absent adapter is not a pass. The browser module @@ -48,6 +49,15 @@ on: - 'wai/wai-rs/src/exact_upscale/**' - 'wai/wai-rs/tests/exact_upscale_gpu.rs' - 'wai/live-conformance/upscale/priors/**' + - 'wai/wai-rs/src/dred_exact/**' + - 'wai/wai-rs/tests/dred_exact_gpu.rs' + - 'wai/live-conformance/dred/**' + # The splat renderer's compositing on the device (extensions/splat-exact.md), and the + # scenes it is held to. + - 'wai/wai-rs/src/splat_exact.rs' + - 'wai/wai-rs/src/splat_exact/**' + - 'wai/wai-rs/tests/splat_exact_gpu.rs' + - 'wai/live-conformance/splat/**' - 'wai/wai-rs/tests/vectors/**' - 'wai/int-payload-conformance/**' - 'wai/neural-conformance/**' @@ -130,12 +140,16 @@ jobs: - name: The browser module builds for wasm32-unknown-unknown working-directory: wai/wai-ops-gpu/browser run: cargo build --locked --release --target wasm32-unknown-unknown - - name: wai-rs builds with ops_gpu, and its GPU test target + - name: wai-rs builds with ops_gpu, and its GPU test targets working-directory: wai/wai-rs run: | set -euo pipefail cargo test --locked --no-default-features --features ops_gpu,video_int,audio_int,splat_int,world_int --test ops_gpu --no-run cargo test --locked --no-default-features --features ops_gpu,exact_upscale --test exact_upscale_gpu --no-run + cargo test --locked --no-default-features --features splat_exact,ops_gpu --test splat_exact_gpu --no-run + - name: wai-rs builds the DRED profile's GPU test target + working-directory: wai/wai-rs + run: cargo test --locked --no-default-features --features dred_exact,ops_gpu --test dred_exact_gpu --no-run - name: The bench tool builds working-directory: wai/tools/ops-gpu-bench run: cargo build --locked --release @@ -212,6 +226,42 @@ jobs: grep -q '^test result: ok\. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out' "$log" || { echo "::error::the test did not run and pass"; exit 1; } grep -qE "^exact-upscale gpu: key=gpu-metal-0 .* cases=[1-9][0-9]* .* cpu=0 .* differ=0 errors=0 equal$" "$rep" \ || { echo "::error::no equal run on the GPU"; exit 1; } + # wai.audio.opus.dred.int (extensions/opus-dred.md §4.8): the corpus's payloads and its + # streams' reconstructions decoded with both graphs of dred-int/1 on the GPU at acc64, every graph also run on the + # interpreter and compared, and the decode's integers held to the CPU's. The weights file + # is fetched and checked against the draft's digest (live-conformance/dred/fetch.sh). + - name: The DRED profile, with its graphs on the GPU + shell: bash + run: | + set -euo pipefail + d="$RUNNER_TEMP/dred" + bash wai/live-conformance/dred/fetch.sh "$d" + log="$RUNNER_TEMP/dred-gpu.log" + rep="$RUNNER_TEMP/dred-gpu.report" + : > "$rep" + cd wai/wai-rs + WAI_OPS_GPU_REPORT="$rep" WAI_DRED_WEIGHTS="$d/dred_unquantized_weights.bin" \ + nice -n 10 cargo test --locked --release --no-default-features --features dred_exact,ops_gpu \ + --test dred_exact_gpu -- --nocapture 2>&1 | tee "$log" + grep -q '^test result: ok\. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out' "$log" || { echo "::error::the DRED GPU test did not run and pass"; exit 1; } + grep -qE "^dred-gpu: key=gpu-metal-0 payloads=[1-9][0-9]* streams=[1-9][0-9]* same=true graphs_on_gpu=[1-9][0-9]* .* on_cpu=0 compared=[1-9][0-9]* differed=0 errors=\[\]$" "$rep" \ + || { echo "::error::no equal DRED run on the GPU"; exit 1; } + # wai-splat-render:i1 (extensions/splat-exact.md §5.6-§5.7) with its compositing on the + # GPU: every canonical and own-pose view of every scene of live-conformance/splat/ equal to + # the CPU's frame byte for byte, and each edited kernel caught. + - name: The splat renderer's compositing on the GPU + shell: bash + working-directory: wai/wai-rs + run: | + set -euo pipefail + log="$RUNNER_TEMP/splat-gpu.log" + rep="$RUNNER_TEMP/splat-gpu.report" + : > "$rep" + WAI_OPS_GPU_REPORT="$rep" nice -n 10 cargo test --locked --release --no-default-features --features splat_exact,ops_gpu \ + --test splat_exact_gpu -- --nocapture 2>&1 | tee "$log" + grep -q '^test result: ok\. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out' "$log" || { echo "::error::the splat GPU test did not run and pass"; exit 1; } + grep -qE '^splat-exact gpu: key=gpu-metal-0 views=[1-9][0-9]* differ=0 mutants_survived=0 ' "$rep" \ + || { echo "::error::no equal splat run on gpu-metal-0, or a mutant survived"; exit 1; } - name: wasm-bindgen CLI 0.2.127, and the wasm32-unknown-unknown target shell: bash run: | diff --git a/scripts/check-public-names.sh b/scripts/check-public-names.sh index 34b2e7d8b..2ae91631f 100755 --- a/scripts/check-public-names.sh +++ b/scripts/check-public-names.sh @@ -19,7 +19,8 @@ # Scope: the tracked files under wai/ with the extensions .md .rs .toml .py # .sh .mjs .js .json .html .css .ttl .h .c .txt, and wai/'s .gitignore files; # or, when files are given as arguments, those files (the self-test, -# scripts/test-public-text-checks.sh, uses this). Excluded: +# scripts/test-public-text-checks.sh, uses this), each a path relative to the +# directory the script is run from, or absolute. Excluded: # - the settled OER/2 documents and corpus (wai/extensions/oer-receipts.md, # wai/wai-rs/src/oer.rs, wai/oer-conformance/), which no change may edit. # @@ -32,12 +33,16 @@ # function, not the owner. # # Exit status: 0 clean; 1 a hit; 2 WAI_NAME_DENYLIST unset or empty, a pattern -# grep cannot compile, or any other grep error. The check never reads an error +# grep cannot compile, a file given that is not a readable regular file (each +# such file is named), or any other grep error. The check never reads an error # as "clean". set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# The files given as arguments are paths from the caller's directory: remember it +# before moving to the repository's root, where the default scope is listed. +CALLER_DIR="$(pwd)" cd "$REPO_ROOT" if [ -z "${WAI_NAME_DENYLIST:-}" ]; then @@ -67,7 +72,12 @@ fi files=() if [ $# -gt 0 ]; then - files=("$@") + for f in "$@"; do + case "$f" in + /*) files+=("$f") ;; + *) files+=("$CALLER_DIR/$f") ;; + esac + done else while IFS= read -r f; do case "$f" in @@ -83,6 +93,20 @@ if [ ${#files[@]} -eq 0 ]; then exit 2 fi +# A file grep cannot read makes it exit 2 with the whole list unchecked; name each +# such file instead of reporting a bare grep failure. File names are not private. +unreadable=0 +for f in "${files[@]}"; do + if [ ! -f "$f" ] || [ ! -r "$f" ]; then + echo "::error::not a readable file: $f" >&2 + unreadable=$((unreadable + 1)) + fi +done +if [ $unreadable -gt 0 ]; then + echo "::error::$unreadable of ${#files[@]} files given cannot be read; nothing was checked" >&2 + exit 2 +fi + set +e grep -HnE -f "$patterns" -- "${files[@]}" > "$out" 2>/dev/null rc=$? diff --git a/scripts/test-public-text-checks.sh b/scripts/test-public-text-checks.sh index 85aa775c8..a2c8b0bea 100755 --- a/scripts/test-public-text-checks.sh +++ b/scripts/test-public-text-checks.sh @@ -23,6 +23,18 @@ tmp="$(mktemp -d)" trap 'rm -rf "$tmp"' EXIT failures=0 +in_dir() { # in_dir : run a command from another directory + local d="$1" + shift + (cd "$d" && "$@") +} +names_file() { # names_file : the command exits 2 and its output names + local f="$1" + shift + "$@" >"$tmp/named" 2>&1 + local got=$? + [ "$got" -eq 2 ] && grep -qF "$f" "$tmp/named" +} expect() { # expect