You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
test: fault-fixture coverage gaps for defensive mechanisms #43
A whole-repo mechanism audit (every recovery/rollback/idempotency guard traced to its origin commit and test) confirmed all defensive mechanisms are justified, but eight lack a test that exercises their exact failure branch. Each needs a fault fixture; none is urgent — adjacent tests cover the surrounding flow.
sandboxd
pool/claim.go — Release in-memory rollback on failed persist: no direct test for the persist-fail arm (hibernate/archive equivalents have one via breakStore).
pool/egress.go — disarmIfReleased: the wake-races-Release window has no test naming this path.
pool/egress.go — armEgressProxy stale-socket removal before bind: no test with a leftover UDS from a prior life.
egress/intercept.go — leafFor near-expiry renewal is not directly asserted (the 1024-entry eviction is, by TestInterceptLeafCacheBounded).
silkd
session.rs — Table::create duplicate-id rejection under real concurrency (two racing creates, loser's shell must not leak).
exec.rs — Started-frame write-failure rollback (needs a broken-pipe writer fixture; the ghost-entry outcome is otherwise untestable).
proc.rs — Table::remove_if pointer-identity guard: pid-reuse eviction has no isolated test (requires a forged pid collision).
vsock.rs / net_egress.rs — accept-error retry loop: no EMFILE-style transient-error fixture; a failure here would take down the whole daemon.
Suggested fixtures: breakStore-style fault injection for the pool items, a half-closed pipe writer for silkd exec, fd-budget exhaustion via setrlimit in a child for the accept loops.
One more accept loop of the last class, host-side this time: egress.Proxy.ServeSOCKS in sandboxd/egress/socks.go (#164). #168 made it back off 50 ms and continue on a transient accept error instead of returning (the pool discarded the return, so an EMFILE ended the SOCKS5 door for the claim's life while the HTTP door kept serving). Its test covers the listener-closed exit only; the fd-budget fixture named above applies to it too.
Checked against main (72cc514). Two items now have their fault fixture:
pool/claim.go Release rollback on failed persist: covered by TestReleaseArchivedRollsBackOnPersistFailure (sandboxd/pool/archive_test.go). That test exercises the archived arm; the plain-release arm shares the same rollback block.
egress/intercept.go 1024-entry eviction: covered by TestInterceptLeafCacheBounded (sandboxd/egress/intercept_test.go). The near-expiry renewal half of that bullet is still untested.
The remaining items are still open: disarmIfReleased, stale-socket removal in armEgressProxy, leafFor renewal, and the four silkd items.
Activity
CMGS commentedon Sep 14, 2026
One more accept loop of the last class, host-side this time:
egress.Proxy.ServeSOCKSinsandboxd/egress/socks.go(#164). #168 made it back off 50 ms and continue on a transient accept error instead of returning (the pool discarded the return, so an EMFILE ended the SOCKS5 door for the claim's life while the HTTP door kept serving). Its test covers the listener-closed exit only; the fd-budget fixture named above applies to it too.CMGS commentedon Sep 29, 2026
Checked against
main(72cc514). Two items now have their fault fixture:pool/claim.goRelease rollback on failed persist: covered byTestReleaseArchivedRollsBackOnPersistFailure(sandboxd/pool/archive_test.go). That test exercises the archived arm; the plain-release arm shares the same rollback block.egress/intercept.go1024-entry eviction: covered byTestInterceptLeafCacheBounded(sandboxd/egress/intercept_test.go). The near-expiry renewal half of that bullet is still untested.The remaining items are still open:
disarmIfReleased, stale-socket removal inarmEgressProxy,leafForrenewal, and the four silkd items.