nigig-org/tools/test-cad-widget-coverage.sh
andodeki 0596fc66ed
Some checks failed
email.yml / test(cad): measure the widget layer — 13.15%, and six files at zero (push) Failing after 0s
repo hygiene / hygiene (push) Has been cancelled
test(cad): measure the widget layer — 13.15%, and six files at zero
The number nobody had. The engine harness is structurally blind to
viewport*.rs, workspace*.rs and friends, so "97.14% covered" has always
been a statement about the smaller half. With the Makepad Linux packages
installed, the real crate builds and its tests run under
-C instrument-coverage, which makes the other half measurable in about
six minutes.

10,714 lines. 13.15% covered. 9,305 never executed by any test.

  viewport_input.rs      736 lines    0.00%
  viewport_render.rs   2,083 lines    0.00%
  workspace_actions.rs   690 lines    0.00%
  cad_editor_sheet.rs    224 lines    0.00%
  viewport_2d.rs         138 lines    0.00%
  code_editor.rs          67 lines    0.00%
  viewport.rs          3,548 lines   14.37%
  workspace.rs         2,462 lines   14.18%
  script_bindings.rs     724 lines   71.27%

viewport_input.rs is every click, drag, modifier and keystroke the
editor handles, and not one line of it has ever run in a test.
viewport_render.rs is every draw call.

This reframes the six sessions of engine work above it. 1044 green tests
and a 97% engine coexist with an input layer nothing has touched. Those
facts were never in tension — they were just never on the same page,
because the tool that produced the good number could not see the bad
one. A coverage figure that excludes the risky half is not a summary,
it is an average with the interesting term deleted.

The new script reports the widget files ONLY, on purpose. Folding them
into one number would let a 97% engine hide a 0% input layer, which is
the arithmetic this exists to prevent.

No floors yet, deliberately: a floor at 13% reads as a blessing rather
than a debt. The first real input test should set one behind it.

Verified: two runs, cold and warm, same numbers; script cleans its
profraw data on exit and refuses with a useful message when the native
packages or llvm-tools are missing.
2026-08-17 11:59:06 +00:00

