Skip to content

test(cascade): pin part-integrity paths (rollback, empty-materialization, U3 arm)#1485

Open
dimitri-yatsenko wants to merge 2 commits into
masterfrom
test/audit-gap-coverage
Open

test(cascade): pin part-integrity paths (rollback, empty-materialization, U3 arm)#1485
dimitri-yatsenko wants to merge 2 commits into
masterfrom
test/audit-gap-coverage

Conversation

@dimitri-yatsenko

@dimitri-yatsenko dimitri-yatsenko commented Jul 6, 2026

Copy link
Copy Markdown
Member

Adds integration coverage for the cascade part-integrity paths hardened in #1484, so a regression in either direction becomes visible.

test_cascade_integrity.py

  • Post-check + rollback: a cascade that reaches 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 (pins the exact fix(#1429): cascade through FK chain for part_integrity="cascade" #1468 code path).

New file only — no conflicts. Tests green locally on MySQL + PostgreSQL. Companion to the cascade fix in #1484.

Scope note

This PR originally also pinned the strict_provenance read/write-gate limits. That surface is being retired in #1489 (which deletes provenance.py), so those tests and the now-moot provenance.py docstring edit were dropped to keep this PR coherent with the guardrail removal. What remains is the cascade-integrity coverage, which is independent of strict_provenance.

…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.
The strict_provenance read/write-gate surface these tests pinned is being
retired in #1489 (which deletes provenance.py). Remove test_strict_provenance_limits.py
and the now-moot provenance.py docstring edit so this PR is coherent with #1489;
retain test_cascade_integrity.py (companion to #1484).
@dimitri-yatsenko dimitri-yatsenko changed the title test(strict,cascade): pin documented enforcement limits and audit coverage gaps test(cascade): pin part-integrity paths (rollback, empty-materialization, U3 arm) Jul 14, 2026

@MilagrosMarin MilagrosMarin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dimitri-yatsenko — three clean pins.

The enforce post-check + rollback test finally covers the data-driven path (cascade reaches Part but not Master → raise + rollback); previously only the direct Part.delete pre-guard had coverage.

The empty-materialization sentinel uses counts.get(Master.full_table_name, 1) == 0 — the 1 default cleanly distinguishes "Master present with zero matches" (the intended [False] sentinel from #1468) from "Master not in counts at all". Both would pass a naïve > 0 check, so the specificity here matters.

The U3 arm with secondary master FK is the isolated non-primary-FK direct-hit test I flagged as a follow-up during #1471. The topology forces U3 exactly, and asserting only master 1 is restricted genuinely distinguishes the fix — a bare proj() would fall to a cross-join and restrict both masters.

Dropping the strict_provenance limits to align with the guardrail removal in #1489 was the right call.

Approving.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Indicates new improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants