Repository navigation
test: edge-case + property suites for 10 key backend modules (/edge-cases 2026-10-06) - #3327
Conversation
…ases 2026-10-06) Adds parametrized edge-case and Hypothesis property tests for capacity/slots, idempotency, dispatch breaker + redelivery governor, loop service, credential encryption + secret settings, URL validation, safe YAML + credential paths + sanitizer, backlog + dispatch admission, operator queue, and pull coordination. Tests only — no product code changes. 22 real bugs are pinned as strict xfails, each naming its issue: #3311 #3312 #3313 #3314 #3315 #3316 #3317 #3318 #3319 #3320 #3321 #3322 #3323 #3324 #3325. Lua-tier breaker tests skip until lupa is added (#3326). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- sanitize_text idempotence: drop the PASSWORD=' glue from the property alphabet; pin the real counterexample as a strict xfail on #3328. - operator-queue marker: a continuing hold keeps the since the file already carried (even a blank one), not always T1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
merge-train (2026-10-07): pushed Two Hypothesis properties were not derandomised and found real counterexamples on roughly 1 in 4 and 3 in 4 local runs, so they would have flipped the unit job red on unrelated PRs:
Not changed, worth a follow-up: S11 ( |
… — keep-both on append-only files
|
merge-train (2026-10-07): merged as part of train #3329 (green). Before the squash, |
…tomic admission dev's edge-case suites (Abilityai#3327) pin that re-acquiring an already-held execution id under the cap returns True and is counted once. The atomic admission returned False, which CapacityManager reads as capacity-full (queue_persistent would re-queue a running row; reject would fail it). acquire_slot now returns True for a held id under the cap. The decision stays inside the WATCH/MULTI/EXEC step: the held path EXECs a read-only transaction, so 'held and under the cap' is validated against the same watched keys as a new admission and retried on WatchError. Nothing is written - the slot is not renewed and its metadata is not overwritten. At the cap a held id still returns False (it counts itself), as on dev. Tests: - test_r14 (Abilityai#3318) is fixed by this PR: drop the strict xfail and hook the pipeline's capacity read, so the interleaving still runs (and asserts it ran). - test_atomic_slot_admission.py: duplicate-id cases updated to the idempotent contract (every caller True, one member, metadata untouched). Refs Abilityai#3305, Abilityai#3318 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(capacity): make slot admission atomic across workers * test: link atomic admission regression to issue 3305 * fix(capacity): re-acquiring a held slot id is idempotent inside the atomic admission dev's edge-case suites (#3327) pin that re-acquiring an already-held execution id under the cap returns True and is counted once. The atomic admission returned False, which CapacityManager reads as capacity-full (queue_persistent would re-queue a running row; reject would fail it). acquire_slot now returns True for a held id under the cap. The decision stays inside the WATCH/MULTI/EXEC step: the held path EXECs a read-only transaction, so 'held and under the cap' is validated against the same watched keys as a new admission and retried on WatchError. Nothing is written - the slot is not renewed and its metadata is not overwritten. At the cap a held id still returns False (it counts itself), as on dev. Tests: - test_r14 (#3318) is fixed by this PR: drop the strict xfail and hook the pipeline's capacity read, so the interleaving still runs (and asserts it ran). - test_atomic_slot_admission.py: duplicate-id cases updated to the idempotent contract (every caller True, one member, metadata untouched). Refs #3305, #3318 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(capacity): held re-acquire refreshes the lease; bound the admission retry loop Two findings from independent validation of the atomic admission. 1. A held id re-acquired under the cap now takes the same atomic write as a new admission, as dev does: ZADD re-anchors the score to now and the metadata hash + TTL are rewritten, inside the same WATCH/MULTI/EXEC. The previous read-only held path returned True on a lease dated from the original admission, so a re-dispatch could be reaped mid-run (the #2433 class), and a held slot whose metadata had expired stayed without it. The member is still counted once; at the cap a held id still returns False and writes nothing (dev's contract, pinned by the p1 oracle). 2. The retry loop is bounded by MAX_ADMISSION_ATTEMPTS (32). redis-py reports a connection lost on a WATCHing pipeline as WatchError, so a connection that kept dying at EXEC retried forever, synchronously, on the event loop. Exhaustion raises SlotAdmissionError (a RedisError): an undecided admission never returns True or False. Tests: the connection-loss cases inject the fault from the connection's send inside the real Pipeline.execute (the old test replaced execute() wholesale and asserted a ConnectionError production cannot raise from there); new cases pin the bound, the single-loss retry, the refresh and the at-cap refusal. Refs #3305 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: trinity-ability <309458136+trinity-ability@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
This PR adds edge-case and property-based tests for 10 high-risk backend modules, from the
/edge-casessweep run on 2026-10-06. It is tests only: no product code changes.For each module the sweep listed boundary cases (boundary values plus the Trinity bug-class checklist), wrote parametrized pytest cases for the gaps and Hypothesis properties for the invariants, and classified every failing test as a wrong test, a wrong property, or a real bug. Each module was then checked with branch coverage and a scoped, hand-applied mutation pass.
capacity_manager+slot_serviceidempotency_service(+db/idempotency)dispatch_breaker+redelivery_governorloop_servicecredential_encryption+secret_settingsurl_validationsafe_yaml+credential_paths+credential_sanitizerbacklog_service+dispatch_admission_serviceoperator_queue_service(+operator_queue_choices)pull_coordination_service+pull_pilotAll 22 real bugs are
xfail(strict=True), and each reason names its issue. So when a fix lands, its xfail turns into an XPASS and fails the run, which forces the marker to be removed in the fixing PR.Test plan
pytest tests/unit/test_ec_*.py: 1306 passed, 30 skipped, 49 xfailed. The 30 skips are the Lua-tier breaker tests, which needlupa(test: run the dispatch-breaker Lua state machine in unit CI (add lupa) #3326).pytest tests/unit/test_ec_*.py --runxfail: all 49 xfails fail, each for the stated bug.tests/unitin a fixed order (-p no:randomly), with and without these files: identical failure sets. Local failures that already exist (ent666, ent477, ent679, retention_floor, route_census) are environment-only and unchanged.tests/lint_sys_modules.pyandtests/lint_root_test_placement.pyare clean.Also adds 20
tests/registry.jsonentries.🤖 Generated with Claude Code