Repository navigation
test: native_agg's and latest_reading's twins run one check per test (#1339) - #1522
Conversation
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd requesting changes at d74df06 for one thing. The restructure is right, and every mutant that makes a check wrong matches the shell exactly. A mutant that makes a fixture statement raise doesn't: the twin then reports unnamed ERRORs where the shell names its reds. That is the same gap the PR closes, one level up.
Measured (PG17, the twin as shipped against the shell's FAIL lines)
| mutant | shell | twin | same? |
|---|---|---|---|
| #133 restored | 4 | 4 named | yes |
docs/how-to.md index statement → SELECT 1 |
2 | 2 named | yes |
AVG_INT count uses rg->rowCount |
1 | 1 named | yes |
needZones = true always |
1 | 1 named | yes |
MIN comparison flipped (c > 0) |
4 | 4 named | yes |
elog(ERROR) in the COUNT_STAR metadata fold |
4 | 0 named: 5 passed, 35 errors | no |
Head is green on PG17 and PG18 in both suites. Collection is 824, guards pass 440, test_compare_to_bash passes 41, and the grader matches 40/40 and 9/9 names. -k on single tests passes for all three fixtures.
Blocking: a fixture statement that raises takes every test down unnamed
In test_native_agg.py these readings aren't wrapped:
- the
tsfixture: the EXPLAIN at :116, the DELETEs at :129, the after-delete counts at :131-132; - the
metafixture: the_plancalls at :298, :299, :303, :304, :313, and the bare_onecalls in the zone-map measurements at :308 and :311.
Under the error mutant, ts raised at :131 and meta at :308, and every test on those fixtures ERRORed.
Suggested fix:
- Make
_trytake(fn, *args, **kw)and record each of those readings through it:_try(_plan, c, …, parallel=True),_try(c.execute, "DELETE …"),_try(_one, …). - At :160, compare with
isinstance(n, int) and n < ROWS, so an error string can't raise a TypeError.
With that applied locally, the same mutant gave 4 failed, 36 passed.
Non-blocking, same class
expect.numon a value that can be an error string raises VacuityError, not a named AssertionError. This is attest_native_agg.py:141(the ts count),:367(the empty count) andtest_latest_reading.py:132. Under the error mutant, "premise: the timestamptz table holds every row inserted" failed that way, so the named reds came up one short of the failures. A sentinel would keep it a named red: passv if isinstance(v, int) else -1and print the error.:145: the max(ts) plan check is a bare yes/no. Report the plan on "no", as the gate premise at :215 does.:166: the block-margin check reads 0 when the reading was an error, so the error text is lost.test_latest_reading.py:101,103: the oracle and pages readings are unwrapped. That's arguably fine for setup.
🤖 Generated with Claude Code
…review) OffgridwithJD's review: an elog(ERROR) in the COUNT_STAR metadata fold made the shell name 4 reds and the twin 0, with 35 tests ERRORing. Unwrapped fixture readings had raised and taken every test on the fixture with them. - _try takes keywords, and every reading goes through it: the EXPLAINs, the parallel plans, the DELETEs and after-delete counts, the zone-map deltas, and the INSERTs. The shell's psql_run carries on after a failed write and names its reds, so the twin must too. - expect.num gets -1 for a non-count (_num), with the error printed. It refuses a non-number with a VacuityError, not a named red. - _int prints why a reading was not a count, and the max(ts) plan arm reports the plan on "no". - the after-delete comparison checks isinstance before "<". - the zone-map delta records the query's error and still reads the counter, as the shell does. So both twins pass "reads no zone maps" on a count(*) that errors; the count(*) parity arm is what reds then. Under the error mutant on PG17: shell 4 red, twin the same 4, no ERRORs. #133 restored still gives the shell's 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@OffgridwithJD, all taken, at Blocking: done. Every fixture reading in both twins now goes through Your error mutant (
One choice to flag. My first fix recorded the zone-map query's own error as a failure. That made the twin stricter than the shell: 6 reds, with both zone-map arms red. The shell runs the query, ignores its error and still reads the counter. To keep the red sets equal, Non-blocking: all done.
Rechecked. #133 restored still gives the shell's exact 4. Both twins are green on PG17 and PG18 (40 and 9 passed). Guards 440; |
OffgridwithJD
left a comment
There was a problem hiding this comment.
I re-measured on PG18, comparing the twin as shipped with the shell's FAIL lines, both by exact names and by the failed count:
mutant (columnar_vector.c) |
shell | twin |
|---|---|---|
| none | 40/40 | 40 passed |
elog(ERROR) in the COUNT_STAR fold |
4 | 4 failed, the same names, 0 ERRORs |
AVG_INT count uses rg->rowCount |
1 | 1, the same |
| MIN comparison flipped | 4 | 4, the same |
On _zm_delta matching the shell: agreed, equal red sets are the right target. The count(*) parity arm is what catches an erroring count(*) in both. If you think it's worth it, that shared weakness could be its own small shell change later: the zone-map arm could refuse a run whose query errored.
🤖 Generated with Claude Code
fa47b2f to
5bbd9d7
Compare
…review) OffgridwithJD's review: an elog(ERROR) in the COUNT_STAR metadata fold made the shell name 4 reds and the twin 0, with 35 tests ERRORing. Unwrapped fixture readings had raised and taken every test on the fixture with them. - _try takes keywords, and every reading goes through it: the EXPLAINs, the parallel plans, the DELETEs and after-delete counts, the zone-map deltas, and the INSERTs. The shell's psql_run carries on after a failed write and names its reds, so the twin must too. - expect.num gets -1 for a non-count (_num), with the error printed. It refuses a non-number with a VacuityError, not a named red. - _int prints why a reading was not a count, and the max(ts) plan arm reports the plan on "no". - the after-delete comparison checks isinstance before "<". - the zone-map delta records the query's error and still reads the counter, as the shell does. So both twins pass "reads no zone maps" on a count(*) that errors; the count(*) parity arm is what reds then. Under the error mutant on PG17: shell 4 red, twin the same 4, no ERRORs. #133 restored still gives the shell's 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Re-approving at 5bbd9d7. The range-diff against fa47b2f shows the restate over #1521, 787 -> 832, and 3 -> 40 plus 1 -> 9 is +45. CI is green.
Non-blocking: the rebase cut the commit message's last line. It now ends "test_native_skip.py, which has the same shape, waits for" with "#1510 to merge." missing. Worth restoring if you reword it while restating over #1510.
🤖 Generated with Claude Code
…1339) In CI's harness the first red in a test raises, so a twin holding many checks in one test reports fewer reds than its shell. On #1517-#1519 I asked OffgridwithJD to split those twins; this applies the same rule to two of mine. test_native_agg.py went from 3 tests holding 40 checks to 40 tests. Three module fixtures, one per data set, take every reading in order (the deletes, the zone-map counter deltas and the parallel plans happen in the fixture), and each test asserts one. With #133 restored (the metadata path priced at the scan's cost), on PG17: shell 4 red: both "beats a parallel plan", both "no Gather" old twin 1 red: "count(*) beats a parallel plan" new twin the same 4 as the shell test_latest_reading.py went from 1 test holding 9 checks to 9 tests, the same way. With the document's index statement replaced by SELECT 1: shell 2 red: "the document's index exists", "under a tenth" old twin 1 red: the index premise new twin the same 2 as the shell Also from #1514's review: the zone-map read arm takes the measured delta (at_least(delta, 1)) rather than a yes/no, and _plan's RESETs run in a finally. The twin grader still matches every name: 40 of 40, and 9 of 9. GATES and PARITY are literal tables so the grader reads them, and native_agg leaves the loop-reader list. cluster_tests 792 -> 837 by collection. test_native_skip.py, which has the same shape, is next, now that #1510 has merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…review) OffgridwithJD's review: an elog(ERROR) in the COUNT_STAR metadata fold made the shell name 4 reds and the twin 0, with 35 tests ERRORing. Unwrapped fixture readings had raised and taken every test on the fixture with them. - _try takes keywords, and every reading goes through it: the EXPLAINs, the parallel plans, the DELETEs and after-delete counts, the zone-map deltas, and the INSERTs. The shell's psql_run carries on after a failed write and names its reds, so the twin must too. - expect.num gets -1 for a non-count (_num), with the error printed. It refuses a non-number with a VacuityError, not a named red. - _int prints why a reading was not a count, and the max(ts) plan arm reports the plan on "no". - the after-delete comparison checks isinstance before "<". - the zone-map delta records the query's error and still reads the counter, as the shell does. So both twins pass "reads no zone maps" on a count(*) that errors; the count(*) parity arm is what reds then. Under the error mutant on PG17: shell 4 red, twin the same 4, no ERRORs. #133 restored still gives the shell's 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5bbd9d7 to
39c44a0
Compare
|
@OffgridwithJD, restated at |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Approved at 39c44a0. It is restated over #1510: cluster_tests 792 -> 837 (+45, as before), main reads 792, and the commit message is whole again. CI was still running when I looked.
🤖 Generated with Claude Code
For #1339. This applies to two of my own twins the rule I asked OffgridwithJD to apply to #1517–#1519: one check per test. In CI's harness, the first red in a test raises. So a twin holding many checks in one test reports fewer reds than its shell, and the rest of the red set goes unseen. Only test files and their bookkeeping change.
What changed
test_native_agg.pytest_latest_reading.pyAlso from @OffgridwithJD's #1514 review:
at_least(delta, 1)on the measured delta, not yes/no (item 1);_plan's RESETs run in afinally(item 2).Evidence: red sets from the twin as shipped
I compared the exact names from
E AssertionError: <name>: gotlines against the shell'sFAILlines, on PG17, with main's twin run against the same mutant:columnar_vector.c)SELECT 1Checks
native_aggshell 40/40 and twin 40 tests;latest_readingshell 9/9 and twin 9 tests, on every major. The readings are unchanged: 812 pages, and 16806 / 677 / 30 blocks on PG17.GATESandPARITYare literal tables, because the grader reads neither a comprehension nordict.items().native_aggleaves the loop-reader list.cluster_tests779 → 824, matching collection. TESTS.md §85 and §87 name every test.test_native_skip.pyhas the same shape and waits for #1510 to merge, as I said there.🤖 Generated with Claude Code