#!/usr/bin/env bash # CHECK -- the Q69 repair of wizard-work/volt/q65_rc_probe.py's scratch root. # # The module defaulted SCRATCH_ROOT to one profile's absolute path, so --emit # and --selftest wrote their mutant copies and fixtures into that directory # from any checkout, and the AST census counted the constant as CODE/CONST. # It now derives the root from tempfile.gettempdir(). Five legs, each one # falsifiable on its own: # text the module carries no host-absolute string literal # census the AST census lists no row for the module (rows are mentions) # selftest the tool's own 25 cells still pass # derive a fresh TMPDIR receives the scratch dir the selftest makes # teeth the text leg's predicate fires on a copy carrying the literal back # rc 0 clean, rc 1 a fault it graded, rc 2 it could not grade at all. set -u ROOT="$(cd "$(dirname "$0")/../.." && pwd)" SUB="wizard-work/volt/q65_rc_probe.py" CENSUS="wizard-work/volt/q69_hostroot_census.py" WANT_CELLS=25 faults=0 leg() { printf '%-9s %s\n' "$1" "$2"; } for f in "$ROOT/$SUB" "$ROOT/$CENSUS"; do if [ ! -f "$f" ]; then echo "q69-scratchroot: missing $f; cannot grade" >&2 exit 2 fi done if ! git -C "$ROOT" rev-parse --git-dir >/dev/null 2>&1; then echo "q69-scratchroot: $ROOT is not a git repository; the census cannot read it" >&2 exit 2 fi TMP="$(mktemp -d "${TMPDIR:-/tmp}/q69-scratchroot.XXXXXX")" || exit 2 trap 'rm -rf "$TMP"' EXIT # text -- no host-absolute literal survives in the module hits="$(grep -c '"/\(root\|home\|var\|srv\|opt\|mnt\)/' "$ROOT/$SUB")" if [ "$hits" -eq 0 ]; then leg text "ok (0 host-absolute literal)" else leg text "FAULT ($hits host-absolute literal)"; faults=$((faults + 1)) fi # census -- the AST census mentions the module not at all if python3 "$ROOT/$CENSUS" --json "$TMP/census.json" >"$TMP/census.out" 2>&1; then rows="$(grep -c 'q65_rc_probe.py' "$TMP/census.json")" if [ "$rows" -eq 0 ]; then leg census "ok (0 row for $SUB)" else leg census "FAULT ($rows row(s) name the module)"; faults=$((faults + 1)) fi else leg census "FAULT (census rc $? -- $(tail -1 "$TMP/census.out"))" faults=$((faults + 1)) fi # selftest -- the module's own cells, still green out="$(cd "$ROOT" && python3 "$SUB" --selftest 2>&1)"; rc=$? cells="$(printf '%s\n' "$out" | grep -c '^ok ')" if [ "$rc" -eq 0 ] && [ "$cells" -eq "$WANT_CELLS" ]; then leg selftest "ok (rc 0, $cells/$WANT_CELLS cells)" else leg selftest "FAULT (rc $rc, $cells/$WANT_CELLS cells)"; faults=$((faults + 1)) fi # derive -- the scratch root follows TMPDIR, not a baked-in directory mkdir -p "$TMP/tmpdir" before="$(find "$TMP/tmpdir" -maxdepth 1 -name 'rcprobe-selftest-*' | wc -l)" TMPDIR="$TMP/tmpdir" python3 "$SUB" --selftest >/dev/null 2>&1; drc=$? after="$(find "$TMP/tmpdir" -maxdepth 1 -name 'rcprobe-selftest-*' | wc -l)" if [ "$drc" -eq 0 ] && [ "$after" -gt "$before" ]; then leg derive "ok (TMPDIR gained $((after - before)) scratch dir, rc 0)" else leg derive "FAULT (rc $drc, TMPDIR dirs $before -> $after)"; faults=$((faults + 1)) fi # teeth -- the text leg's predicate is not one that cannot fire cp "$ROOT/$SUB" "$TMP/pinned.py" || exit 2 printf 'SCRATCH_ROOT = "/root/.hermes/profiles/volt/cache/scratch"\n' >>"$TMP/pinned.py" poison="$(grep -c '"/\(root\|home\|var\|srv\|opt\|mnt\)/' "$TMP/pinned.py")" if [ "$poison" -ge 1 ]; then leg teeth "ok (poisoned copy reads $poison, clean copy reads 0)" else leg teeth "FAULT (poisoned copy reads 0 -- the text leg cannot fail)" faults=$((faults + 1)) fi if [ "$faults" -eq 0 ]; then echo "q69-scratchroot: 5 leg(s), 0 fault(s)" exit 0 fi echo "q69-scratchroot: 5 leg(s), $faults fault(s)" exit 1