Repository navigation
test: native_roundtrip gains its pytest twin, and asserts the read crosses its row groups (#1341) - #1518
Conversation
a227d93 to
5be44b2
Compare
jdatcmd
left a comment
There was a problem hiding this comment.
@OffgridwithJD, requesting changes at 5be44b28 for one thing: the twin still hides part of the red set, which the body says the split prevents.
My mutant: a by-reference null reads back as a present empty value
In columnar_reader.c's per-value decode, the null branch returns an empty text with nulls[c] = false when !att->attbyval. That's a different class from your by-value mutant: only v text is affected. On PG17:
| red | |
|---|---|
main's native_roundtrip.sh |
4: all columns, null handling (v), filtered scan, projection |
| this PR's shell | the same 4 (9 checks, 5 pass) |
| this PR's twin | 2: all columns, null handling (v). 2 pass, 2 fail |
test_a_native_table_reads_back_what_the_heap_holds runs "all columns", "filtered scan" and "projection" in one loop. The first red raises, so the other two never run. The body says the two-test split is there "so one red doesn't hide the rest of a red set", and under this mutant it hides half of it. Your three mutants happened not to show it: each one's red names fell one per test, or into the row-count test.
Suggested fix: parametrize the two loop tables, so each name is its own test. cluster_tests then goes up by the number of names rather than by 2, and the loop-reader entry can go, because the names become parametrize ids. Or anything else that runs each check whatever the one before it did.
Non-blocking
premise:on the row-group count. A writer that ignoresstripe_row_limitreddens it, so by #1236 it's a property rather than a premise. Same as the plan premises in #1513 and #1517.- "native row count" is answered from metadata, as your body notes, so it can't see a lost row group. Worth a word in the TESTS.md row.
5be44b2 to
6de9308
Compare
The twin covers all 7 checks by the shell's name, in two tests. Its skip counter reads -1 when the plan has none, so "bloom off skips nothing" cannot pass on a plan without the columnar scan, and "bloom on skips groups" is an at_least on the count rather than yes/no. The shell is unchanged: an absent counter there is an empty string, which neither of its skip arms accepts. Five runs on PG18 (none, the bloom consulted whatever the GUC says, never consulted, answering absent for every value, never written) redden the same names in both: 0, 1, 1, 1 and 2. Ledger: native_bloom seeded, 4433 -> 4440 rows, never 3071 -> 3074, dated 1362 -> 1366, suites_not_covered 187 -> 186. cluster_tests 758 -> 760, TESTS.md §179, and the stem leaves unported_suites.txt. Stacked on #1518. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the index (#1341) The shell's "indexed lookup after gap" counted with the defaults, which plan an Index Only Scan. That fetches each row only while the visibility map is unset (so the old suite was already red under an index fetch that finds no row) and answers from the index alone once a VACUUM marks the pages. It is now forced to fetch every row through n_id (custom scan, seqscan and bitmap scans off, count(v)), and a premise asserts the plan, as native_truncate's lookup is. A guard, not a fix. The twin covers all 9 checks by the shell's name, one check per test: a module fixture runs every step in the shell's order and records each reading, so one red cannot stop the checks after it. The file-growth arm is an at_least on the measured growth rather than yes/no. Four runs on PG18 (none, gap fill removed as before 6a16582, the test hook advancing nothing, index fetch finding no row) redden the same names in the shell and in the twin as shipped: 0, 6, 1 and 1. Ledger: native_gap seeded, 4415 -> 4424 rows, never 3066 -> 3069, dated 1349 -> 1355, suites_not_covered 189 -> 188. cluster_tests 754 -> 763, TESTS.md §177, and the stem leaves unported_suites.txt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…osses its row groups (#1341) The suite's header says the read crosses several row groups, and nothing checked it. A new check, "the native table holds five row groups", counts them: stripe_row_limit 1000 over 5000 rows gives five. The twin covers all 9 checks by the shell's name, one check per test: the reads and the answers are parametrized by the shell's names, so one red cannot stop the next. Five runs on PG18 (none; a null by-value column read back as a present 0; a null by-reference one read back as a present empty value, jdatcmd's; the last row group never loaded; zone-map pruning inverted) redden the same names in the shell and in the twin as shipped: 0, 2, 4, 6 and 1. The old suite is red on the same names under each (the by-reference one as jdatcmd measured it). Ledger: native_roundtrip seeded, 4424 -> 4433 rows, never 3069 -> 3071, dated 1355 -> 1362, suites_not_covered 188 -> 187. cluster_tests 763 -> 772, TESTS.md §178, and the stem leaves unported_suites.txt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6de9308 to
9bc605c
Compare
|
@jdatcmd agreed on all of it, and thank you for both mutants. I took (a), one check per test, in all three PRs:
The red-set tables now come from the twin as shipped, not from my local soft runner. You were right that the soft runner showed only that a name could go red. My runner now runs the real twin file and reads the
Also done:
On (b), a deferred-failure mode for 🤖 Generated with Claude Code |
jdatcmd
left a comment
There was a problem hiding this comment.
Approving at 9bc605ce. I took (a) in this PR and reran my mutant on the twin as shipped, comparing exact red-name sets from E AssertionError: <name>: got lines against the shell's FAIL lines. PG17:
| mutant | shell red | twin red | sets |
|---|---|---|---|
| a by-reference null reads back present and empty (`columnar_reader.c`) | 4 | 4 | identical: all columns, null handling (v), filtered scan, projection |
Counts. One cluster_tests line, 772, and collection at this head is 772.
At the stack's tip (e53ba5d6), test_harness_deps, test_compare_to_bash and test_mutation_ledger pass 105.
I'll merge in stack order as CI goes green: #1517, then #1518, then #1519.
|
@OffgridwithJD merging #1518 now at |
@jdatcmd Stacked on #1517. Review only the top commit, 9bc605c.
What changes
A new check.
native_roundtrip.sh's header says the read crosses several row groups, and nothing checked that. A new check, "the native table holds five row groups", counts them inpgcolumnar.row_group:stripe_row_limit1000 over 5000 rows gives five. It isn't apremise:, because a writer that ignores the limit would redden it.The twin is
test/pytest/test_native_roundtrip.py. It covers all 9 checks by the shell's name, one check per test. The reads and the answers are parametrized by the shell's names (name,sql), so one red can't stop the next. The loop-reader list no longer needs the file.Evidence: the shell against the twin as shipped (raising
expect)columnar_reader.c)All of these are PG18 runs, and yours gives the same 4 on PG17. The head run is 9/9 on each of PG15–19.
Bookkeeping
native_roundtripseeded with 9 rows: 4424 → 4433, never 3069 → 3071, dated 1355 → 1362,suites_not_covered188 → 187.cluster_tests763 → 772, nine tests.unported_suites.txt.🤖 Generated with Claude Code