#!/bin/sh # script/test: run the test suite. Quiet on success; on failure, rerun # verbosely for full diagnostic output (the exit 1 ensures the rerun # never turns a failure into a pass). set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" # The flags live in one function so the quiet run and the verbose rerun # below cannot drift apart. A rerun that used different flags would # diagnose a different program than the one that failed. # # -count=1 is the documented way to bypass Go's test result cache, and # it is not optional here. Without it, a package whose inputs are # unchanged prints `ok (cached)`, and that line is # indistinguishable -- to every check this repo performs -- from a # package that actually ran. The whole suite reports its full set of # `ok` lines in under half a second having executed nothing. That # matters beyond the local inner loop: the Dockerfile's `RUN make test` # is forced to re-execute by CHECK_EPOCH, but a GOCACHE baked into an # earlier image layer survives into the re-executed step, so the step # can re-run and still do no work. It is applied unconditionally rather # than only in the containerised path because the pre-commit hook runs # this same script; a gate that is honest only in CI is dishonest # exactly where people lean on it most. # # -timeout is a hang backstop, not a performance budget: its job is to # turn a deadlocked test into a stack dump instead of a wedged CI job, # so it wants to sit far above the slowest legitimate runtime, not just # above it. It is per test binary and covers test execution only -- the # clock starts inside testing.M.Run, after compilation and linking, so # build time is not charged against it. (Measured: a containerised run # with an empty GOCACHE reports per-package durations within noise of a # warm host run. A shell `timeout 30 go test ./...` would include # compilation, but that is a different mechanism from this flag.) # # The 120s value DELIBERATELY DIVERGES from REPO_POLICIES.md:192, which # mandates "Add a 30-second timeout", and from that file's canonical Go # recipe at :212-214, which uses -timeout 30s. REPO_POLICIES.md is # org-canonical and cannot be amended from this repo, so the divergence # is recorded here instead, and issue #101 proposes amending the policy # text upstream. Do not revert this to 30s without reading #101 first. # # Why it diverges: the slowest packages are internal/database and # internal/vaultik, observed under -race at about 6.4s warm, 8.1s in a # cold containerised run on a contended host, and 10.2s in an # independent cold run on this same host. The worst case is not tightly # characterised -- each fresh measurement has come in above the last -- # which is itself an argument for generous headroom. Against the 10.2s # observation, 30s is only 2.9x: not a safety margin but a flake # waiting for a slow day, whose failure mode is a timeout that looks # like a real defect. 120s leaves about 12x while still bounding a hung # package -- including the verbose rerun below -- to a few minutes. The # cost of that choice, also recorded on #101: because of the rerun, a # hung package pays the timeout twice. run_tests() { go test -race -timeout 120s -count=1 "$@" ./... } main() { cd "$ROOT" run_tests || { echo "--- Rerunning with -v for details ---" run_tests -v exit 1 } } main "$@"