138 lines
5.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Source coverage for the CAD *widget* layer — the half
# tools/test-cad-coverage.sh cannot see.
#
# WHY THIS EXISTS
#
# The host-only harness measures the fourteen pure engine files by
# copying them into a crate with no Makepad in it. That is fast, needs no
# root, and is what the CI gate uses — but it is structurally blind to
# viewport*.rs, workspace*.rs, mod.rs, script_bindings.rs,
# cad_editor_sheet.rs and code_editor.rs, which are the files that handle
# every click, drag, keystroke and draw call in the editor.
#
# Those were called unmeasurable for a long time, including by the
# tooling's own documentation. They are not. They need the Makepad Linux
# packages — not a desktop, not a GPU, not a display server. With those
# installed, `cargo test -p nigig-build --lib` builds and runs, and it
# runs just as happily under -C instrument-coverage.
#
# The first run of this script reported 13.15% of lines over those ten
# files, with viewport_input.rs, viewport_render.rs, workspace_actions.rs,
# viewport_2d.rs, cad_editor_sheet.rs and code_editor.rs at exactly zero.
#
# COST
#
# ~6 minutes single-job from cold, most of it compiling the Makepad graph
# with instrumentation. Unlike the engine harness this needs apt packages
# and therefore root, which is why it is a separate script and not a flag
# on the other one.
#
# USAGE
#
# bash tools/makepad-native-libs.sh --check # what is missing
# bash tools/makepad-native-libs.sh --install # opt-in, apt-based
# ./tools/test-cad-widget-coverage.sh
#
# CAD_WIDGET_KEEP=1 ./tools/test-cad-widget-coverage.sh # keep profraw
# + line report
#
# Deliberately NOT gated with floors yet. A floor at 13% reads as a
# blessing; the number is here to be driven up, and the first person to
# add a real input test should set one behind them.
set -Eeuo pipefail
IFS=$'\n\t'
ROOT="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
CAD_REL="crates/apps/nigig-build/src/construction_frame/pages/workspace/cad"
TOOLCHAIN="$(sed -n 's/^channel = "\(.*\)"/\1/p' "$ROOT/rust-toolchain.toml")"
HOST_TRIPLE="${CAD_WIDGET_HOST:-x86_64-unknown-linux-gnu}"
WORK="$(mktemp -d "${TMPDIR:-/tmp}/cad-widget-coverage.XXXXXXXX")"
KEEP="${CAD_WIDGET_KEEP:-0}"
cleanup() {
local status=$?
if [[ "$KEEP" == "1" ]]; then
echo "kept: $WORK" >&2
else
rm -rf "$WORK"
echo "cleaned temporary coverage data" >&2
fi
exit "$status"
}
trap cleanup EXIT HUP INT TERM
# The build cache is reused by default: a cold instrumented build of the
# Makepad graph is minutes, and throwing it away every run would make
# this unusable in a loop. Point it somewhere else, or at $WORK, to get
# a hermetic run.
export CARGO_TARGET_DIR="${CAD_WIDGET_TARGET_DIR:-$WORK/target}"
export LLVM_PROFILE_FILE="$WORK/profiles/%p-%m.profraw"
export RUSTFLAGS="-C instrument-coverage"
export CARGO_NET_GIT_FETCH_WITH_CLI=true
export CARGO_BUILD_JOBS="${CAD_WIDGET_JOBS:-1}"
mkdir -p "$WORK/profiles"
if ! command -v cargo >/dev/null 2>&1; then
echo "ERROR: cargo is not on PATH." >&2
echo " Unlike tools/test-cad-coverage.sh this script does not install a" >&2
echo " toolchain: it builds the real crate, so it uses yours." >&2
exit 1
fi
if ! pkg-config --exists wayland-client x11 alsa 2>/dev/null; then
echo "ERROR: the Makepad Linux packages are missing." >&2
echo " bash tools/makepad-native-libs.sh --check" >&2
echo " bash tools/makepad-native-libs.sh --install" >&2
exit 1
fi
cd "$ROOT"
cargo test --locked -p nigig-build --lib
LLVM_BIN="$(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/bin"
if [[ ! -x "$LLVM_BIN/llvm-profdata" ]]; then
echo "ERROR: llvm-tools-preview is missing from the active toolchain." >&2
echo " rustup component add llvm-tools-preview --toolchain $TOOLCHAIN" >&2
exit 1
fi
"$LLVM_BIN/llvm-profdata" merge -sparse "$WORK/profiles"/*.profraw \
-o "$WORK/widget.profdata"
BIN="$(find "$CARGO_TARGET_DIR/debug/deps" -maxdepth 1 -type f -executable \
-name 'nigig_build-*' ! -name '*.d' -printf '%T@ %p\n' \
| sort -rn | head -1 | cut -d' ' -f2-)"
[[ -n "$BIN" ]] || { echo "no instrumented test binary found"; exit 1; }
# The widget files only. The engine files have their own report with
# floors; mixing them here would let a 97% engine hide a 0% input layer,
# which is exactly the arithmetic this script exists to prevent.
WIDGET_FILES=(
mod.rs
viewport.rs
viewport_input.rs
viewport_render.rs
viewport_2d.rs
workspace.rs
workspace_actions.rs
script_bindings.rs
cad_editor_sheet.rs
code_editor.rs
)
SOURCES=()
for f in "${WIDGET_FILES[@]}"; do
SOURCES+=("$ROOT/$CAD_REL/$f")
done
echo
echo "=== CAD widget layer — the half the engine harness cannot see"
echo
"$LLVM_BIN/llvm-cov" report "$BIN" -instr-profile="$WORK/widget.profdata" \
"${SOURCES[@]}" | sed "s|$ROOT/$CAD_REL/||"
if [[ "$KEEP" == "1" ]]; then
"$LLVM_BIN/llvm-cov" show "$BIN" -instr-profile="$WORK/widget.profdata" \
"${SOURCES[@]}" | grep -E '^ *[0-9]+\| *0\|' > "$WORK/uncovered-lines.txt" || true
echo "uncovered line report: $WORK/uncovered-lines.txt" >&2
fi