Run the tests under the race detector with make test-race (closes #18)
check / check (push) Failing after 2s
check / check (push) Failing after 2s
script/test-race runs go test -race in a digest-pinned Debian golang image that has gcc, since the detector needs cgo and the build keeps it off. The checkout is mounted read-only, the tests run as nobody so the tests that make a file unreadable still see the read fail, and the container is removed afterwards. It is not part of make check. The detector found no races. Model: opus-5-5
This commit is contained in:
@@ -6,7 +6,7 @@ BINARY := sfdupes
|
||||
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
|
||||
LDFLAGS := -X main.Version=$(VERSION)
|
||||
|
||||
.PHONY: sfdupes build bootstrap setup test lint fmt fmt-check check docker hooks clean
|
||||
.PHONY: sfdupes build bootstrap setup test test-race lint fmt fmt-check check docker hooks clean
|
||||
|
||||
# Standard targets are thin shims; the implementations live in script/
|
||||
# per the scripts-to-rule-them-all pattern.
|
||||
@@ -27,6 +27,9 @@ setup:
|
||||
test:
|
||||
@script/test
|
||||
|
||||
test-race:
|
||||
@script/test-race
|
||||
|
||||
lint:
|
||||
@script/lint
|
||||
|
||||
|
||||
@@ -827,6 +827,15 @@ and may be invoked directly. The provided entrypoints are:
|
||||
- `script/test` — run the test suite with a 30-second timeout and
|
||||
coverage enabled, rerunning verbosely on failure so the logs show
|
||||
which test failed.
|
||||
- `script/test-race` — run the test suite under the race detector
|
||||
with a 60-second timeout. The detector needs cgo and a C compiler,
|
||||
which the build never uses, so the tests run in a digest-pinned
|
||||
Debian `golang` image that has `gcc`, with the checkout mounted
|
||||
read-only; the container is removed when it exits. They run as
|
||||
`nobody`, because several tests make a file unreadable and root
|
||||
reads it anyway. Not part of `script/check`. Every run starts with
|
||||
empty caches, so it needs the network and takes minutes, and the
|
||||
mount needs a local docker daemon.
|
||||
- `script/lint` — run the linter. It builds `Dockerfile.lint`, which
|
||||
copies the repository into the digest-pinned
|
||||
`golangci/golangci-lint` image and runs
|
||||
@@ -914,6 +923,9 @@ carries the compile recipe:
|
||||
pre-commit hook.
|
||||
- `make test` — run the test suite (30-second timeout; reruns with
|
||||
`-v` on failure).
|
||||
- `make test-race` — run the test suite under the race detector, in
|
||||
Docker (see `script/test-race`); requires `docker`. Not part of
|
||||
`make check`.
|
||||
- `make lint` — run `golangci-lint` with the repo config, in Docker
|
||||
(see `script/lint`); requires `docker`.
|
||||
- `make fmt` / `make fmt-check` — format Go sources / verify
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- `make test-race` runs the test suite under the race detector in a
|
||||
cgo-enabled container, outside `make check` (2026-10-04,
|
||||
https://git.eeqj.de/sneak/sfdupes/issues/18)
|
||||
|
||||
- tests cover a missing database, `scan` keeping stdout empty, its skip
|
||||
warning, the `report` and `trees` summary lines, and every subcommand
|
||||
going through `runE` (2026-10-04, https://git.eeqj.de/sneak/sfdupes/issues/16)
|
||||
@@ -538,5 +542,7 @@ Accepted divergences (no action):
|
||||
- flat single-package layout with `.go` files in the repo root — fine
|
||||
for a small single-binary tool per the Go styleguide; the tracker
|
||||
audit agrees
|
||||
- `go test` runs without `-race` — the repo mandates `CGO_ENABLED=0`
|
||||
(pure-Go builds) and the race detector requires cgo
|
||||
- `make test` runs without `-race` — the repo mandates `CGO_ENABLED=0`
|
||||
(pure-Go builds) and the race detector requires cgo, so the detector
|
||||
runs in a separate cgo-enabled container, `make test-race`, which is
|
||||
not part of `make check`
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
# script/test-race: run the test suite under the race detector. Not part
|
||||
# of script/check.
|
||||
#
|
||||
# The race detector needs cgo and a C compiler, which the host build
|
||||
# never uses, so the tests run in a golang image that has gcc. The
|
||||
# checkout is mounted read-only, so the docker daemon must be local. The
|
||||
# container starts with empty caches every time: each run downloads the
|
||||
# dependencies and compiles them with the detector, which needs the
|
||||
# network and takes minutes.
|
||||
#
|
||||
# The tests run as nobody, not root: several of them make a file
|
||||
# unreadable and expect reading it to fail, and root reads it anyway.
|
||||
# nobody has no home directory, so HOME is /tmp, where Go puts its build
|
||||
# cache.
|
||||
set -eu
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
|
||||
# golang:1.25-trixie, 2026-10-04. Debian rather than the Alpine image the
|
||||
# Dockerfile builds with, because this one includes gcc.
|
||||
IMAGE="golang@sha256:2c4c60ef415fbfa5e90300722293bef36c5e63fae17570ce18f580af933dbd73"
|
||||
|
||||
main() {
|
||||
docker run --rm \
|
||||
--user 65534:65534 \
|
||||
--env HOME=/tmp \
|
||||
--env CGO_ENABLED=1 \
|
||||
--volume "$ROOT:/src:ro" \
|
||||
--workdir /src \
|
||||
"$IMAGE" \
|
||||
go test -race -timeout 60s ./...
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user