Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ jobs:
export CHROMEDRIVER="${CHROMEWEBDRIVER:+$CHROMEWEBDRIVER/chromedriver}"
mise run wasm-agent-cov

# The pic-viewer display path only runs in a browser, so it is invisible to the cargo-llvm-cov run.
# Its native parse tests already ride that run; this drives the module's wasm-bindgen display tests in
# the same headless Chrome as the ws-wasm-agent step above and folds their lcov into lcov.info.
- name: Merge pic-viewer coverage into lcov.info
timeout-minutes: 20
run: |
export CHROMEDRIVER="${CHROMEWEBDRIVER:+$CHROMEWEBDRIVER/chromedriver}"
mise run pic-viewer-cov

- name: Collect Python coverage
timeout-minutes: 15
env:
Expand Down
79 changes: 79 additions & 0 deletions .mise/config.coverage.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
# The wasm coverage builds need it: minicov's build.rs hardcodes bare `clang` to compile its C profiler runtime
# for the guest target, so this wasm-capable clang must be first on PATH (the wasm build tasks prepend it). LLVM
# 22 here matches rustc's LLVM, keeping the covmap format aligned with the llvm-tools llc/llvm-cov used downstream.
#
# Known-broken on macOS: mise resolves the [env] _.path prepend below to a PATH position BEHIND /usr/bin, so
# under `mise run` bare `clang` still hits Apple's and minicov's C compile fails with "unable to create target:
# No available targets are compatible with triple wasm32-unknown-unknown". The wasm coverage tasks
# (wasm-agent-cov, pic-viewer-cov) therefore only work locally on Linux until that ordering is fixed; on a Mac,
# run the task body manually in a shell with the conda-clang bin dir genuinely first on PATH. CI (ubuntu) is
# unaffected because the distro clang already has the wasm backend.
#
# Windows is deliberately out of scope for this env (hence the os scoping here): coverage collection runs only
# on the ubuntu CI lane, and there is no intention to make the wasm coverage pipeline work on Windows.
[tools]
"conda:clang" = { version = "latest", os = ["linux", "macos"] }

