Host-side unit tests for fields.c and page.c (#68, partial) #82
No reviewers
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/PedalPebble!82
Loading…
Reference in a new issue
No description provided.
Delete branch "tooling/host-test-harness"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this is
Partial progress on #68 ("Host-side unit tests for the watchapp logic"), scoped down to what
currently exists in
watchapp/src/c/after #58/PR #81 (fields.c/fields.h, page.c/page.h). Severalof #68's own acceptance criteria depend on issues that haven't landed yet — see "Deferred" below.
This PR does not close #68; a comment on the issue lists exactly what's covered vs. still blocked.
Layout
watchapp/tests/CMakeLists.txt— host build, two CTest binaries (test_fields,test_page)watchapp/tests/harness.h— dependency-free assertion harness (~90 lines). No C test framework,per the issue's own instruction. Analogue for a C#/xUnit or Jest background:
TH_ASSERT_*macrosplay the role
Assert.*/expect()play, plus aTH_RUN/TH_REPORTrunner convention.watchapp/tests/stubs/pebble.h+pebble_stub.c— a fake in-memorypersist_*backing.Note on path: I used
watchapp/tests/(plural), notwatchapp/test/as #68's own "Files"section names it.
.forgejo/workflows/fast-lane.yml'shost-c-testsjob checks specifically forwatchapp/tests/CMakeLists.txt(plural) as its skip guard, and getting that job to activate is thehighest-value part of this issue — so I matched the workflow rather than the issue text. Confirmed:
that guard now finds this CMakeLists.txt and the job will build+run it once a runner is registered
(no runner is registered yet per tonight's other PRs, so this hasn't executed for real in CI, only
verified locally — see below).
page.c: stubbed, not split
page.c mixes pure logic with two
persist_*calls (page_store_load/page_store_save). Issue #68and PR #81 both flag this as a decision point: stub the SDK calls, or split the file. I stubbed
(
tests/stubs/pebble.hsupplies just thepersist_exists/get_size/read_data/write_datasurfacepage.c touches, backed by an in-memory fake). page.c compiles completely unmodified this way —
it's not aware it's being tested — which seemed simpler to keep in sync than maintaining a second
persistence-free copy of the file. This also made
page_store_load/save's fallback-to-defaultsbehaviour testable for free, so I included it as bonus coverage even though it wasn't explicitly
asked for tonight.
Covered (44 assertions, 2 binaries)
--, zero-is-not-absentfor any of them
FieldId(22 of them) formats correctly and renders--when unavailable — metric only. fields.c as merged has no imperial unit support (that's #44,
still open); I did not fabricate imperial formatting to satisfy #68's "metric and imperial"
bullet — noted as blocked below instead.
threshold, recovers on a fresh touch, stays false while a field is unavailable (not merely
untouched), stays false before the group has ever been touched, ignores a backwards clock, and a
constant value under changed-keys-only updates stays fresh as long as its group keeps ticking.
out-of-range template id, rejects an unknown field id in any of the 6 slots, rejects an all-0xFF
malformed blob. (
page_descriptor_unpack's signature is a fixeduint8_t[PAGE_DESCRIPTOR_WIRE_SIZE]— there's no length to get "wrong" at this API, so theissue's "wrong slot counts" phrase doesn't apply until whatever decodes a variable-length
CONFIG_PAGES payload into this fixed array exists (#61); noted in a code comment, not tested.)
page_has_live_field(including that it counts a merely-stale field as live, not just anavailable one) and
page_default_descriptor.Deliberately deferred — not built or faked here
#60, not yet built
Verification
No
cmakein this sandbox, so I couldn't run the CTest path directly. I built and ran both testbinaries by hand with the same sources/flags the CMakeLists.txt declares:
Both compile clean under
-Wall -Wextra -Werrorand both pass clean (28 + 16 = 44 assertions, 0failures, exit 0). I then deliberately broke one assertion's expected value and reran: it failed
loudly with a
file:linemessage and a nonzero exit code, confirming the harness doesn't silentlyswallow a failure.
watchapp/wscript'spbl_buildonly globssrc/c/**/*.c, sowatchapp/tests/doesn't affect thereal
pebble build/pebble-buildCI job.Since no runner is registered yet (per tonight's other PRs),
host-c-testshasn't actually executedin CI for this PR — only the skip-guard logic and local build were verified.
https://claude.ai/code/session_01DAoXbRmJUf2uxNYBfdAXPt