Skip to content

cintegration: mock daemon lifts coverage past FFI-bound ceiling#3

Merged
TeoSlayer merged 1 commit into
mainfrom
mock-daemon-harness
May 28, 2026
Merged

cintegration: mock daemon lifts coverage past FFI-bound ceiling#3
TeoSlayer merged 1 commit into
mainfrom
mock-daemon-harness

Conversation

@TeoSlayer
Copy link
Copy Markdown
Contributor

Summary

  • New standalone mock daemon binary (cintegration/mockdaemon/) speaks the bare IPC wire protocol so the C harness can drive every Pilot* endpoint that requires a connected handle.
  • C harness forks the mock into a temp Unix socket, runs 41 new tests against it, then SIGTERMs on exit. 70 tests total (29 pre-existing + 41 new), all passing on darwin/arm64.
  • Per-statement coverage rises 20.8% to 66.3%. Per-function coverage of bindings.go now sits between 71-100% for nearly every Pilot* export.

Protocol notes

The IPC layer is simpler than expected: length-prefixed frames ([uint32-be-len][cmd-byte][payload]), no hello/handshake, no Ed25519 negotiation. Identity is daemon-to-daemon, not on the local socket. The mock supports:

  0x01 Bind        -> 0x02 BindOK     [port(2)]
  0x03 Dial        -> 0x04 DialOK     [connID(4)]
  0x06 Send        -> echoed via 0x07 Recv push
  0x08 Close       -> 0x09 CloseOK push -> driver's Read sees io.EOF
  0x0D Info        -> 0x0E InfoOK     [JSON]
  0x0F Handshake   -> 0x10 HandshakeOK [JSON]  (sub-cmds dispatched)
  ... etc through 0x29 Broadcast

Reverse-engineered from web4/internal/ipcutil, web4/pkg/driver/ipc.go, web4/pkg/daemon/ipc.go. Reply payload shapes (e.g. CmdBindOK = [port(2)], CmdDialOK = [connID(4)]) match the daemon handlers in pkg/daemon/ipc.go.

What is NOT touched

  • bindings.go, embedded.go, coverflush.go — production code untouched per task constraints.
  • Mock lives entirely under cintegration/mockdaemon/ with its own go.mod, no effect on the libpilot module graph.

Endpoints still uncovered

  • PilotRecvFrom — needs spontaneous CmdRecvFrom server push. Can be added by spawning a goroutine on the mock side that pushes a canned datagram on a timer.
  • PilotListenerAccept — would block indefinitely without a peer dialling into the listener; out of mock scope (would need a second client driving inbound dials).
  • PilotDialTimeout success branch — mock replies instantly; the timeout path is exercised by the existing dial_timeout_huge invalid-handle test.
  • main — cgo entry, never reachable in any harness.

Test plan

  • cd cintegration && make clean && make cover on darwin/arm64 -> 70/70 pass, total 66.3%
  • go test ./... on libpilot module still green
  • CI on Linux (will run on PR open)

The previous iteration drove libpilot's //export surface from C, but
every endpoint requiring a connected handle (PilotInfo, PilotHealth,
PilotDial, PilotListen, the entire Network*/Managed*/Policy* surface,
trust handshake variants, conn read/write) was blocked at the
loadHandle()/driverFromHandle() gate. Coverage capped at 20.8%.

Adds a standalone mock daemon binary (cintegration/mockdaemon/main.go)
that speaks the bare IPC wire protocol — length-prefixed frames with
a single command byte, no JSON RPC, no handshake. It services every
request type with canned replies sufficient for libpilot to round-trip
a real handle:

  - 0x01 Bind        -> 0x02 BindOK     [port(2)]
  - 0x03 Dial        -> 0x04 DialOK     [connID(4)]
  - 0x06 Send        -> echoed back via 0x07 Recv push
  - 0x08 Close       -> server-pushed 0x09 CloseOK so reads see EOF
  - 0x0D Info        -> 0x0E InfoOK     [JSON]
  - 0x0F Handshake   -> 0x10 HandshakeOK [JSON]  (sub-cmds dispatched)
  - 0x11 Resolve     -> 0x12 ResolveOK  [JSON]
  - 0x13 SetHostname -> 0x14 SetHostnameOK [JSON]
  - 0x15 SetVisibility .. 0x29 Broadcast
                     -> matching XxxOK code with JSON or empty payload

The C harness forks the mock binary into a temp Unix socket, polls
until the socket appears (capped at 2s), then runs 41 new tests
covering every handle-bound endpoint plus a write/echo/read round
trip over a dialled Conn. Mock is SIGTERMed at end.

Result: 70 tests (29 pre-existing + 41 mock-driven), all passing on
darwin/arm64. Per-statement coverage climbs from 20.8% to 66.3%.
Per-function coverage of bindings.go now shows nearly every PilotXxx
between 71% and 100%; only PilotRecvFrom (needs spontaneous CmdRecvFrom
push), PilotListenerAccept (would block indefinitely without a peer
dialling in), and PilotDialTimeout's success branch (mock doesn't
inject delay) remain partially covered. main() is cgo-only and not
test-reachable in any harness.

Protocol details I reverse-engineered vs. canned:
- Wire frame format from internal/ipcutil/ipcutil.go (length-prefixed)
- Cmd constants from pkg/driver/ipc.go (canonical numbering)
- Reply payload shapes from pkg/daemon/ipc.go handlers (handleBind,
  handleDial, handleInfo, sendError)
- Driver demux behaviour from pkg/driver/ipc.go readLoop: known
  XxxOK cmds route to a single in-flight pending channel; CmdRecv /
  CmdCloseOK / CmdAccept are server-pushed and routed by ID
- No IPC-layer Ed25519 handshake; identity is daemon-to-daemon only.
  A fresh Unix-socket connection sends frames immediately.

What is NOT modified: bindings.go, embedded.go, coverflush.go.
Mock daemon lives entirely under cintegration/mockdaemon/ with its
own go.mod so it never affects the libpilot module graph.
@TeoSlayer TeoSlayer merged commit ab30d48 into main May 28, 2026
1 check passed
@TeoSlayer TeoSlayer deleted the mock-daemon-harness branch May 28, 2026 00:54
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

2 participants