Stage containers sharing the eureka-sccache volume died mid-build with cargo's "could not execute process ... sccache ... (never executed)" or a missing dep-info file in their own target dir, though the image's sccache is present, executes, and a lone container builds clean. The wrapper only caches, so a failed build with RUSTC_WRAPPER set is retried once without it; the job summary carries a NOTE line saying which way it went, the first attempt's log is kept, and a build dead either way stays a red baseline (exit 4) with its cause. Container errors now tail 25 lines, not 5. Tests: dead wrapper recovers with NOTE; red with and without the wrapper stays red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
75 lines
4.7 KiB
Shell
Executable file
75 lines
4.7 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
# Fake cargo for tools/test-tools.sh, only what tools/cargo-mutants.sh calls:
|
|
# cargo locate-project --workspace --message-format plain
|
|
# cargo test --no-run
|
|
# cargo test -- <filter> [<harness args>] --list (prints "<n> tests, 0 benchmarks" per test binary)
|
|
# cargo mutants [--list] --in-diff <diff> [-f <file>] [-F <re>]... [--shard k/n] [-o <dir>] [...] [-- <filter> [-- <harness args>]]
|
|
# FAKE_CM_TABLE: tab-separated <mutant name> <outcome under a filtered run> <outcome under the full suite>
|
|
# (caught|missed|timeout|unviable). A run with -F is the full suite; a run with -f and a filter is filtered.
|
|
# FAKE_CM_TESTS: tab-separated <filter> <tests the filter selects> (default 1)
|
|
# FAKE_CM_RED=1|2: the stage-1 or stage-2 run fails its baseline (exit 4, no output).
|
|
# FAKE_CM_KILLS: a path a run creates (the watchdog's YGG_KILLED flag appearing mid-job).
|
|
# FAKE_CM_LOG: appended one line per run (stage, filter, harness args, open fds from 10 up).
|
|
# FAKE_WSROOT: the workspace root relative to the repository root, with a trailing slash ('' = the repository root).
|
|
case ${1:-} in
|
|
locate-project) echo "$(git rev-parse --show-toplevel)/${FAKE_WSROOT:-}Cargo.toml"; exit 0 ;;
|
|
test)
|
|
shift; for a; do [ "$a" != --no-run ] || exit 0; done
|
|
[ "${1:-}" = -- ] || { echo "fake cargo test: unsupported arguments" >&2; exit 64; }
|
|
shift; f=$1; shift; h=()
|
|
for a; do [ "$a" = --list ] || h+=("$a"); done
|
|
echo "count filter=$f harness=${h[*]}" >>"${FAKE_CM_LOG:?}"
|
|
n=$(awk -F'\t' -v f="$f" '$1 == f { print $2 }' "${FAKE_CM_TESTS:-/dev/null}")
|
|
printf '%s tests, 0 benchmarks\n0 tests, 0 benchmarks\n' "${n:-1}"; exit 0 ;;
|
|
mutants) shift ;;
|
|
*) echo "fake cargo: unsupported ${1:-}" >&2; exit 127 ;;
|
|
esac
|
|
list=0; mult=''; mintimeout=''; diff=''; ffile=''; res=(); shard=''; out=''; tail=()
|
|
while [ $# -gt 0 ]; do
|
|
case $1 in
|
|
--list) list=1 ;;
|
|
--in-diff) diff=$2; shift ;;
|
|
-f) ffile=$2; shift ;;
|
|
-F) res+=("$2"); shift ;;
|
|
--shard) shard=$2; shift ;;
|
|
-o) out=$2; shift ;;
|
|
--jobs) shift ;;
|
|
--minimum-test-timeout) mintimeout=$2; shift ;;
|
|
--timeout-multiplier) mult=$2; shift ;;
|
|
--) shift; tail=("$@"); break ;;
|
|
*) echo "fake cargo mutants: unknown argument $1" >&2; exit 64 ;;
|
|
esac
|
|
shift
|
|
done
|
|
[ -n "$diff" ] && [ -f "$diff" ] || { echo "fake cargo mutants: no readable --in-diff" >&2; exit 64; }
|
|
# the mutants of the files the diff touches (paths as the diff prints them: relative to the workspace root)
|
|
touched=$(sed -n 's|^+++ b/||p' "$diff")
|
|
sel=$(awk -F'\t' 'NR == FNR { t[$0] = 1; next } { f = $1; sub(/:.*/, "", f); if (f in t) print $1 "\t" $2 "\t" $3 }' <(printf '%s\n' "$touched") "${FAKE_CM_TABLE:?}")
|
|
if [ -n "$ffile" ]; then sel=$(awk -F'\t' -v f="$ffile" '{ n = $1; sub(/:.*/, "", n); if (n == f) print }' <<<"$sel"); fi
|
|
if [ "${#res[@]}" -gt 0 ]; then
|
|
keep=$(cut -f1 <<<"$sel" | perl -e '@r = map { qr/$_/ } @ARGV; while (<STDIN>) { chomp; for $r (@r) { if (/$r/) { print "$_\n"; last } } }' "${res[@]}")
|
|
sel=$(awk -F'\t' 'NR == FNR { k[$0] = 1; next } $1 in k' <(printf '%s\n' "$keep") <(printf '%s\n' "$sel"))
|
|
fi
|
|
if [ -n "$shard" ]; then
|
|
sel=$(awk -F'\t' -v k="${shard%/*}" -v n="${shard#*/}" '(NR - 1) % n == k' <<<"$sel")
|
|
fi
|
|
if [ "$list" = 1 ]; then cut -f1 <<<"$sel" | awk 'NF'; exit 0; fi
|
|
stage=1; [ "${#res[@]}" -eq 0 ] || stage=2
|
|
filter=''; harness=()
|
|
if [ "${#tail[@]}" -gt 0 ] && [ "${tail[0]}" != -- ]; then filter=${tail[0]}; fi
|
|
for i in "${!tail[@]}"; do if [ "${tail[$i]}" = -- ]; then harness=("${tail[@]:$((i + 1))}"); break; fi; done
|
|
open=$(perl -MPOSIX -e '$n = 0; for (10 .. 40) { my $d = POSIX::dup($_); if (defined $d) { $n++; POSIX::close($d) } } print $n')
|
|
[ -z "${FAKE_CM_KILLS:-}" ] || touch "$FAKE_CM_KILLS" # a watchdog kill arriving while a run is going
|
|
echo "stage=$stage filter=$filter harness=${harness[*]} openfds=$open mult=$mult min=$mintimeout" >>"${FAKE_CM_LOG:?}"
|
|
[ "${FAKE_CM_RED:-}" != "$stage" ] || { echo "baseline failed" >&2; exit 4; }
|
|
# FAKE_CM_DEADWRAP=1: a run whose environment still holds RUSTC_WRAPPER dies like cargo with a wrapper that cannot execute.
|
|
[ -z "${FAKE_CM_DEADWRAP:-}" ] || [ -z "${RUSTC_WRAPPER:-}" ] || { echo " Caused by: could not execute process $RUSTC_WRAPPER rustc (never executed)"; exit 101; }
|
|
mkdir -p "$out/mutants.out/log"
|
|
col=3; [ "$stage" = 2 ] || col=2
|
|
for o in caught missed timeout unviable; do
|
|
awk -F'\t' -v c="$col" -v o="$o" '{ x = $c; if (x == o) print $1 }' <<<"$sel" >"$out/mutants.out/$o.txt"
|
|
done
|
|
# a run that selected no mutant (the awk above printed empty lines): drop them
|
|
for o in caught missed timeout unviable; do sed -i '/^$/d' "$out/mutants.out/$o.txt"; done
|
|
if [ -s "$out/mutants.out/timeout.txt" ]; then exit 3; elif [ -s "$out/mutants.out/missed.txt" ]; then exit 2; fi
|
|
exit 0
|