#!/bin/bash # Correctness gate: no perf win is allowed to cost functionality. # # 1. .auto/check_search.py -- the search fast paths against the plain loop. # Caches that go stale still return AN answer, so no scenario test can see # them; this compares fast and slow directly, for every typed prefix. # 2. .auto/check_rename.py -- a rename keeps the listing's walk and only # re-renders its text. When that goes wrong the pane simply keeps showing # the old name, which nothing else notices. Checks a NARROW read (what # painting does) and a WIDE one (what building the search body does), and # the whole model against a rebuild. # 3. .auto/check_edit.py -- the listing after an ITEM edit. bump_items(ea) # keeps the walk in front of the edit rather than discarding it; keeping # anything across a structural change is the risky half and it fails # silently, so the kept model is compared against a rebuild row for row. # 4. tests/run.py -- the project's own front door: every suite, pure and IDA, # ~185s. It used to be only the scenario suite here, and that gap cost a # real regression: a faster worker connect left the loading overlay up a # moment longer relative to the index finishing, and project mode's first # keypress landed on the overlay. Only test_project_ui.py covers that, and # it was not being run. # # Only failures reach stdout: the agent sees the last 80 lines on failure, and a # wall of "ok" would push the actual break out of view. A file that fails is # re-run ALONE before it counts -- the IDA suites share a loaded box, and a # worker that got CPU-starved mid-analysis reads as a failure but is not one # (see the note in tests/run.py). set -euo pipefail cd "$(dirname "$0")/.." PY="${IDATUI_PYTHON:-$HOME/ida-venv/bin/python}" search=$("$PY" .auto/check_search.py targets/echo 2>&1) || { echo "--- search fast paths disagree with the plain loop ---" echo "$search" | tail -20 exit 1 } echo "$search" | tail -1 rn=$("$PY" .auto/check_rename.py targets/echo 2>&1) || { echo "--- the listing is wrong after a rename ---" echo "$rn" | tail -20 exit 1 } echo "$rn" | tail -1 ed=$("$PY" .auto/check_edit.py targets/echo 2>&1) || { echo "--- the listing is wrong after an item edit ---" echo "$ed" | tail -20 exit 1 } echo "$ed" | tail -1 out=$(python3 tests/run.py 2>&1) || true echo "$out" | tail -2 # Files run.py marked bad, e.g. " FAIL scenarios 301 passed, 2 failed" # run.py's summary says "N passed[, M failed]..."; no "failed" clause == green. if ! echo "$out" | tail -3 | grep -q "failed"; then exit 0 fi echo "--- first pass failures ---" echo "$out" | grep -E "^ FAIL" | head -20 # run.py names them itself: "failing files: formats scenarios" (colourised). files=$(echo "$out" | sed -e 's/\x1b\[[0-9;]*m//g' \ | sed -n 's/^failing files: *//p' | tr '\n' ' ') if [ -z "$files" ]; then echo "--- could not identify the failing file; full tail ---" echo "$out" | tail -30 exit 1 fi echo "--- retrying alone: $files ---" retry=$(python3 tests/run.py $files 2>&1) || true if echo "$retry" | tail -3 | grep -q "failed"; then echo "--- REAL regression ---" echo "$retry" | grep -E "^ FAIL" | head -30 echo "$retry" | tail -3 exit 1 fi echo "flake: [$files] pass in isolation"