Expand Down Expand Up @@ -279,3 +289,72 @@ rpt="$covdir/report.txt"
rg "ws-wasm-agent/src/lib.rs|Filename|TOTAL" "$rpt" || true
"""
shell = "bash -euo pipefail -c"

[tasks.pic-viewer-cov]
depends = ["build-wasm-cov-wrapper"]
description = "Coverage for pic-viewer: run its wasm-bindgen display tests headless, emit lcov into lcov.info"
# Coverage for the module's browser-only display path; its native parse tests already ride cargo-llvm-cov.
# show_image's fetch/decode/canvas-draw only runs in a real browser, so this drives the wasm-bindgen browser
# tests (tests/show_image.rs) in headless Chrome, instrumented the same way as wasm-agent-cov -- the
# workspace wrapper's -Cinstrument-coverage + --emit=llvm-ir, wasm-bindgen-test's built-in coverage cfg, and
# et-web/coverage for minicov's profiler runtime -- then converts the .profraw the same way (gut every
# workspace .ll body to `unreachable`, keep the covmap, llc to a fixed x86_64 ELF object, llvm-cov to lcov,
# keep only this module's records). No backend is needed: the display tests are offline.
run = """
covdir=target/pic-viewer-cov
coreutils mkdir -p "$covdir"
coreutils rm -f "$covdir"/*.profraw "$covdir"/*.o "$covdir"/*.g.ll
# Force a recompile so this run emits a fresh instrumented .ll whose covmap matches the captured .profraw.
rustup target add wasm32-unknown-unknown
cargo clean -p et-ws-pic-viewer --target wasm32-unknown-unknown

# Resolve the webdriver, honouring a CHROMEDRIVER already in the environment before the mise-pinned one.
driver="${CHROMEDRIVER:-$(mise which chromedriver)}"

runner="$(mise which wasm-bindgen-test-runner)"
export RUSTC_WORKSPACE_WRAPPER="{{ config_root }}/target/debug/int-wasm-cov-wrapper"
export RUSTFLAGS="--cfg wasm_bindgen_unstable_test_coverage"
export CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER="$runner"
export CHROMEDRIVER="$driver"
export LLVM_PROFILE_FILE="{{ config_root }}/$covdir/pic-viewer-%p.profraw"
cargo test -p et-ws-pic-viewer --features et-web/coverage --target wasm32-unknown-unknown --test show_image

host="$(rustc +nightly -vV | goawk '/^host:/ { print $2 }')"
llbin="$(rustc +nightly --print sysroot)/lib/rustlib/$host/bin"
gut="$covdir/gut.awk"
coreutils cat > "$gut" <<'AWK'
/^target datalayout/ { next }
/^target triple/ { next }
/^define/ { print; print "start:"; print " unreachable"; print "}"; skip = 1; next }
skip && /^}/ { skip = 0; next }
skip { next }
{
gsub(/"target-cpu"="[^"]*"/, "")
gsub(/"target-features"="[^"]*"/, "")
if ($0 ~ /^attributes #/ && $0 ~ /\\{[[:space:]]*\\}/) sub(/\\{[[:space:]]*\\}/, "{ nounwind }")
print
}
AWK
"$llbin/llvm-profdata" merge -sparse -o "$covdir/pic-viewer.profdata" "$covdir"/pic-viewer-*.profraw
objs=()
for ll in target/wasm32-unknown-unknown/debug/deps/*.ll; do
name="$(coreutils basename "$ll" .ll)"
goawk -f "$gut" "$ll" > "$covdir/$name.g.ll"
"$llbin/llc" -filetype=obj -mtriple=x86_64-unknown-linux-gnu -o "$covdir/$name.o" "$covdir/$name.g.ll"
objs+=("-object" "$covdir/$name.o")
done
"$llbin/llvm-cov" export --format=lcov --instr-profile "$covdir/pic-viewer.profdata" "${objs[@]}" > "$covdir/all.lcov"
keep="$covdir/keep.awk"
coreutils cat > "$keep" <<'AWK'
{ buf = buf $0 ORS }
/^SF:/ { keep = index($0, want) > 0 }
/^end_of_record$/ { if (keep) printf "%s", buf; buf = ""; keep = 0 }
AWK
coreutils touch lcov.info
goawk -v want="ws-modules/pic-viewer/src/" -f "$keep" "$covdir/all.lcov" >> lcov.info

rpt="$covdir/report.txt"
"$llbin/llvm-cov" report --instr-profile "$covdir/pic-viewer.profdata" "${objs[@]}" > "$rpt" 2>/dev/null || true
rg "ws-modules/pic-viewer/src/lib.rs|Filename|TOTAL" "$rpt" || true
"""
shell = "bash -euo pipefail -c"
6 changes: 6 additions & 0 deletions .mise/config.rust.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ description = "Build the comm1 workflow WASM module"
dir = "services/ws-modules/comm1"
run = "{{ vars.web_cov_wrapper }}wasm-pack build . --target web {{ vars.no_opt }}{{ vars.web_cov_feat }}"

[tasks.build-ws-pic-viewer-module]
depends = ["build-wasm-cov-wrapper"]
description = "Build the pic-viewer broadcast picture viewer WASM module"
dir = "services/ws-modules/pic-viewer"
run = "{{ vars.web_cov_wrapper }}wasm-pack build . --target web {{ vars.no_opt }}{{ vars.web_cov_feat }}"

[tasks.build-ws-except1-module]
depends = ["build-wasm-cov-wrapper"]
description = "Build the except1 exception-handling demo WASM module"
Expand Down
10 changes: 10 additions & 0 deletions .mise/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,16 @@ description = "Run headless Chrome tests for the WebSocket WASM client"
dir = "services/ws-wasm-agent"
run = "env CHROMEDRIVER=\"$(mise which chromedriver)\" wasm-pack test --headless --chrome"

[tasks.test-pic-viewer-firefox]
description = "Run headless Firefox tests for the pic-viewer module (image display onto the canvas)"
dir = "services/ws-modules/pic-viewer"
run = "wasm-pack test --headless --firefox"

[tasks.test-pic-viewer-chrome]
description = "Run headless Chrome tests for the pic-viewer module (image display onto the canvas)"
dir = "services/ws-modules/pic-viewer"
run = "env CHROMEDRIVER=\"$(mise which chromedriver)\" wasm-pack test --headless --chrome"

[tasks.ws-e2e-chrome]
depends = ["test-ws-wasm-agent-chrome", "ws-server"]
description = "Run both the ws-server and ws-wasm-agent using Chrome"
Expand Down
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ members = [
"services/ws-modules/graphics-info",
"services/ws-modules/har1",
"services/ws-modules/nfc",
"services/ws-modules/pic-viewer",
"services/ws-modules/sensor1",
"services/ws-modules/speech-recognition",
"services/ws-modules/video1",
Expand Down
5 changes: 5 additions & 0 deletions config/ast-grep/rules/doc-summary-ends-with-period.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ files:
- services/websockify/src/lib.rs
- services/websockify/tests/relay.rs
- services/ws-modules/except1/src/lib.rs
- services/ws-modules/pic-viewer/build.rs
- services/ws-modules/pic-viewer/src/lib.rs
- services/ws-modules/pic-viewer/tests/parse.rs
- services/ws-modules/pic-viewer/tests/show_image.rs
- services/ws-pyo3-runner/tests/modules.rs
- services/ws-server/src/config.rs
- services/ws-server/src/lib.rs
Expand All @@ -51,6 +55,7 @@ files:
- services/ws-wasi-runner/tests/modules.rs
- services/ws-wasi-runner/tests/otel_propagation.rs
- services/ws-wasi-runner/tests/vector_otlp_relay.rs
- services/ws-wasm-agent/src/lib.rs
- services/ws-web-runner/build.rs
- services/ws-web-runner/tests/modules.rs
- services/ws/tests/config.rs
Expand Down
47 changes: 47 additions & 0 deletions services/ws-modules/pic-viewer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
description = "Picture viewer"
name = "et-ws-pic-viewer"
version = "0.1.0"
edition.workspace = true
license.workspace = true
repository.workspace = true

[lib]
crate-type = ["cdylib", "rlib"]
doctest = false
test = false

[dependencies]
edge-toolkit.workspace = true
et-web.workspace = true
et-ws-wasm-agent.workspace = true
js-sys.workspace = true
serde_json.workspace = true
tracing.workspace = true
tracing-wasm.workspace = true
wasm-bindgen.workspace = true
wasm-bindgen-futures.workspace = true
web-sys = { workspace = true, features = [
"CanvasRenderingContext2d",
"Document",
"Element",
"HtmlCanvasElement",
"HtmlElement",
"HtmlImageElement",
"Window",
"console",
] }

[dev-dependencies]
wasm-bindgen-test.workspace = true
# Extra web-sys surface used only by the browser tests; cargo unions it with the [dependencies] features.
# Blob backs the object-URL serving the embedded test image, ImageData the drawn-pixel readback.
web-sys = { workspace = true, features = ["Blob", "ImageData", "Url"] }

[build-dependencies]
# Stages the favicon test fixture into OUT_DIR (see build.rs).
et-path.workspace = true
fs-err.workspace = true

[lints]
workspace = true
20 changes: 20 additions & 0 deletions services/ws-modules/pic-viewer/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//! Stage the browser tests' image fixture (the ws-server page favicon) into `OUT_DIR`.
//!
//! The `show_image` browser tests embed a real PNG via `include_bytes!`, and the repo's
//! `no-relative-path-literal` rule (rightly) forbids reaching it through a `../..` literal. Copying it here,
//! anchored on `et_path::find_project_root_from_manifest()`, keeps the checked-in favicon as the single
//! source of truth while giving the macro a stable `OUT_DIR` path to include.

use std::path::PathBuf;

#[expect(
clippy::unwrap_used,
reason = "build script: failing the build loudly is exactly right when the fixture can't stage"
)]
fn main() {
let favicon = et_path::find_project_root_from_manifest().join("services/ws-server/static/favicon.png");
println!("cargo:rerun-if-changed={}", favicon.display());

let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
let _bytes_copied = fs_err::copy(&favicon, out_dir.join("favicon.png")).unwrap();
}
Loading
Loading