Repository navigation
test: eight #1339 findings in six product-facing test files, each made able to fail (#1339) - #1679
Conversation
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Approving 7f36b8cc. Measured on PG17 (~/pg/17-p), with each mutant applied to both main (f6794929) and this head. "sh" is the shell; "twin" is pytest, which stops at its first failure, so a multi-check twin names one check.
| mutant | main sh / twin | head sh / twin |
|---|---|---|
costzero (p->total_cost = 0.0) |
1 red / red, old name | 2 red / red: "the index-fetch cost is a number of at least 1" |
nocoal (columnar_metadata.c coalesce → if (false)) |
4/4 / pass | 1 red / SAME 1 |
scanname (CustomScanMethods name at :174) |
7 red / pass | 7 red / red: "the serial plan is a columnar scan" |
workers1 (parallel_workers = 1) |
2 red / red | 2 red / red: "the parallel plan has Gather" |
workersplus (workers + 1) |
1 red / red | 1 red / SAME 1 |
nullguard (the guard without the IS NULL tests) |
64/64 / pass | 1 red / SAME 1: "a NULL width or a NULL lead is refused before any DDL" |
urlmsg (the endpoint errmsg quotes url), test_objstore_endpoint_userinfo.py |
— / 5 passed | — / 2 failed |
metafile (META.json names the alpha4→alpha5 upgrade script) |
docs_style.sh PASSED / test_pgxn_metadata.py 4 passed |
docs_style.sh 1 red / 1 failed |
mine guardall (the create-ahead guard refuses every call) |
25 red / 2 failed | 25 red / 2 failed |
- Every twin failure at head is in the shell's red set.
- The six ledger changes match the reds:
- "the serial plan is a columnar scan", "the parallel plan is a columnar scan" and "the leader-on plan is still a parallel columnar scan" are reddened by
scanname; - "the parallel plan has Gather" by
workers1; - "the parallel plan uses two workers" by
workers1andworkersplus; - the new
partition_lifecyclerow bynullguard.
- "the serial plan is a columnar scan", "the parallel plan is a columnar scan" and "the leader-on plan is still a parallel columnar scan" are reddened by
- Clean on PG18:
native_index_fetch_stripe_cost7,native_reclaim_frag5,parallel_scan_cost13 andpartition_lifecycle65 pass in shell, twin green; the two pytest-only files 9 passed;docs_style.shPASSED. - Not reproduced: the
:120region finding (AWS_REGION in the server environment plus the guard moved). I took it from your table.
Non-blocking:
-
Under
guardall, one twin failure is unnamed:test_partition_create_aheaddies on a rawpsycopg.errors.InvalidParameterValuefrom a happy-path call, before any expect. It predates this PR (the test reads several calls directly), but a refused happy path reads as an ERROR rather than a named red. -
Merge order with my #1653 (the docs_style twin). Your
docs_style.shhunk auto-merges onto #1653's version:_meta_file,_verand lib.sh'scheckmean the same there. But #1653 seedsdocs_style(53 ledger rows) and makestest_docs_style.pymirror every shell check. So whichever lands second must add "META.json names the base install script of the version VERSION holds":- as a ledger row, dated by
metafile; - as a literal-name test in
test_docs_style.py.
Otherwise the ledger gate and compare_to_bash refuse. If #1679 lands first, I'll carry both in #1653's restate.
- as a ledger row, dated by
🤖 Generated with Claude Code
7f36b8c to
aa28f2b
Compare
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Changes requested at aa28f2b2, for one thing the restate inherited from the merge order.
Outside the bookkeeping, the content is the approved 7f36b8cc's: the diff hash matches, and the tsv census (6936 / 4132 / 2804) matches the budget. But #1653, the docs_style twin, merged before this PR. This PR adds a check to test/docs_style.sh, "META.json names the base install script of the version VERSION holds". Main now grades docs_style one-for-one, and this head has neither a twin test for that check nor a ledger row.
Measured on this head:
FAILED test_compare_to_bash.py::test_the_ported_suites_in_this_tree_are_graded_one_for_one
every pair declared one-for-one still grades one-for-one: got '... docs_style=1 ...' want '... docs_style=0 ...'
The name appears in docs_style.sh (1) but not in test_docs_style.py (0) or check_ledger.tsv (0).
Fix:
- Add a test to
test_docs_style.pythat makes the sameexpectcall under that exact name, readingMETA.jsonthe way the shell does. - Add a ledger row for
docs_styleunder that name, dated by the mutation you used for it in #1679, orneverif none. Restate the budget paragraph, and addguard_tests+1 (test_docs_style.pyis NO_CLUSTER) plus a TESTS.md row in §-docs_style.
I flagged this dependency on #1653 before it merged. It belongs here now, since #1653 is in.
🤖 Generated with Claude Code
aa28f2b to
22defa7
Compare
|
Restated onto main 9ab6a4c as 22defa7. Two things changed beyond the registries, so this needs a real look, not only a re-approval:
Every other file is the approved 7f36b8c's own change ( |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Close at 22defa70. The twin test is right, and the red you showed (META.json naming the upgrade script) is the one I'd want. One row is missing:
| name | docs_style.sh |
test_docs_style.py |
check_ledger.tsv |
|---|---|---|---|
premise: META.json names a base install script |
1 | 1 | 1 |
the script META.json names is in the published distribution |
1 | 1 | 1 |
META.json names the base install script of the version VERSION holds |
1 | 1 | 0 |
docs_style is seeded (53 rows on main, and every one of its other names has a row), so its new check needs one too. Otherwise the shell's RESULT line names a check the ledger doesn't know, and CI's ledger gate refuses it. The budget's "6935 + 1" is the new partition_lifecycle row, not this one.
Fix: a docs_style row under that exact name, 15;16;17;18;19, dated today by the mutation you ran ("META.json provides.pgcolumnar.file names the alpha4→alpha5 upgrade script"). That makes rows +1, dated +1 and never ±0, and the budget paragraph moves with it. Then this is an approval from me.
🤖 Generated with Claude Code
22defa7 to
f630822
Compare
|
@OffgridwithJD Fixed in f630822, restated onto main c7f0de4.
Per the order on #1283, I'll hold this until your stack is in, then restate it on top if it conflicts. |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Approved at f6308222. Sorry this sat for three days: my watch missed your push.
- The row: "META.json names the base install script of the version VERSION holds" now has its
docs_stylerow (15;16;17;18;19, dated by the upgrade-script mutation). The name appears once each in the shell, the twin and the ledger. - Guards:
test_compare_to_bash.pyandtest_docs_style.pypass 95 of 95, withdocs_stylegrading one-for-one again. - Content: outside the bookkeeping, it's unchanged from the approved content. The census (7146 / 4187 / 2959) matches the budget.
It conflicts with main now that my chain is in (4c511f38), so it goes into your restate after #1670, as agreed. I'll re-verify the restated head the same way.
🤖 Generated with Claude Code
…ostgreSQL's casts (#1706) Item 2 of #1706, decided there as option (a). The reader skipped the TimestampType's isAdjustedToUTC flag and returned the raw microseconds for either target type. In a New York session a naive (wall-time) column read into timestamptz came back as 08:00-04 instead of 12:00-04, and an adjusted column read into timestamp kept its UTC wall time instead of 08:00. The reader now keeps the flag (the legacy TIMESTAMP_* converted types are defined as adjusted) and, in those two mixed cases only, converts as timestamp_timestamptz and timestamptz_timestamp do, in the session zone. It is written from timestamp2tm, DetermineTimeZoneOffset and tm2timestamp, so it is the same on every major: PG19 renamed the exported helper, and PG15-18 export none for timestamptz -> timestamp. Same-kind reads, and any read in a UTC session, are unchanged. A wall time is not monotonic in its instant across a spring-forward gap: in New York on 2024-03-10, 02:00, 02:30 and 03:00 become 07:00Z, 07:30Z and 07:00Z. Converted row-group statistics need not bound the converted rows, so the foreign table no longer skips row groups of a column read this way. Measured: with skipping left on, `t > '07:15Z'` over such a group returned 0 rows instead of 1. The Iceberg foreign table's year(), month(), day() and hour() pruning compared a constant with partition cells the writer computed in the source field's own kind, while the reader now converts a mixed-kind column's rows. PgColumnarIcebergTemporalMap now leaves out a field whose Iceberg source type is the other timestamp kind than its column, so nothing prunes on it. Measured on PG17 before the guard, in New York: byhour declared timestamptz with `ts >= '2021-03-01 06:00+00'` returned no rows where iceberg_scan returned 2,3, and byhour_tz declared timestamp with `tt <= '2021-02-28 20:00'` returned none where it returned 1,2. #1707 (merged) is a prerequisite: with the reader honouring the flag and the old exporter marking timestamp adjusted, a timestamp exported and re-imported in a New York session came back 08:00 (measured). An arm pins that round trip. New suite test/parquet_timestamp_zone.sh and its twin, 16 checks, including the naive file read in a second zone (Tokyo), the repeated hour of the 2024-11-03 fall-back, and test/fixtures/parquet/legacy_timestamp_micros.parquet, written by main's exporter before #1707 (0c5e924) with only the TIMESTAMP_MICROS converted type. Two arms in test/iceberg_fdw.sh and its twin. docs/user-guide.md states the rule; CHANGELOG under Changed. Measured on PG17: - Red, the head before the Iceberg guard: both new iceberg_fdw checks, in shell and twin ("got [] want [2,3]", "got [] want [1,2]"). - Mutants, the same names in shell and twin: the flag ignored (6), no instant-to-wall shift (2), skipping on converted stats (1), main's exporter before #1707 (the round trip, 1), the conversion pinned to New York (the Tokyo pair, 2), legacy converted types read as naive (the legacy pair, 2), the zone offset taken at the wall time read as UTC (the fall-back hour and the two gap checks, 3), no Iceberg kind guard (2). - Green: parquet_timestamp_zone 16/16 and iceberg_fdw 76/76, shell; 16/16 and 80/80, twin; on each of PG15 to PG19. - Without pyarrow the twin declines by the shell's skip name. - docs_style 53/53, harness_selftest 1248/1248, shellcheck clean. Ledger: 6951 rows, 2811 dated by the mutations and 4140 never. suites_not_covered 75 -> 75 (a new suite, registered and covered together; iceberg_fdw is not yet seeded, so its two new checks add no rows), cluster_tests 3222 -> 3240, TESTS.md section 296. The ledger gate, guards (804 passed), name grading and the self-test pass over 9ab6a4c. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e operator family (#1712) The foreign table's group-exclusion check refused any constant whose type was not the column's. A bare integer literal is int4, so the most ordinary filter on a bigint column, `WHERE id > 150000`, read every row group; only `150000::int8` skipped. Answers were correct; reads were not saved. The check now compares the statistics with the constant through the operator family's comparison function for (column type, constant type), as the native zone-map path already did (OffgridwithJD's measurement on #1712). A family with no such function means no skip. Two details the old code would have got wrong for a cross-type constant: the NaN check read the constant as the column's float type (it now reads it by its own type), and equality called the comparison with the constant first (the column's value is now always the first argument). New suite test/parquet_skip_cross_type.sh and its twin, 9 checks, over a 200,000-row file in 4 row groups: int4 constants on an int8 column (>, =, and on the left), a negative float4 constant on a float8 column, the answers against the same-type query, and a float4 NaN that must still find the NaN row its group's statistics leave out. parquet_export_stats measured the old refusal in six arms ("a cross-type constant skips nothing", and five like it). Those assertions are now wrong by design: each is renamed for what it asserts, the skip its same-type twin gets, keeps its ledger row, and is re-dated by the pre-#1712 reader, which fails exactly those six in both harnesses. Three soundness arms are added for the changed predicates that had none ([i8 < 5::int], [i8 < 5], [f4 < 0.4]); every oracle arm passes. docs/limitations.md states the new rule. Measured on PG17: - Red: the pre-#1712 reader fails the four cross-type skip arms of the new suite, in shell and twin. - Green: 9/9 shell and twin on each of PG15 to PG19; parquet_export_stats 165/165 shell and twin on each of PG15 to PG19. - Mutants, the same names in shell and twin: the comparison called with the constant first (4, the same-type control among them); the column type's own function used for a constant of another type (the negative float4 arm); the NaN constant read as the column's type (the NaN arm). - 47 parquet, iceberg and arrow suites on PG17: only parquet_export_stats's six refusal arms failed, before they were rewritten; 1044 checks. - docs_style passes. Guards 476 passed. cluster_tests 2763 -> 2775 (collected 2775). Ledger 6180 + 12 = 6192 rows, 3886 -> 3892 never, 2294 -> 2300 dated; the gate passes, ceiling 102. - Rebased onto #1736 at a93f14b, the registry re-derived there: cluster_tests 3240 -> 3252 (collected 3252). Ledger 6951 + 12 = 6963 rows, 4140 -> 4146 never, 2811 -> 2817 dated. The gate is run on the commit after this one. Stacked on #1736 (and #1707), which touch the same function. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…amptz constant (#1712) OffgridwithJD's review of #1737 measured a wrong answer. For a timestamp column and a timestamptz constant, timestamp_cmp_timestamptz turns each statistic, a wall time, into an instant in the session zone, and that is not monotonic across a spring-forward gap. In New York a row group holding 2024-03-10 02:00, 02:30 and 03:00 has a converted max of 07:00Z but holds 02:30, which is 07:30Z. So `ts > '2024-03-10 07:15+00'::timestamptz` skipped the group and returned no row; a heap copy returns row 1. The same held for >= 07:15Z and = 07:30Z. The group-exclusion check now refuses that pair before choosing the comparison function. A timestamp constant on a timestamp column still skips, and a timestamptz column with a timestamp constant is unchanged. docs/limitations.md and the CHANGELOG entry say so. parquet_skip_cross_type and its twin gain 7 checks over a naive timestamp file in 2 row groups, every session in New York: the three predicates against the heap copy, a same-type control that still skips 1 group, its answer against the heap, and two premises. Measured: - Red: on the rebased head without the guard, PG17, the >, >= and = arms fail by the same names in shell (13 passed + 3 failed = 16) and twin (3 failed, 13 passed), each "got none want 1". - Mutant: deleting the guard line reddens the same three names in both harnesses, which dates their ledger rows. - Green: parquet_skip_cross_type 16/16 and parquet_export_stats 165/165, shell and twin, on each of PG15 to PG19. parquet_timestamp_zone 16/16 shell and twin on PG17. - Guards 804 passed. docs_style passes. cluster_tests 3252 -> 3259 (collected 3259). Ledger 6963 + 7 = 6970 rows, 4146 -> 4150 never, 2817 -> 2820 dated; the gate passes against origin/main, ceiling 75. compare_to_bash: every bash property is covered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er collide (#1742) A twin that starts its own S3 or HTTP fixture server takes the port from pick_port(slot) in a module fixture. Under -n, a module's tests are split across workers, so every worker runs that fixture. The port depended on the slot only, so two workers probed the same free port at the same moment and the second bind failed with "Address already in use" (#1635, #1714, #1721). CI runs the cluster files serially, so CI stayed green; the guard job and developers run -n. pick_port now starts each worker in its own block of 64 ports (WORKER_STRIDE), with the slot as an offset inside it. The worker comes from PYTEST_XDIST_WORKER, so no fixture changes. Slot 0 is the worker's own cluster, which make_cluster now asks for through the same function. A slot that does not fit in a block is refused. The walk on a busy port, the AUX band and the ephemeral-floor contract are unchanged. test_runshape.py gains test_two_workers_taking_a_fixture_port_do_not_collide: an inner -n 2 run where each worker takes pick_port(27), waits until the other has a port, then binds it. On main it is red: "the two workers were given two different ports: got 1 want 2", and the inner bind fails with [Errno 98] Address already in use. With the fix it is green. Measured on PG17 (a copy of the prefix): - test_iceberg_objstore.py under -n 2: main 3 of 3 red ("premise: sigv4 fixture server is up: got '0' want '1'"; "Connection refused"); fixed 16 passed 3 of 3, and 16 passed serially. - test_objstore_listing.py from #1714 under -n 2: as is, 13 failed ("the private cluster did not start"); with this pgc_cluster.py, 15 passed 3 of 3 and serially. - test_connection.py and test_hardening.py under -n 2: 20 passed. guard_tests 476 -> 477, by collection over NO_CLUSTER; TESTS.md section 10 gains a row. The guards (477), test_harness_deps.py and test_capability_decline.py with --pg-config pass over 21182d0. Review (OffgridwithJD): a 64-port block holds slots 0 to 31, and main's twins already ask for 32 to 35 (the stack for up to 41), so slot 32 raised at fixture time: test_iceberg_rest.py "14 errors", ValueError "slot 32 does not fit in a worker's block of 64 ports". WORKER_STRIDE is now 96 (slots 0 to 47; the AUX band's 2000 ports still give 20 workers). Two guards keep the stride and the corpus from drifting apart, red first on the 64 stride: every literal pick_port slot fits a worker's block (it named the 32-35 files), and the corpus's highest slot (35) gets a port in the band. Green: test_runshape.py 18 passed; the five twins that errored pass serially (14, 11, 29, 10, 8); iceberg_rest + iceberg_objstore under -n 2, 30 passed; guards 807 passed on main 9ab6a4c (guard_tests 804 -> 807). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…le, pinned reader, and a crash no longer passes as a refusal (#1341) test/pytest/test_parquet_export.py ports all 14 checks of test/parquet_export.sh by name. Five kinds of shell check could pass with nothing measured, or vanish; all are fixed in both twins. - "reject non-columnar table" and "reject unsupported type" passed on any error. With the columnar check removed, exporting a heap failed on "unsupported columnar format version" and passed; with the type refusal formatting the typmod, it failed on "cache lookup failed" and passed. Each refusal now needs its own message. - "parquet values match heap oracle" and "extended values match heap oracle" agreed on two empty readings: with the generator's rows never inserted, both passed. They now need the generator's ids on both sides and the file's row count. - "duckdb non-null count(b)" compared DuckDB's count with t_col, the table under test: with half of t_col deleted before the export, it passed. It is now held to the generator's 80002, by check_num. - Without the duckdb CLI the shell left its four DuckDB checks out without a word (10 = 10). It now skips them by name (10 passed + 4 skipped = 14). A skip, not check_unrunnable: the suites job installs no DuckDB CLI, and an INCOMPLETE suite fails its major there. DuckDB in the twin, as decided on #1341 (option 1 with option 2's mechanism): the duckdb Python package is pinned at 1.5.6 in requirements-test.txt; duckdb joins pyarrow in DECLINABLE_CAPABILITIES, held by four new tests in test_capability_decline.py, written red first; and the cluster job sets PGC_REQUIRE=pyarrow,duckdb. The twin reaches duckdb only through require_module, under the shell's check names. Measured, PG17, shell and twin: - duckdb absent: the four DuckDB tests decline by name and the run is green (10 pass + 4 declined); with PGC_REQUIRE=duckdb the same four fail. - the columnar check removed, and the type refusal formatting the typmod: the refusal red in both; main's shell passed 14 of 14. - the generator's rows never inserted: 8 red in both; main's shell 5. - half of t_col deleted: 4 red in both; main's shell 3. - the type check removed (the backend aborts): the refusal red in both, with the same 5 collateral reds in both. - nine more mutations of src/columnar_parquet.c: each red set identical in both twins and in main's shell. DECIMAL written little-endian and a negative int4 written as null are red in both readers, pyarrow and DuckDB; row-group num_rows one high is red in DuckDB only. - clean: 14 of 14 on PG15 to PG19 in both twins. Ledger: 14 rows, 14 dated by the 11 mutations and 0 never. suites_not_covered 75 -> 74, cluster_tests 3222 -> 3236, guard_tests 804 -> 808, TESTS.md section 296. The ledger gate, guards (808), name grading and the self-test pass over 4adb2e7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ails no longer reads as a fast one (#1341) Ports test/planner_choice_quality.sh to test/pytest/test_planner_choice_quality.py, all 11 checks by the shell's name, one test per check, on a private database with serial planning as the shell's cluster runs. Each arm's EXPLAIN, warming run and timed run share one session, so the plan named is the plan timed. Two holes in the shell, each measured on PG17 against main and fixed in both twins: - psql prints "Time:" after a statement that errored, and run_plan only looked for a timeout. So a chosen plan that raised an error was read as a fast plan. With PgColumnarBeginCustomScan raising at execution, or PgColumnarBeginGroupAggScan, main's shell PASSED every check (the grouped query "chose Custom Scan=1.911ms", 0.01x). run_plan now reads psql's exit status under ON_ERROR_STOP, and tells the statement-timeout cancel apart by its own message. A new check, "[$label] the chosen plan ran to completion", fails by name; a forced alternative that fails fails the ratio check as "nothing to compare" instead of standing in as the fastest plan (main read it as 15.94x over the bound). - The ratio check's name carried the bound and the node that won the comparison, so it was "... alternative (Index Scan)" when green and "... alternative (Custom Scan (PgColumnarScan))" when red: a red no green run had named. The names now carry only the query's label, and the values are in the display line. "forcing produced a different plan" loses its premise prefix (#1339): with pgcolumnar.enable_custom_scan ignored by the planner, it is the check that goes red. PGC_SKIP_TIMING: CI's suites job sets it, and run_all_versions.sh does not run the suite at all under it (is_timing_suite), which is why CI reports it skipped. Run directly under the flag, the shell builds 20,000 rows, runs the plan-shape checks and records the two measured checks per query as SKIP. The twin reads the same flag: it builds the same fixture, and declares the same two checks per query unrunnable under the shell's names, so the session ends INCOMPLETE (67), never green. Five mutations on PG17, each reddening the same names in shell and twin: scan100x (refined scan cost x100, the planner picks the index scan; 2 ratio checks, 23.3x-25.4x over three shell runs and 23.6x-36.7x over three twin runs), scanerrors 2, fetcherrors 2, gucignored 2, groupaggerrors 2. Clean, the ratio is 0.02x-0.05x on every run. 11/11 in shell and twin on each of 15-19. Ledger: 11 rows, 6 dated by the 5 mutations and 5 never. suites_not_covered 75 -> 74, cluster_tests 3222 -> 3233, TESTS.md section 296. The ledger gate, guards (804), name grading and the self-test pass over 4adb2e7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s left open (#1743) A worker of parallel_export_parquet learns its multipart upload id only from the answer to CreateMultipartUpload (POST ?uploads), and the store creates the upload when the request arrives. A worker that ended while it waited for that answer left an upload open that nothing could abort. #1727's exit callback (in this base) aborts an upload a terminated worker holds the id of; it cannot help a worker that never got the id. The dispatcher's cleanup now lists the uploads under the export's prefix (ListMultipartUploads) and aborts each one whose key is exactly one of the export's part names, part-0000.parquet to part-(nkeys-1).parquet. Any other key under the prefix is left alone. - On a cancel or other error the aborts run inside #1744's PgColumnarCleanupAndRethrow, in the cleanup callback after pexport_cleanup. The helper has copied the handled error out and emptied the stack, so a second cancel that lands in a part DELETE cuts short only that DELETE: the aborts still run and the first cancel is re-thrown. They also run after a worker failed (for example, the workers were terminated). - Interrupts are held only around bounded waits: 5 s on a timed latch for the terminated workers to stop, then 10 s for the listing and aborts. - New module entries list_uploads and abort_upload, which take a timeout that sets a deadline on the handle; ABI 5 -> 6. - os_wait: this builds on #1727's WL_TIMEOUT (4dc63aa, in this base through #1744's stack, not on main). It keeps WL_TIMEOUT for every wait and cuts the slice to the time left when a handle has a deadline. The first version's comment "os_wait passes no WL_TIMEOUT" is gone; this hunk depends on #1727 landing. - The fixture server already wrote __open_uploads__ (#1721) and had __delete_delay__ (#1744). One copy of each is kept; the __open_uploads__ writer is the module function _write_open_uploads, which --seed-upload also uses. Review of the first version (80ee33e): a second cancel during pexport_remove_outputs' part DELETEs emptied the error stack (#1741), the first version's outer PG_CATCH then raised "errstart was not called", and the aborts never ran. That outer PG_TRY, its copy-flush-rethrow helper and pexport_spawn_and_wait are removed. Test: new suite objstore_export_open_uploads and its twin, 30 checks each, identical names. The fixture server gains ListMultipartUploads, delay hooks on POST ?uploads, part PUTs and the listing, and --seed-upload. Five arms: cancel while parts are sent; cancel while every CreateMultipartUpload is held; the workers terminated there; cancel there, then cancel again once the first part DELETE has arrived (__delete_delay__ 3 s); and cancel there while the listing is held. The double-cancel arm was red first on the rebased first version, PG17, shell and twin alike: "XX000: errstart was not called", one more errstart line in the server log, and 4 uploads left open. With the rework: 30/30 on PG15-19, shell and twin. Ledger: 30 rows, 12 dated by four mutations that redden the same names in both twins on PG17 (no listing; every listed key aborted; the part match off by one; the cleanup run with the handled error on the stack), 18 never. "parts: no upload of this export is left open" is never: on this base #1727 also closes it, so no single mutation reddens it. never 4488 -> 4506, dated 3260 -> 3272, rows 7748 -> 7778; suites_not_covered stays 34; cluster_tests 4027 -> 4057; TESTS.md section 338. Restated onto main 4500efd, stacked on #1752. main's #1745 added a test named test_double_cancel_reports_the_first_cancel to test_parallel_flush_optin.py, so the corpus defined that name twice and two guards in test_docs_cover_the_corpus.py failed. This twin's test is renamed test_double_cancel_reports_the_exports_own_cancel, with its TESTS.md row; the check name it records is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e able to fail (#1339) Each finding was checked red-first on PG17: the mutation was applied to the tree at main, and main's shell suite and pytest twin both stayed green. After the fix, the same mutation reddens the named check in both twins. #1339 test_native_index_fetch_stripe_cost.py:91 (inaccurate name). "the index-fetch cost responds to the per-table stripe_row_limit (c1 is a number)" read one cost, so it could not see a response. Renamed in both twins to "the index-fetch cost is a number of at least 1". The shell twin now asks for >= 1, as the pytest twin did; it asked only for digits. Mutation: the penalised path's total cost set to 0 (columnar_customscan.c). Main: shell green ("0.00" is digits), twin red. Fixed: both red on the new name. #1339 test_native_reclaim_frag.py:102 (weak). "never larger" stayed green with the split on reuse switched off (`if (pgcolumnar_reclaim_coalesce)` around the remnant insert made `if (false)`, columnar_metadata.c): the sizes stayed 262144 and 286720. New check in both twins: "coalesce on: reuse splits an oversized freed range, so no byte between ranges is lost". It lays out the live groups and the free ranges by offset, and asks for no gaps. Main: green in both. Fixed: red in both, with "1 gaps of 122520 bytes". #1339 test_objstore_endpoint_userinfo.py:101 (weak). The check looked for the word "endpoint", which is in the message's own text. Mutation: errmsg quotes `url` instead of `ep`. Main: 5 passed. Fixed: the check asks for the quoted endpoint and no s3:// URL, and goes red for both endpoints. #1339 test_objstore_endpoint_userinfo.py:120 (weak). "no region is configured" was assumed. Mutation: AWS_REGION set in the server environment, and the endpoint guard moved below the region demand. Main: 5 passed. New check: "no region is configured: a clean endpoint here is refused for want of one". Fixed: red on that name. No shell twin. #1339 test_parallel_scan_cost.py:73 (twin mismatch). The pytest twin took any custom scan; the shell twin took only PgColumnarScan. The pytest twin now checks "Custom Plan Provider". Mutation: the scan's CustomScanMethods CustomName changed to PgColumnarScanX. Main: shell red, twin green. Fixed: both red on "the serial plan is a columnar scan". The twin stops at that first failure, so "the parallel plan is a columnar scan" and "the leader-on plan is still a parallel columnar scan" go red by name in the shell twin only. #1339 test_parallel_scan_cost.py:83 (mislabelled). Five checks lose their `premise: ` prefix in both twins: the serial, parallel and leader-on "columnar scan" checks, "has Gather" and "uses two workers". A one-line change reddens each one: the CustomName above; the partial path planned with parallel_workers = 1 ("has Gather" red in both twins); and with workers + 1 ("uses two workers" red in both, got 3). #1339 test_partition_lifecycle.py:77 (weak, NULL halves only). No arm called partition_create_ahead with a NULL width or lead. Mutation: the guard without `width IS NULL` and `ahead IS NULL` (pgcolumnar--1.0-alpha5.sql). Main: green in both twins. New check in both twins: "a NULL width or a NULL lead is refused before any DDL". Fixed: red in both, got "ok: 0|ok: 0|0". #1339 test_pgxn_metadata.py:117 (weak). The check accepted any shipped script. Mutation: META.json names pgcolumnar--1.0-alpha4--1.0-alpha5.sql. Main: green, and green in docs_style.sh too. New check in the pytest file and in docs_style.sh: "META.json names the base install script of the version VERSION holds". Fixed: red in both. Counts: check_ledger.tsv rows 6149 + 1 = 6150, never 3878 - 5 = 3873, dated 2271 + 6 = 2277. native_index_fetch_stripe_cost, native_reclaim_frag and docs_style have no ledger rows. Test collection does not change, so expected_tests.txt does not change. Gates: the four touched shell suites and six pytest files are clean on PG15, 16, 17, 18 and 19 (50 runs). docs_style.sh: PASSED. Guards: 476 passed, 1660 pass + 0 fail. compare_to_bash: "every bash property is covered" for all four pairs. Ledger gate (PG16 and PG18 logs, each suite): census 3873 agrees, ceiling 103 -> 103. Restated onto main 9ab6a4c. docs_style.sh gained a pytest twin (#1341) after this commit was written, so the twin now carries the same check by the same name: test_meta_json_names_the_base_script_of_the_version. META.json naming pgcolumnar--1.0-alpha4--1.0-alpha5.sql reddens it (1 failed, 53 passed); the tree passes (54 passed). guard_tests 804 -> 805; TESTS.md lists the test. Restated again onto main c7f0de4, with the ledger row OffgridwithJD asked for: docs_style "META.json names the base install script of the version VERSION holds", 15;16;17;18;19, dated 2026-10-22 by META.json naming the alpha4 -> alpha5 upgrade script. Census on this base: rows 7144 + 2 = 7146, never 4192 - 5 = 4187, dated 2952 + 7 = 2959. guard_tests 806 -> 807 (main already counts the two #1735 added). Guards: 807 passed. parallel_scan_cost 13/13, partition_lifecycle 65/65 and docs_style 54/54 on PG16 and PG18; the ledger gate over those six logs exits 0, census 4187 agreeing, ceiling 69 -> 69. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f630822 to
261b29b
Compare
|
Restated onto main 4500efd as 261b29b, in one linear stack (this PR sits on #1755), so these eight merge without voiding each other. Every non-registry file carries the same change as before; the registries are re-derived on the new base, and each census agrees with a recount. Guards, the PR's own shell suites on PG16 and PG18, its twins on PG17, compare_to_bash and the ledger gate all pass at this head. Re-approval needed. |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Re-approved at 261b29bf, restated onto main 4500efdd in the linear stack. Outside the ledger, the budget, expected_tests and TESTS.md, the commit's diff matches the approved f6308222. The tsv is sorted, and its census (8072/4566/3506 rows/never/dated) matches the budget.
🤖 Generated with Claude Code
@OffgridwithJD, this fixes eight #1339 findings in six test files whose checks read product behaviour. Four files have shell twins.
test_pgxn_metadata.pyhas none, butdocs_style.shcarries the same META.json checks, so it gets the same new check.Each mutation was applied to the tree at
origin/main, then to this branch, on PG17. "Main" meansorigin/main's test files and "fixed" means this branch's. The pytest names come from the record dumper. Pytest assertions here are fatal, so a twin reports only its first failing check.Findings
test_native_index_fetch_stripe_cost.py:91: the name claimed a response to the option, but the check reads one costcolumnar_customscan.c:p->total_cost += add;changed top->total_cost = 0.0;the index-fetch cost responds to ... (c1 is a number)the index-fetch cost is a number of at least 1R = pgcolumnar_written_stripe_row_limit(relid)changed to the session GUCchanging the per-table stripe_row_limit changes the estimated costgoes redtest_native_reclaim_frag.py:102: "never larger" does not see the splitcolumnar_metadata.c:1153:if (pgcolumnar_reclaim_coalesce)changed toif (false)coalesce on: reuse splits an oversized freed range, so no byte between ranges is lost(got1 gaps of 122520 bytes)test_objstore_endpoint_userinfo.py:101: "endpoint" is in the message's own textcolumnar_objstore_module.c:1439: errmsg quotesurl, notepand it names the endpoint rather than the s3:// URL, for http://u:p@127.0.0.1:1and..., for http://user@127.0.0.1:1test_objstore_endpoint_userinfo.py:120: "no region is configured" was assumedAWS_REGION=us-east-1in the server environment, and the endpoint guard moved below the region blockno region is configured: a clean endpoint here is refused for want of onetest_parallel_scan_cost.py:73: the pytest twin took any custom scancolumnar_customscan.c:174:CustomScanMethodsCustomNamePgColumnarScanchanged toPgColumnarScanXpremise: the serial plan is a columnar scan) / greenthe serial plan is a columnar scantest_parallel_scan_cost.py:83:premise:on checks that product code decidescolumnar_customscan.c:3314:parallel_workers = workerschanged to= 1premise: the parallel plan has Gatherthe parallel plan has Gatherparallel_workers = workers + 1premise: the parallel plan uses two workers(got 3)the parallel plan uses two workerstest_partition_lifecycle.py:77, the NULL halves onlypgcolumnar--1.0-alpha5.sql:2092: guard withoutwidth IS NULLandahead IS NULLa NULL width or a NULL lead is refused before any DDL(gotok: 0|ok: 0|0)test_pgxn_metadata.py:117: any shipped script passedMETA.json:filenamespgcolumnar--1.0-alpha4--1.0-alpha5.sqldocs_style.shgreen / 4 passeddocs_style.shred / red:META.json names the base install script of the version VERSION holdsThings you should know
:73mutation line was wrong. It namedcolumnar_customscan.c:179, theCustomExecMethodsname. That name does not reach EXPLAIN: with it changed, all 13 shell checks passed. The name EXPLAIN prints is theCustomScanMethodsname at:174, so that is the line I used.:120check now reads the server's environment. WithAWS_REGIONset and the guard where it is now, that check goes red, which is what the test's name claims. A CI leg that setsAWS_REGIONwould need this test changed.Clean runs and gates
native_index_fetch_stripe_cost7,native_reclaim_frag5,parallel_scan_cost13 andpartition_lifecycle65 passed on each major. Every new or renamed name shows PASS 5 times in each twin.docs_style.sh: PASSED.NO_CLUSTERfiles), PG17, after rebasing on f679492:476 passed,accounting: 1660 pass + 0 fail + 0 unrun = 1660.compare_to_bash.pyfor all four pairs:VERDICT: every bash property is covered.census stated 3873, ledger holds 3873: they agree,ceiling ... 103 -> 103, which does not rise.parallel_scan_costrows are renamed and dated, and onepartition_lifecyclerow is new.native_index_fetch_stripe_cost,native_reclaim_fraganddocs_stylehave no ledger rows. Test collection does not change, soexpected_tests.txtdoes not change.Re-checked by me before pushing (PG17, main f679492): finding 7, the two
IS NULL ORtests removed from the create-ahead guard: main's shell 64/64; this shell 1 failed, "a NULL width or a NULL lead is refused before any DDL: got [ok: 0|ok: 0|0]"; the twin failstest_partition_create_ahead. On finding 4's side effect: no CI leg sets AWS_REGION today (git grep AWS_REGION -- .githubfinds nothing).🤖 Generated with Claude Code