| 1 | #!/bin/sh |
| 2 | # Rewrites .amadan/test-weights.tsv, the measured weights .amadan/test-gate.sh |
| 3 | # deals the split packages' tests by. |
| 4 | # |
| 5 | # go test -count=1 -json ./internal/console/ >console.json |
| 6 | # go test -count=1 -json . >root.json |
| 7 | # .amadan/test-weights.sh console.json root.json |
| 8 | # |
| 9 | # Measure on a quiet machine with the temp root on tmpfs, as CI has it, or |
| 10 | # the fsync-heavy tests weigh several times what they do there. |
| 11 | # |
| 12 | # Only the packages in the given files are rewritten; rows for other |
| 13 | # packages are kept. A top-level test of a quarter-second or more gets a |
| 14 | # row. A test that called t.Parallel (its JSON has a "pause") overlaps |
| 15 | # with its neighbours, so its weight is its time divided by 8, roughly |
| 16 | # what it adds to its shard's wall clock. Everything unlisted is dealt as |
| 17 | # short (test-gate.sh counts it as 0.05 s), which is what it is: host's |
| 18 | # 2,500 small serial tests average about 0.025 s. |
| 19 | set -eu |
| 20 | |
| 21 | [ $# -gt 0 ] || { |
| 22 | echo "usage: .amadan/test-weights.sh go-test-json-file..." >&2 |
| 23 | exit 2 |
| 24 | } |
| 25 | |
| 26 | out=.amadan/test-weights.tsv |
| 27 | tab=$(printf '\t') |
| 28 | new=$(mktemp "${TMPDIR:-/tmp}/test-weights-XXXXXX") |
| 29 | trap 'rm -f "$new" "$out.tmp"' EXIT |
| 30 | cat "$@" | awk ' |
| 31 | /"Test":"/ { |
| 32 | if (!match($0, /"Test":"[^"]*"/)) next |
| 33 | test = substr($0, RSTART + 8, RLENGTH - 9) |
| 34 | if (index(test, "/")) next |
| 35 | if (!match($0, /"Package":"[^"]*"/)) next |
| 36 | pkg = substr($0, RSTART + 11, RLENGTH - 12) |
| 37 | key = pkg "\t" test |
| 38 | if ($0 ~ /"Action":"pause"/) { parallel[key] = 1; next } |
| 39 | if ($0 !~ /"Action":"(pass|fail)"/) next |
| 40 | if (!match($0, /"Elapsed":[0-9.]+/)) next |
| 41 | secs[key] = substr($0, RSTART + 10, RLENGTH - 10) + 0 |
| 42 | } |
| 43 | END { |
| 44 | for (k in secs) { |
| 45 | w = (k in parallel) ? secs[k] / 8 : secs[k] |
| 46 | if (w >= 0.25) printf "%s\t%.2f\n", k, w |
| 47 | } |
| 48 | # A package line with no weighted test still marks its rows as replaced. |
| 49 | for (k in secs) { split(k, f, "\t"); seen[f[1]] = 1 } |
| 50 | for (p in seen) printf "#pkg\t%s\n", p |
| 51 | } |
| 52 | ' >"$new" |
| 53 | { |
| 54 | printf '# package\ttest\tseconds (.amadan/test-weights.sh, %s)\n' "$(date -u +%Y-%m-%d)" |
| 55 | { |
| 56 | grep -v '^#pkg' "$new" |
| 57 | if [ -f "$out" ]; then |
| 58 | awk -F "$tab" -v newf="$new" ' |
| 59 | BEGIN { while ((getline l < newf) > 0) { split(l, f, "\t"); if (f[1] == "#pkg") replaced[f[2]] = 1 } } |
| 60 | /^#/ { next } |
| 61 | !($1 in replaced) |
| 62 | ' "$out" |
| 63 | fi |
| 64 | } | sort -t "$tab" -k1,1 -k3,3gr |
| 65 | } >"$out.tmp" |
| 66 | mv "$out.tmp" "$out" |
| 67 | echo "wrote $out: $(($(wc -l <"$out") - 1)) weighted tests" |
| 68 | |