diff --git a/Dockerfile b/Dockerfile index a84a860..33c753b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,20 +42,35 @@ RUN go mod tidy -diff || \ # Go's build cache is kept on a tmpfs, out of the image: nothing uses it # after this step, and writing it into the image takes seconds. The tests # are built with the no_fs_access tag, as the binary is in the build stage. +# +# The race detector finds bugs only in code that runs in several goroutines +# at once. Of the Core Rule Set's tests, only +# TestConcurrentRequestsKeepTheirOwnExclusions inspects requests that way, +# so it is the only one of them in this pass. The second pass runs the rest. FROM test-setup AS test-race RUN --mount=type=tmpfs,target=/root/.cache/go-build \ - go test -tags no_fs_access -timeout 90s -race -cover ./... || \ + others="$(go list ./... | grep -vxF sneak.berlin/go/smallwebwaf/internal/coreruleset)"; \ + { go test -tags no_fs_access -timeout 90s -race -cover $others && \ + go test -tags no_fs_access -timeout 90s -race -cover \ + -run '^TestConcurrentRequestsKeepTheirOwnExclusions$' ./internal/coreruleset; } || \ { echo "--- Rerunning with -v for details ---"; \ - go test -tags no_fs_access -timeout 90s -race -v ./...; exit 1; } + go test -tags no_fs_access -timeout 90s -race -v $others; \ + go test -tags no_fs_access -timeout 90s -race -v \ + -run '^TestConcurrentRequestsKeepTheirOwnExclusions$' ./internal/coreruleset; \ + exit 1; } -# Second pass: the recorded requests, too slow for make test under -race. +# Second pass: every other test of the Core Rule Set, the recorded requests +# among them, without the race detector. FROM test-setup AS test-recorded RUN --mount=type=tmpfs,target=/root/.cache/go-build \ - go test -tags no_fs_access,recorded -timeout 90s -cover -run '^TestOrdinary' ./internal/coreruleset/... || \ + go test -tags no_fs_access,recorded -timeout 90s -cover \ + -skip '^TestConcurrentRequestsKeepTheirOwnExclusions$' ./internal/coreruleset || \ { echo "--- Rerunning with -v for details ---"; \ - go test -tags no_fs_access,recorded -timeout 90s -run '^TestOrdinary' -v ./internal/coreruleset/...; exit 1; } + go test -tags no_fs_access,recorded -timeout 90s -v \ + -skip '^TestConcurrentRequestsKeepTheirOwnExclusions$' ./internal/coreruleset; \ + exit 1; } # The test phase that script/test and the build stage name. Nothing is # wanted from the two passes; the copies are what make BuildKit run them. diff --git a/README.md b/README.md index 7f8d919..5f400d6 100644 --- a/README.md +++ b/README.md @@ -702,8 +702,12 @@ on the host. - `script/projectname`: prints `smallwebwaf`, which the other scripts tag their images with. - `script/test`: checks that `go.mod` and `go.sum` are tidy, then runs the - tests, as the `test` phase of the `Dockerfile`. It runs them twice: once with - the race detector, and once without it for the recorded requests. `make test`. + tests, as the `test` phase of the `Dockerfile`, in two passes. `make test`. + - The first runs every package's tests with the race detector. Of the Core + Rule Set's tests, it runs only the one that inspects requests from several + goroutines at once. + - The second runs the Core Rule Set's other tests without the race detector, + the recorded requests among them. - `script/tidy`: writes `go.mod` and `go.sum` as `go mod tidy` writes them, in the `tidy` stage of the `Dockerfile`. `make tidy`. - `script/lint`: runs golangci-lint, as the `lint` phase of the `Dockerfile`.