diff options
| author | Scott Gasch <[email protected]> | 2026-08-29 19:26:49 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-08-29 19:26:49 -0700 |
| commit | 9632634b648109765955e89ec07f788388d8170f (patch) | |
| tree | 7854105dd63ae6eb95f776700048e824f9650575 /src/debug_smoke_test.sh | |
| parent | 4b99e893a2b423247fd20ab69c0346fcbe6bca81 (diff) | |
Fix batch-mode exit code, killer-table backfill collision, impossible QSearch mate-magnitude asserts, MATEMOVE PV display, --command truncation, and test.sh's stale egtbpath.
Several small, independent correctness fixes bundled together since
they were all exercised together through today's precommit_check.sh
and curated-suite runs:
- command.c: batch-mode's "Exhausted input" exit was exit(-1), which
truncates to 255 (an 8-bit status) and is indistinguishable from a
real crash's nonzero exit. Changed to exit(0) so debug_smoke_test.sh
can reliably tell a clean batch run apart from a crash by exit status
alone.
- dynamic.c: _NewKillerMove's slot[1] backfill from
mvNullmoveQuietRefutations[uPly] had no check that the backfilled
move differed from the move just placed in slot[0]. When they
coincided, both slots held the identical move, silently wasting a
killer slot in release builds (ASSERT is a no-op there) and tripping
_NewKillerMove's own IS_SAME_MOVE invariant in DEBUG builds. Fixed by
skipping the backfill on collision.
- search.c: removed two ASSERT(iBestScore > -NMATE) calls in QSearch
that encoded an invariant that isn't actually guaranteed -- at an
early full-width root iteration, or after aspiration-window widening
following repeated fail-highs, an ancestor frame's iAlpha/iBeta can
itself already be more extreme than -NMATE with no mate anywhere in
the line, so a legitimate fail-low placeholder or fail-high score can
land in mate-magnitude territory purely as a window artifact.
hash.c's storage path already treats any value <= -NMATE as a sound
upper bound regardless of origin, so this was a false invariant, not
a caught bug. Also: minor whitespace cleanup, an added ASSERT
documenting the futility-margin depth precondition it replaced a
redundant runtime check for, and PV/leaf-count bookkeeping on the
mate/draw-at-root leaf paths that was previously skipped.
- util.c: MATEMOVE sentinel moves weren't handled in PV-to-string
conversion, so a PV ending in a detected mate would either display
garbage or hit the same-move assert. Added an explicit "<#>" marker.
- test.sh: --egtbpath pointed at a nonexistent /egtb/three;/egtb/four;
/egtb/five; corrected to /zscratch/egtb, this box's actual EGTB
location.
- main.c/input.c: --command's initial-command buffer (g_szInitialCommand)
was a fixed 256-byte array; strncpy(..., SMALL_STRING_LEN_CHAR - 2)
silently truncated any longer --command string, and -- worse -- when
the source was long enough not to fit, strncpy doesn't null-terminate
the destination, so the immediately-following strcat(..., "\r\n") could
read/write past the buffer. Long move-replay command strings used
during this session's debugging hit the truncation directly (a ~600
char move list silently cut off mid-token, desyncing the input queue).
Changed g_szInitialCommand to a heap allocation sized to the actual
input length instead of a fixed cap.
- CLAUDE.md: documents the above (this file's own diff is prior
session's writeup of these same fixes, committed now alongside the
code).
All exercised together via precommit_check.sh (self-test suite + DEBUG
smoke test against random ecm.ep_ samples) and the sd10/sn5m curated
suite sweep run for the eval.c hand-tuning commit just before this one.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01M9ZDiJhiUajUxh95mTXCFJ
Diffstat (limited to 'src/debug_smoke_test.sh')
| -rwxr-xr-x | src/debug_smoke_test.sh | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/debug_smoke_test.sh b/src/debug_smoke_test.sh new file mode 100755 index 0000000..1d2ba0e --- /dev/null +++ b/src/debug_smoke_test.sh @@ -0,0 +1,82 @@ +#!/bin/sh +# Fast pre-commit smoke test: run a DEBUG=1 build over a random sample of +# positions from the full 881-position tests/ecm.ep_ suite at a shallow +# fixed depth, to catch assertion failures without paying full bench-depth +# DEBUG overhead. Variety (many distinct positions) matters more here than +# depth or suite curation -- each position starts with fresh killer/history +# state and a different piece mix, exercising more distinct code paths per +# second than grinding one position deeper or reusing the same fixed +# curated suite every run. Sampling fresh positions each run (rather than a +# fixed suite) also means repeated runs build up coverage over time instead +# of exercising the exact same 11-90 positions forever. +# +# Usage: ./debug_smoke_test.sh [path-to-DEBUG-binary] [depth] [count] +# Defaults: ./_typhoon, sd 4, 10 positions + +BIN="${1:-./_typhoon}" +DEPTH="${2:-4}" +COUNT="${3:-10}" +SUITE=../tests/ecm.ep_ +LOGDIR=/tmp/typhoon/smoke_test +mkdir -p "$LOGDIR" + +if [ ! -x "$BIN" ]; then + echo "ERROR: $BIN not found or not executable (build with DEBUG=1 first)" + exit 1 +fi + +if [ ! -f "$SUITE" ]; then + echo "ERROR: $SUITE not found (run from src/)" + exit 1 +fi + +# ecm.ep_ is NOT a clean fixed-lines-per-problem file (3517 lines / 881 +# problems is not an integer -- some records vary in length), so sample +# whole setboard..go records, not individual lines, or a random line +# offset shreds problems into garbled fragments (silently: the engine's +# script command just reports "total problems: 0" rather than erroring). +SAMPLE="$LOGDIR/sample.ep_" +awk -v k="$COUNT" ' +BEGIN { srand() } +{ sub(/\r$/, "") } +/^setboard/ { rec = $0; next } +/^go[ \t]*$/ { rec = rec "\n" $0; n++; recs[n] = rec; rec = ""; next } +rec != "" { rec = rec "\n" $0 } +END { + if (k > n) k = n + picked = 0 + while (picked < k) { + r = int(rand() * n) + 1 + if (!(r in used)) { + used[r] = 1 + print recs[r] + picked++ + } + } +}' "$SUITE" > "$SAMPLE" + +STAMP=$(date +%Y%m%d_%H%M%S) +LOG="$LOGDIR/sample_${STAMP}.log" +OUT="$LOGDIR/sample_${STAMP}.out" +SAMPLE_SAVED="$LOGDIR/sample_${STAMP}.ep_" +cp "$SAMPLE" "$SAMPLE_SAVED" + +echo "=== $COUNT random positions from $SUITE (sd $DEPTH) ===" +echo " FENs chosen (reproduce a failure with: script $SAMPLE_SAVED):" +grep '^setboard' "$SAMPLE_SAVED" | sed 's/^setboard / /' + +START=$(date +%s) +"$BIN" --cpus 1 --hash 64m --logfile "$LOG" \ + --batch --command "force; book name /nonexistent.book.bin; sd $DEPTH; script $SAMPLE" \ + > "$OUT" 2>&1 +STATUS=$? +END=$(date +%s) +echo " exit=$STATUS elapsed=$((END - START))s" + +if [ "$STATUS" -ne 0 ]; then + echo " *** ASSERTION OR CRASH DETECTED (exit=$STATUS) -- see $OUT / $LOG ***" + echo " positions tried (saved): $SAMPLE_SAVED" + echo "SMOKE TEST FAILED" + exit 1 +fi +echo "SMOKE TEST PASSED" |
