DAO unit test suite covering all eight tables #23

11 Commits
Author SHA1 Message Date
Joshua King a8d2b1af9d test: collect database calls anywhere in the expression tree
The probe guard now walks Call nodes (execute/fetch_one/fetch_all/
execute_many) rather than bare Await nodes, so calls wrapped inside
asyncio.gather or helper awaitables are still classified and cannot
hide a raw write from the sanctioned-function scan.
2026-09-14 09:10:48 -04:00
Joshua King b67dda8655 test: two-pass import validation so binding order cannot matter
pytest raises aliases are collected across the whole file FIRST, then
every competing import (wherever it appears, even before the genuine
binding) is rejected - closing the reversed-order spoof
2026-09-14 09:08:51 -04:00
Joshua King e5b9146bab test: import-shadow validation covers Import nodes; plain 'import pytest' allowed, aliased spoofs rejected 2026-09-14 09:06:44 -04:00
Joshua King fa502730ef test: guard all database entry points; real ImportFrom binding validation for bare raises
- probe guard now inspects execute, fetch_one, fetch_all AND
  execute_many calls, so bypasses through read/many paths are caught
- bare Name('raises') trusted only when the file's actual ImportFrom
  nodes bind 'raises' from pytest; competing imports shadowing
  'raises'/'pytest' from other modules fail closed
2026-09-14 09:04:49 -04:00
Joshua King fe8ceb2f40 test: sanctioned functions hold exactly their one table's probe; bare raises requires from-pytest import binding
- every raw statement naming either table in a sanctioned function must
  be exactly that function's expected-table probe (cross-table inserts
  rejected); per-function count still enforces exactly one
- bare Name('raises') is trusted only when the file imports it from
  pytest (from pytest import ... raises); other import bindings
  rejected
2026-09-14 09:03:23 -04:00
Joshua King d1e4603a15 test: matcher base-chain validation, casefolded table comparison 2026-09-14 09:00:25 -04:00
Joshua King 86bd4023f4 test: structurally-exact raises shape and identifier-normalized table matching
- raises block: func must be Attribute pytest.raises or a bare Name
  'raises'; matcher must be a Name/Attribute chain whose final segment
  is exactly IntegrityError (fake.IntegrityError/NotIntegrityError fail)
- insert target matching tokenizes the leading identifier, strips
  quotes/brackets, and takes the last dot-segment, so INSERT OR IGNORE
  INTO "main"."children" and attached-qualified spellings all count
  as table inserts requiring the raises block
2026-09-14 08:58:50 -04:00
Joshua King d34c08b5b7 test: AST-exact probe guard - pytest.raises shape, IntegrityError matcher, INSERT-variant normalization, per-function probe count
- raises block must be pytest.raises (func attr check) with matcher
  exactly naming IntegrityError (dotted-name boundary match, so
  NotIntegrityError fails)
- INSERT OR IGNORE/quoted/qualified table spellings normalized before
  matching so they cannot bypass the raises-block requirement
- probe count is per-function (each of the two sanctioned functions
  must hold exactly one probe), not an aggregate
2026-09-14 08:56:48 -04:00
Joshua King 020b3679e1 test: exact pytest.raises(IntegrityError) matcher, UPDATE/DELETE ban, unquote AST strings in probe guard 2026-09-14 08:54:38 -04:00
Joshua King 2265b5c3f1 test: real conflict-refresh assertions; AST-exact probe guard
- task-instances matrix test asserts same row id + rewritten due_time
  + pre-refresh None (the vacuous refreshed_same_id walrus is gone)
- compensating guard parses the two sanctioned functions' ASTs: each
  must contain its raw INSERT (children NOT NULL, admin_users PK),
  lexically inside a pytest.raises block, and no other raw SQL may
  name these tables anywhere else in the matrix file
2026-09-14 08:52:30 -04:00
Joshua King c41e28cb29 feat: add cross-table DAO unit suite covering all eight tables (#23) 2026-09-14 08:49:06 -04:00