Skip to content

test(annotate): raise ui.annotate coverage and fix depth-state equals recursion - #426

Merged
tstapler merged 5 commits into
mainfrom
backlog/stelekit-annotate-ui-test-coverage
Oct 15, 2026
Merged

tstapler merged 5 commits into
mainfrom
backlog/stelekit-annotate-ui-test-coverage

Conversation

@tstapler

Copy link
Copy Markdown
Owner

Summary

ui.annotate was 46.4% line / 27.3% branch covered (backlog item 6bc196d3). This adds tests for the ViewModel branches, DepthEstimationCoordinator, and the zero-covered BLE/permission/calibration UI via Robolectric, and fixes two bugs the tests exposed.

What Changed

  • Bug fix: DepthCoordinatorState.equals recursed infinitely (a private FloatArray?.contentEquals shadowed the stdlib overload and called itself → StackOverflowError).
  • Bug fix: BleDevicePanel Cancel did not cancel the in-flight mock connection, so the panel flipped to Connected after Cancel.
  • formatMeters is now internal for direct unit testing.
  • commonTest: AnnotationEditorViewModelBranchTest, DepthEstimationCoordinatorTest, ParseGridRefLengthTest, FormatMetersTest.
  • androidUnitTest (Robolectric): CalibrationNudgeBannerTest, PermissionRationaleDialogTest, CalibrationSheetTest, BleDevicePanelTest, SmallAnnotateDialogsTest, AnnotateEditorPartsTest, AnnotationEditorScreenRobolectricTest.
  • project_plans/annotate-ui-test-coverage/: requirements, research, plan, validation, and coverage-results.md + union_coverage.py.

Coverage (JaCoCo, ui.annotate)

Covered / Total %
JVM report 1334 / 2649 50.4
Android report 1970 / 2631 74.9
Line-level union 2202 / 2657 82.9

VM branch 168/198 = 84.8%; DepthEstimationCoordinator branch 27/28 = 96.4%. JaCoCo cannot merge the JVM and Android reports, so the union is computed by union_coverage.py.

Test plan

  • ./gradlew :kmp:jvmTest --tests 'dev.stapler.stelekit.*annotate*' :kmp:jacocoTestReport
  • ./gradlew :kmp:testDebugUnitTest --tests 'dev.stapler.stelekit.*annotate*' :kmp:jacocoAndroidTestReport (needs ANDROID_HOME)
  • python3 -I project_plans/annotate-ui-test-coverage/union_coverage.py
  • 264 annotate tests, 0 failures; no display required
  • Remote CI
  • Not done: Bazel wiring of the new commonTest files; injectable device source for BleDevicePanel.

…tate UI

Fix DepthCoordinatorState.equals infinite recursion (private FloatArray?.contentEquals
shadowed the stdlib overload and called itself). Promote formatMeters to internal for tests.
@tstapler

Copy link
Copy Markdown
Owner Author

Tracked by Stapler Squad backlog item: ssq://onyx.staplerhome.internal/backlog/v1/bl_01M4WBVQVMNJR6SRQP1YPW12P6
Host: host_01M0H2V3S43XCN5MGPZ4Z5Y3JX

@github-actions

Copy link
Copy Markdown
Contributor

JVM Load Benchmark (Desktop)

Synthetic in-memory benchmark measuring load performance for the desktop (JVM) app.
Comparing ea20703a (this PR) vs a53809c3 (baseline)
Graph config: xlarge — 230 pages

Metric This PR Baseline Delta
Phase 1 TTI ↓ 0ms 0ms 0 (0%)
Phase 2 background ↓ 0ms 0ms 0 (0%)
Phase 3 index ↓ 1ms 1ms 0 (0%)
Total ↓ 1ms 1ms 0 (0%)
Write p95 (baseline) ↓ 32ms 33ms -1ms (-3%) ✅
Write p95 (under load) ↓ n/a n/a
Jank factor ↓ n/a n/a
↓ lower is better
Flamegraphs (this PR) **Allocation** — object allocation pressure (JDBC/SQLite churn)

Alloc flamegraph not available

CPU — method-level hotspots by on-CPU time

CPU flamegraph not available

Top allocation hotspots (this PR) `33%` byte[]_[k] `6.7%` java.lang.String_[k] `5.8%` int[]_[k] `4.4%` java.util.LinkedHashMap$Entry_[k] `4.2%` java.lang.Object[]_[k]
Top CPU hotspots (this PR) `96%` /usr/lib/x86_64-linux-gnu/libc.so.6 `1.3%` /tmp/sqlite-3.51.3.0-6ce1d010-b960-43dd-b972-39e011abd9c8-libsqlitejdbc.so `0.3%` __libc_pwrite `0.3%` fsync `0.3%` SR_handler

@github-actions

Copy link
Copy Markdown
Contributor

Android Load Benchmark

Instrumented benchmark on an API 30 x86_64 emulator — 500-page synthetic graph.

Comparing ea20703a (this PR) vs 8afdd032 (baseline)
Device: API 30 x86_64 emulator — 530 pages loaded

Graph Load

Metric This PR Baseline Delta
Phase 1 TTI ↓ 36ms 53ms -17ms (-32%) ✅
Phase 3 index ↓ 4687ms 4586ms +101ms (+2%) ⚠️

Interactive Write Latency (during Phase 3)

Metric This PR Baseline Delta
Write p95 (baseline) ↓ 13ms 8ms +5ms (+63%) ⚠️
Write p95 (during phase 3) ↓ 10ms 17ms -7ms (-41%) ✅
Jank factor ↓ 0.77x 2.13x -1.36x (-64%) ✅
Concurrent writes ↑ 23 23 0 (0%)

SAF I/O Overhead (ContentProvider vs direct File read)

Measures Binder IPC cost added by ContentResolver per readFile() call.
Real SAF via ExternalStorageProvider will be higher on device; this is a lower bound.

Metric This PR Baseline Delta
Direct read / file ↓ 0.0ms 0.0ms 0ms (-100%) ✅
Provider read / file ↓ 0.2ms 0.2ms +0ms (+35%) ⚠️
IPC overhead ratio ↓ 7x 5x +2x (+40%) ⚠️
↓ lower is better · ↑ higher is better

@tstapler
tstapler marked this pull request as ready for review October 15, 2026 00:31
@tstapler
tstapler merged commit 2581c01 into main Oct 15, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant