nigig-org/crates/apps/doc/doc-ui/COVERAGE.md
andodeki 1d8b3a6053
Some checks failed
makepad-table / model (push) Has been cancelled
makepad-table / widget (push) Has been cancelled
makepad-table / hygiene (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
repo hygiene / hygiene (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
merge(local): reapply local WIP onto merged main -- cad dashboard/explode/script_parts/xray merged with remote Phase-5 LOD, plus doc-ui extraction, spreadsheet xls-import, android ussd, camera and test work
2026-09-01 21:13:52 +03:00

4.7 KiB
Raw Permalink Blame History

Doc-workspace source coverage

tools/test-doc-workspace-coverage.sh measures line/region coverage for the pure (widget-free) part of this module and enforces floors in CI (.forgejo/workflows/nigig-build.yml, job doc-workspace-coverage). The same suite also runs uninstrumented inside cargo test -p nigig-build --lib, so every test executes twice: once in the real crate and once in the harness.

How it works

The script copies the dependency-free sources — advanced_json.rs, crdt_bridge.rs, mobile_gesture.rs, persistence.rs, projection_layout.rs, projection_session.rs, and the collaboration/, editing/, layout/, model/, plugins/ trees — plus tests_pure.rs byte-for-byte into a temporary host-only crate with the real module path. A 30 line makepad-widgets shim (re-exporting makepad_math plus the log! / error! macros) satisfies the only Makepad symbols the pure layer uses (DVec2, Rect, Vec4f, dvec2, vec4). doc-engine is included as a path dependency because the pure projection code sits on top of it.

The harness then installs its own pinned toolchain with llvm-tools-preview into the same temp dir, runs the suite under -C instrument-coverage, and enforces:

  • a total line floor (DOC_WS_COVERAGE_TOTAL_FLOOR), and
  • a per-file floor for every instrumented source (DOC_WS_COVERAGE_PER_FILE_FLOORS).

The per-file floors are the point: deleting one file's whole test section moves the total by a point or two and a lone number would wave that through. Lowering a floor is a reviewable edit to the script, not something to do quietly. Everything — toolchain, cargo home, target dir, fetched Makepad tree, profraw data — is removed by a shell trap on every exit path; nothing is written into the repository or $HOME unless KEEP_COVERAGE=1 is set.

Running it

./tools/test-doc-workspace-coverage.sh                    # gated run (CI)
DOC_WS_COVERAGE_REPORT_ONLY=1 ./tools/test-doc-workspace-coverage.sh   # measure only
KEEP_COVERAGE=1 ./tools/test-doc-workspace-coverage.sh   # keep uncovered-lines.txt + report

Latest measurement (2026-08-17)

File Lines covered
TOTAL 96.76% (6170 lines)
advanced_json.rs 98.02%
crdt_bridge.rs 95.45%
mobile_gesture.rs 100%
persistence.rs 65.85% (see exclusions)
projection_layout.rs 98.52%
projection_session.rs 100%
collaboration/* 100%
editing/commands.rs 93.39%
editing/controller.rs 93.39%
editing/history.rs 95.65%
layout/* 94100%
model/* 91100%
plugins/mod.rs 100%

What is intentionally not measured

  • The widget layermod.rs, crdt_widget.rs, widgets/, render/, projection_renderer.rs, tests.rs. These need live_design!, a Cx, and an event loop; they are gated by the full nigig-build build/test CI jobs instead. The split is deliberate: tests_pure.rs contains everything that can run host-only, and both files are compiled into the crate's normal test suite.
  • persistence.rs write pathssave_doc_state / save_doc_state_as / load_saved_doc_state resolve the host's real application-data directory and unconditionally write into it. They are thin wrappers over save_doc_state_to / load_saved_doc_state_with, which the tests drive with explicit temp paths; the wrappers themselves are covered by the widget-runtime tests on device. This is why persistence.rs keeps a lower floor (55%) — do not lower it further without a genuine new exclusion.
  • Defensive guards — cycle guards in RGA/block-order traversal (seen.insert continue arms), unreachable block-id parse failures inside layout_projection (engine ids always contain actor:counter), and the unreachable canvas-text serialization arm's sibling rejections in advanced_json.rs. They exist for invariant defense; there is no honest public-API path that reaches them.

Defects found by this coverage drive (fixed with tests)

  1. editing/commands.rs::ReplaceBlockRange validated the explicit block_ids length after draining blocks out of the document, so a malformed command destroyed content before reporting failure. Validation now happens before any mutation; a test pins that a rejected replace leaves blocks and ids untouched.
  2. model/crdt.rs::visit_children was dead code (a String-collecting duplicate of visit_atoms with no callers). Removed.
  3. Multi-peer atom-id collisions: two CrdtMetadata::default() peers mint identical AtomIds, so a concurrent insert silently resurrects instead of inserting. The sync test now assigns distinct document.crdt.local_actors — matching how real peers must be provisioned — and pins the convergent "hi!" exchange.