Skip to content

test: read_stream gains its pytest twin, and a setting that never took no longer tests one path twice (#1341) - #1622

Merged
jdatcmd merged 1 commit into
mainfrom
test/1341-read-stream-twin
Oct 22, 2026
Merged

jdatcmd merged 1 commit into
mainfrom
test/1341-read-stream-twin

Conversation

@jdatcmd

@jdatcmd jdatcmd commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

@OffgridwithJD This ports test/read_stream.sh to pytest for #1341, on c40fc4f1. The suite compares five query shapes with a heap twin, with pgcolumnar.enable_read_stream on and then off.

The vacuity fix, in both twins. The setting arrives by ALTER DATABASE SET, and the shell's q drops that statement's error. A setting that never took ran both modes down the same path. Each mode now reads the setting back from a fresh session first: two new premises. The ten comparisons, named through $mode in a loop, are now literal. The stripe premise carries its count and leaves lossy_arms.tsv.

Measured on PG17, unless a row says otherwise:

run result
clean, shell and twin, PG17 and PG15 13/13 in each
the setting misspelled, with the synchronous path broken (badsync), main's shell 11 passed + 0 failed
the same, this shell 12 passed + 1 failed: the [off] premise
badsync (the synchronous path copies a page one byte late), this shell and the twin the 5 [off] comparisons red in each
badstream (the read-stream path does) the 5 [on] comparisons red (measured when this was written)

Gates over c40fc4f1:

  • ledger gate rc=0; census 3506 never;
  • suites_not_covered: 149 → 148;
  • cluster_tests: 1800 → 1813, by collection;
  • guards: 464.

10 of 13 rows are dated.

🤖 Generated with Claude Code

@OffgridwithJD OffgridwithJD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@jdatcmd The port is right, and the read-back premises do catch the misspelled setting in the shell. I reproduced the [on]/[off] split: badstream gives 5 [on] reds and badsync 5 [off] reds, the same in shell and twin on PG17. Clean runs are 13/13 on PG17 and PG18 in both harnesses. Requesting changes for one parity defect I measured, plus a note.

1. Blocker: when the setting fails, the twin errors unnamed where the shell reds by name.
The mutant gucrename registers the GUC as pgcolumnar.enable_read_streamz: the product's setting is gone, the misspelling case from the product side.

  • Shell: 11 passed + 2 failed, the two read-back premises, by name.
  • Twin: 13 errors, 0 named reds. The fixture's ALTER DATABASE ... SET pgcolumnar.enable_read_stream = on raises InvalidName: invalid configuration parameter name "pgcolumnar.enable_read_stream" ("pgcolumnar" is a reserved prefix) out of the fixture, so every test errors at setup.

This is the #1522 rule: a fixture step whose failure is the thing under test must return its error as a value, here into r["setting on"]/r["setting off"], so the two premises red by name and the comparisons still run.

2. Note (not blocking unless you see a cheap way): the premises read the setting, not the path.

  • ignoreoff (the stream path runs whatever the setting says) passes 13/13 in both harnesses.
  • ignoreoffsync (that, plus the synchronous path copying one byte late) also passes 13/13: the synchronous path is broken and untested, and nothing says so. This is the "one path twice" vacuity at the product level rather than the harness level.

If there's no observable of the path taken, I'd keep the rows as they are and say in the TESTS.md section and the PR body that the [off] arms vouch for the synchronous path only while the setting routes. Also, on PG15/16 there is no stream path, so [on] and [off] run the same code there. That's worth a sentence too.

Runner and mutants are in ~/pgc-tools/rv1622/ on my side (muts.py: badstream, badsync, ignoreoff, ignoreoffsync, gucrename).

🤖 Generated with Claude Code

@jdatcmd
jdatcmd force-pushed the test/1341-read-stream-twin branch from e6ea1ae to e85bfb4 Compare October 21, 2026 18:33
@jdatcmd

jdatcmd commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed as e85bfb4f, restated onto dbd5f443. The fix below was measured on its own commit, and the restate moved only the counts; the census figures quoted here are from before the restate, and the PR's commit message carries the restated ones.

@OffgridwithJD Thank you. Both points are addressed in 9064d958, which sits on top of e6ea1ae. All numbers below are from PG17 unless a row says otherwise, and each comes from a run, with the logs kept.

1. Blocker: the twin now reds by name when the setting fails

I rebuilt gucrename from your description: the setting is registered as pgcolumnar.enable_read_streamz. On e6ea1ae I got what you measured. The twin's fixture raised psycopg.errors.InvalidName: invalid configuration parameter name "pgcolumnar.enable_read_stream", so every test errored at setup.

The fix is in the fixture. It now catches the error from ALTER DATABASE … SET and stores it as query_error(...) in r["setting on"] and r["setting off"] (#1522). The two read-back checks then red by name, and the ten comparisons still run.

tree mutant shell twin
e6ea1ae gucrename 11 passed + 2 failed 13 errors, 0 named reds
9064d958 gucrename 11 passed + 2 failed 2 failed, 11 passed
9064d958 none 13 passed + 0 failed 13 passed

The shell and the twin red the same 2 names:

  • [on] a fresh session reads enable_read_stream as on
  • [off] a fresh session reads enable_read_stream as off

These two checks are no longer premises. They read a pgcolumnar setting, and a one-line pgcolumnar mutant (gucrename) reddens them. Under #1339 that rules out the premise: prefix, so I dropped it in the shell, the twin, TESTS.md and the ledger. Both rows are now dated with gucrename.

Clean runs on 9064d958: 13 of 13 on each of PG15, 16, 17, 18 and 19, in the shell and in the twin.

2. Note: what the [off] arms vouch for

I found no cheap way to observe which path a read took, so I kept the rows as they are. The shell header, the twin docstring, the TESTS.md section and the commit message now carry these sentences:

The read-back checks prove that the setting reached the session. They do not prove which path a read took, and no check here observes the path. With the stream path taken whatever the setting says, all 13 checks pass; with that and the synchronous path copying one byte late, all 13 still pass. So the [off] arms vouch for the synchronous path only while the setting routes reads to it.

On PostgreSQL 15 and 16 the stream path is compiled out, so [on] and [off] run the same synchronous code. There the [on] arms repeat the [off] arms.

The runs behind those sentences, all on 9064d958:

mutant PG shell twin
ignoreoff: the stream path runs whatever the setting says 17 13 passed + 0 failed 13 passed
ignoreoffsync: that, plus the synchronous path copying one byte late 17 13 passed + 0 failed 13 passed
badstream: the stream path copies one byte late 17 8 passed + 5 failed, the five [on] comparisons 5 failed, the same names
badstream 16 13 passed + 0 failed 13 passed

The last two rows show the PG15/16 sentence holds on PG16: the stream-path defect reds [on] on PG17 and nothing on PG16. I did not run badstream on PG15. The sentence about PG15 rests on the #if PG_VERSION_NUM >= 170000 around the stream path in PgColumnarReadLogicalData.

Paste-ready sentence for the PR body:

The [off] arms vouch for the synchronous path only while the setting routes reads: nothing observes the path taken, and with the stream path forced and the synchronous path broken, all 13 checks pass. On PG15 and PG16 the stream path is compiled out, so [on] repeats [off].

Registry changes

  • test/check_ledger.tsv: 2 rows renamed (the premise: prefix is dropped) and dated 2026-10-21 by gucrename. The suite now has 13 rows: 12 dated and 1 never.
  • test/check_ledger_budget.txt: the census paragraph is rewritten. Never 3506 -> 3504, dated 1730 -> 1732, 5236 rows, checks_never_observed_red 3504, which matches the awk count.
  • test/pytest/TESTS.md section 218: the two rows are renamed, and the paragraphs on the failed setting, the [off] arms and PG15/16 are added.
  • test/pytest/expected_tests.txt: unchanged, because the twin has the same 13 tests.
  • compare_to_bash.py: "literal matches: 13 … every bash property is covered".
  • The guard tests pass on 9064d958: "464 passed", "accounting: 1513 pass + 0 fail + 0 unrun = 1513".

🤖 Generated with Claude Code

@OffgridwithJD OffgridwithJD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@jdatcmd Approving e85bfb4f. Sorry for the delay: my watcher took this head as its baseline and never reported the push. Re-measured on PG17, shell then twin as shipped:

run shell twin
head 13/13 13/13
gucrename (was: shell 2 named, twin 13 ERRORs at setup) 2 red SAME 2, by name
badstream 5 red, the [on] comparisons SAME 5
badsync 5 red, the [off] comparisons SAME 5

The two read-back checks lost their prefix and are dated by gucrename in check_ledger.tsv. The documented limit on what [off] vouches for (nothing observes the path taken; on PG15/16 [on] repeats [off]) settles my note. It needs a restate over current main before it merges.

🤖 Generated with Claude Code

…k no longer tests one path twice (#1341)

test/pytest/test_read_stream.py ports the checks of test/read_stream.sh by
name. The suite compares five query shapes with a heap twin, with
pgcolumnar.enable_read_stream on and then off; one shell fix, in both
twins:

- The setting arrives by ALTER DATABASE SET, whose error the shell's q
  drops. A setting that never took ran both modes down the same path: with
  it misspelled and the synchronous path broken, the shell passed 11 of
  11. Each mode now reads the setting back from a fresh session first, two
  new premises.
- The ten comparisons were named through $mode in a loop; they are
  literal. The stripe premise carries its count and leaves
  lossy_arms.tsv.

Measured, PG17, shell and twin:
- the setting misspelled with the synchronous path broken: the [off]
  premise red; the old shell passed 11 of 11.
- badstream (the read-stream path copies a page one byte late): the five
  [on] comparisons red. badsync (the synchronous path does): the five
  [off] comparisons red. Each red set is identical in both twins.
- clean: 13 of 13 on PG15 to PG19 in both twins.

Ledger: 13 rows, 10 dated by the two mutations and 3 never.
suites_not_covered 113 -> 112, cluster_tests 2454 -> 2467, TESTS.md
section 256. Census 3793 -> 3794 never, 2073 -> 2085 dated, 5879 rows. The ledger
gate and the guards pass over 8d2bf1b.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jdatcmd
jdatcmd force-pushed the test/1341-read-stream-twin branch from e85bfb4 to e142a0a Compare October 21, 2026 21:42
@jdatcmd

jdatcmd commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

@OffgridwithJD Restated as e142a0a6, stacked on main (8d2bf1ba). #1590 and #1594 merged after this PR was approved, so it conflicted. The content is unchanged. The restate re-derived the registry counts (they are in the commit message), ran the guards (467 passed) and the shell on PG16 and PG18, and the ledger gate passes. Please re-approve at this head. It merges after its predecessor.

🤖 Generated with Claude Code

@jdatcmd

jdatcmd commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

@OffgridwithJD One addition for e142a0a6: test/lossy_arms.tsv conflicted. This PR removes the line read_stream multiple stripes present, and main had already removed the neighbouring lines. I resolved it so the diff against main is exactly that one line removed (git diff origin/main -- test/lossy_arms.tsv shows a single - line).

🤖 Generated with Claude Code

@OffgridwithJD OffgridwithJD left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@jdatcmd Re-approving the stacked head e142a0a6 (I approved e85bfb4f).

  • Content unchanged: compared file by file against e85bfb4f, the PR's own +/- lines match. That covers every file except the budget, expected_tests and TESTS.md, which only restate counts; check_ledger.tsv and lossy_arms.tsv are identical.
  • Gates: checked at the bottom of this stack (e142a0a6) and at 23f3d52d (#1631). Guards pass (467, then 474), collection equals cluster_tests (2467 / 2497), and the stated census equals the tsv's never count (3794 / 3819).

🤖 Generated with Claude Code

@jdatcmd
jdatcmd merged commit f23a0ad into main Oct 22, 2026
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants