Skip to content

test(strict,cascade): pin documented enforcement limits and audit coverage gaps#1485

Open
dimitri-yatsenko wants to merge 1 commit into
masterfrom
test/audit-gap-coverage
Open

test(strict,cascade): pin documented enforcement limits and audit coverage gaps#1485
dimitri-yatsenko wants to merge 1 commit into
masterfrom
test/audit-gap-coverage

Conversation

@dimitri-yatsenko

Copy link
Copy Markdown
Member

Final piece of the post-2.3 audit remediation (companions: #1480 update1 gate, #1484 cascade fix, datajoint/datajoint-docs#195 docs batch). These tests lock the documented best-effort limits of strict_provenance and the untested cascade part-integrity paths — so a regression in either direction (a documented bypass silently closing, or a blocking path silently opening) becomes visible.

test_strict_provenance_limits.py — the read/write-gate surface, empirically pinned

Idiom (inside strict make()) Pinned behavior
len(Undeclared & key), bool(Undeclared & c) bypass (documented limit)
{...} in (Undeclared & r) (query-expr form) bypass (documented)
{...} in Undeclared (class form) RAISES — metaclass __iter__ routes through the gated cursor (real asymmetry, now locked)
(Ancestor & Undeclared).fetch() restriction-by-table bypass (documented)
(Undeclared * Ancestor).fetch() join RAISES "undeclared" — the one gated read path, previously untested
len(dj.U(...).aggr(Undeclared, ...)) bypass; the same aggregation's .fetch() RAISES
delete_quick() on another/undeclared table bypass (documented: deletes ungated)
self.insert(<QueryExpression>) target gate holds; per-row key consistency skipped (documented INSERT…SELECT exception)
self.upstream[SelfPart] vs self.PartName read upstream raises; direct read allowed
context cleanup after a raising make(); nested push/pop token restore verified

test_cascade_integrity.py

  • Enforce post-check + rollback: cascade reaching a Part without its Master raises "before its master" and rolls back completely (previously only the Part.delete pre-guard had a test).
  • Empty-materialization sentinel: cascade mode with zero matching part rows previews the master at 0 and deletes cleanly.
  • U3 upward arm: a Part with a secondary -> master FK — proj(*attr_map.keys()) correctly restricts only the right master; a bare proj() would have restricted both (assertion distinguishes the exact fix(#1429): cascade through FK chain for part_integrity="cascade" #1468 code path).

Also

  • Corrects the provenance.py module docstring (audit item B6): context is pushed/popped inside _populate_one in whichever process/thread runs the make() — the old "inherits at fork time / across threads" rationale was inaccurate (behavior unchanged).

New files only — no conflicts with the #1480/#1484 branches. All 12 new tests green locally on MySQL + PostgreSQL; existing strict suite unaffected (8/8).

Note: the schema in the read-limits test gives Undeclared an FK from the declared ancestor so the semijoin probe has shared attribute lineage (semantic matching requires it) while Undeclared stays outside the allowed set — a descendant, not an ancestor.

…erage gaps

Locks the behaviors the post-2.3 audit verified, so regressions in either
direction — a documented bypass silently closing, or a blocking path silently
opening — become visible.

test_strict_provenance_limits.py: len/bool and query-expression 'in' bypass
(documented); CLASS-form 'in' RAISES (gated __iter__); restriction-by-table
bypasses; join with undeclared operand RAISES (the one gated read path,
previously untested); Aggregation __len__ bypasses while its fetch RAISES;
delete_quick ungated (documented); INSERT...SELECT skips per-row key
consistency (documented exception); self.upstream[SelfPart] raises while
direct self.PartName read is allowed; context cleared after raising make();
nested push/pop token restore.

test_cascade_integrity.py: enforce post-check raises 'before its master' AND
rolls back; empty-materialization sentinel previews master at 0 and deletes
cleanly; U3 upward arm with SECONDARY -> master FK restricts only the correct
master (bare proj() would restrict both).

Also corrects the provenance.py module docstring (audit item B6): context is
pushed/popped inside _populate_one in whichever process/thread runs make() —
the old across-threads/fork-inheritance rationale was inaccurate. Behavior
unchanged.

New files only — no conflicts with the open #1480/#1484 branches.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant