#!/bin/sh
# race.sh — the race detector over the packages whose invariants only a
# data race can break (make race).
#
# On a branch, only the packages the branch changed run. The CI runner
# sets QUARRY_CHANGED to a file listing the paths the branch changed
# since its fork point; a package runs when one of those paths is in it
# (its own files, or a subdirectory that is not a package of its own),
# and every package runs when a path is a build input. With no list —
# trunk, a local run, a lookup that failed — every package runs, so a
# race a branch reaches only through a dependency is still caught on
# trunk.
#
# The cheap packages repeat; internal/web and internal/index take over
# a minute a pass, so they run COUNT times, once by default.
set -eu
COUNT=${COUNT:-1}
list=${QUARRY_CHANGED:-}
if [ -n "$list" ] && [ ! -r "$list" ]; then
echo "race: QUARRY_CHANGED names $list, which cannot be read; running every package" >&2
list=
fi
if [ -n "$list" ] && grep -qxE 'go\.(mod|sum)|Makefile|scripts/(race|ci-zit|build-linux)\.sh' "$list"; then
echo "race: the branch changed a build input; running every package" >&2
list=
fi
# changed PKG: did the branch change PKG? (sh has no locals, so these
# names are its own: pick's loop variable must survive the call.)
changed() {
[ -z "$list" ] && return 0
while IFS= read -r changed_path; do
d=$(dirname "$changed_path")
while [ "$d" != . ] && [ "$d" != "$1" ]; do
# A directory between the path and PKG with Go files of its
# own is another package.
if ls "$d"/*.go >/dev/null 2>&1; then
break
fi
d=$(dirname "$d")
done
[ "$d" = "$1" ] && return 0
done <"$list"
return 1
}
# pick PKG...: the packages of these the branch changed, as ./PKG/.
pick() {
out=
for pkg in "$@"; do
if changed "$pkg"; then out="$out ./$pkg/"; fi
done
echo "$out"
}
ran=
pkgs=$(pick internal/children internal/xfer)
if [ -n "$pkgs" ]; then
go test -race -count=3 $pkgs
ran="$ran$pkgs"
fi
if [ -n "$(pick cmd/quarry)" ]; then
go test -race -count=3 -run '^(TestTheForgeStopsInOrder|TestAnAPIStreamEndsWhenTheForgeStops|TestTeardownWaitsForHandlersThatIgnoredTheStop|TestAStopWaitsForALiveZitChildAndLogsIt|TestAQuietStopStillRefusesNewChildren|TestTheDrainBoundIsKept)$' ./cmd/quarry/
ran="$ran ./cmd/quarry/"
fi
pkgs=$(pick internal/web internal/index)
if [ -n "$pkgs" ]; then
go test -race -count="$COUNT" -timeout 20m $pkgs
ran="$ran$pkgs"
fi
if [ -z "$ran" ]; then
echo "race: the branch changed none of the raced packages; trunk runs them all"
fi