ADR-0004 — Hermetic default test lane, engine fidelity lane
- Status: Accepted + landed (2026-06-22, commit
ffc21f2c9). Updated after the raft engine moved to an externalrqlitedprocess (see the last consequence below). - Enforced by:
scripts/arch-fitness.shcheckno-cgo-sqlite(hard-zero).
Context
Section titled “Context”make test/unit ran against a real node of the old embedded-raft engine
(libdqlite) under CGO, so a contributor could not run the suite without the
libdqlite/autotools toolchain. A pure-Go sqlite parity backend already existed
(testsupport/dbtestreg/register_sqlite.go) but was
never wired to a make target — the default lane stayed cgo-coupled for no reason.
Decision
Section titled “Decision”Two lanes:
make test/unit(default, hermetic):CGO_ENABLED=0, no engine build tag, noconfigureprereq. The modernc.org/sqlite parity backend rejects DML+RETURNING exactly as the raft engine does. Runs with a barego/make, no native toolchain.- Fidelity lane: the original embedded-engine + CGO lane, exercising the three real-raft/driver-specific tests the hermetic lane skips.
The one CGO test (migrate_squash_test.go, the only mattn/go-sqlite3 importer)
was swapped to pure-Go modernc.org/sqlite (driver "sqlite").
CI should run both lanes (hermetic everywhere for speed; the fidelity lane on a runner that has the engine available) so the fidelity tests keep coverage.
Consequences
Section titled “Consequences”go test ./...-style hermetic runs work without cgo.- Paths stay enumerated (
./cmd/... ./... ./pkg/... ./tests/unit/...), never./..., to dodge the dh-golangobj-*/GOPATH tree. - Reintroducing
mattn/go-sqlite3fails the build. - Post-rqlited update: the raft engine is now an external
rqlitedprocess (core/rqlited), so the CGO build split — and with it the fidelity lane as a separate build — is gone. Engine-fidelity coverage now comes from the live-engine tests (rqlited process, cluster join, engine flip), which skip unless arqlitedbinary is resolvable (SHC_RQLITED_BIN, ormake vendor/rqliteon Linux). The hermetic default lane and the parity backend’s DML+RETURNING rejection survive unchanged: rqlite’s/db/executereturns results, not rows, so the constraint still holds on the cluster engine.
shc@docs:~$