fix: batch A - crash bugs, a leak, and startup/edge fragility
CI / compile (pull_request) Successful in 10s
CI / unit (pull_request) Successful in 19s
CI / integration (pull_request) Successful in 10s
build / build (push) Failing after 46m40s
CI / compile (push) Successful in 20s
CI / unit (push) Successful in 19s
CI / integration (push) Successful in 16s
CI / compile (pull_request) Successful in 10s
CI / unit (pull_request) Successful in 19s
CI / integration (pull_request) Successful in 10s
build / build (push) Failing after 46m40s
CI / compile (push) Successful in 20s
CI / unit (push) Successful in 19s
CI / integration (push) Successful in 16s
Seven confirmed defects from the code audit, each small and low-risk.
* ai_functions.get_random_cyclic_message: random.randint(0, len(CYCLIC_WORDS))
is inclusive -> could return len -> IndexError. Now randrange(len) + guard on
an empty CYCLIC_WORDS.
* librarian_commands.get_image_sadox: random.randrange(0, len(res)-1) never
picked the last comic and raised ValueError('empty range') on a single file.
Now randrange(len) + an empty-dir guard.
* ai_commands image generation: every DALL-E error branch replied but did not
return, so control fell through to `if response:` with response unbound ->
UnboundLocalError right after the friendly message. Each branch now returns;
response is pre-initialised; and PermissionDeniedError no longer passes a
(message, text) tuple as a single arg.
* search_bot DOI match: `item["DOI"] in data` was a substring test, so a DOI
that is a prefix of a longer one (10.1/1 vs 10.1/12) produced a false 'exists'
hit. Now matches the line's first whitespace token exactly, via an O(1) dict
index built once per consumer (also removes the O(queried-DOIs) per-line scan
- a real win for large databases).
* communication_subroutine.scan_incoming: matched records were never removed
from awaiting_q, so it grew unbounded over uptime and a reused UUID could
re-match a stale record. Matched records are now dropped after dispatch.
* communication_subroutine.id3: (resp.headers.get("icy-name") or "").title()
guards against a stream that omits headers (was AttributeError on None,
500-ing the /prepped_tracks "next" handler).
* betoniarka.scan_tracks: waits for the radio logs to exist instead of dying
with FileNotFoundError on a fresh deploy (which silently killed the
now-playing forwarder until a restart).
Verified: tests/unit/test_search_bot.py gains exact-match and trailing-metadata
cases; full unit job 43 passed. Remaining observations (image-gen stale
/home/pi fallback paths + dead FileNotFoundError-after-OSError branch; tailer
still vulnerable to mid-run log rotation; DOI-first-token assumption) noted for
follow-up - none are crashes on the normal path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #8.
This commit is contained in:
@@ -94,6 +94,33 @@ def test_survives_invalid_utf8_byte_and_still_finds_later_doi(tmp_path, monkeypa
|
||||
assert hit, "DOI after the bad byte was not found - the file was aborted mid-read"
|
||||
|
||||
|
||||
def test_doi_match_is_exact_not_substring(tmp_path, monkeypatch):
|
||||
# A DB line "10.1/12" must NOT satisfy a search for "10.1/1" (the old
|
||||
# `doi in line` substring test did). The exact DOI must still be found.
|
||||
monkeypatch.setattr(search_bot, "DATABASE_PATH", str(tmp_path) + "/")
|
||||
(tmp_path / "0_chunk.txt").write_text(
|
||||
"10.1/12\n10.1/1\n10.2/999\n", encoding="utf-8"
|
||||
)
|
||||
|
||||
finished, result = _run_bounded([("10.1/1", "DATA"), ("10.9/absent", "DATA")])
|
||||
|
||||
assert finished
|
||||
by_doi = {r["DOI"]: r["exists"] for r in result}
|
||||
assert by_doi["10.1/1"] is True # exact line present -> found
|
||||
assert by_doi["10.9/absent"] is False
|
||||
|
||||
|
||||
def test_doi_match_handles_line_with_trailing_metadata(tmp_path, monkeypatch):
|
||||
# Lines of the form "<DOI>\t<metadata>" still match on the first token.
|
||||
monkeypatch.setattr(search_bot, "DATABASE_PATH", str(tmp_path) + "/")
|
||||
(tmp_path / "0_chunk.txt").write_text("10.5/abc\tsome title here\n", encoding="utf-8")
|
||||
|
||||
finished, result = _run_bounded([("10.5/abc", "DATA")])
|
||||
|
||||
assert finished
|
||||
assert result[0]["exists"] is True
|
||||
|
||||
|
||||
def test_discover_chunk_files_sorted_numerically(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(search_bot, "DATABASE_PATH", str(tmp_path) + "/")
|
||||
for n in (0, 2, 10, 1):
|
||||
|
||||
Reference in New Issue
Block a user