From b52f59b9bbdbcf60317cdca09897f2eac17b20b9 Mon Sep 17 00:00:00 2001 From: "Joshua (D) Drake" <136637981+ChronicallyJD@users.noreply.github.com> Date: Wed, 9 Sep 2026 21:47:01 +0000 Subject: [PATCH 1/2] test: pin exact zone-map boundaries (#831) Co-authored-by: Cursor --- CHANGELOG.md | 9 +++ test/pytest/TESTS.md | 26 +++++++-- test/pytest/test_zonemap_boundaries.py | 78 ++++++++++++++++++++++++++ test/run_all_versions.sh | 1 + test/zonemap_boundaries.sh | 52 +++++++++++++++++ 5 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 test/pytest/test_zonemap_boundaries.py create mode 100755 test/zonemap_boundaries.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index cae5839a..901dcb5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,15 @@ true until the next version shipped. ### Added +- Exact zone-map boundary coverage now lives in matching shell and pytest tests + (#831). + + The `<=` and `>=` arms put the constant exactly at a row-group minimum or + maximum and compare returned rows with a heap twin. The `>` and `=` mirrors + assert groups removed with bloom disabled, so a conservative pruning + regression cannot hide behind a correct answer. Each of the four one-token + boundary mutations was proved to fail its corresponding assertion. + - The test harness refuses to measure a binary that was not built from the source under test. diff --git a/test/pytest/TESTS.md b/test/pytest/TESTS.md index 1b455763..72cbe0d6 100644 --- a/test/pytest/TESTS.md +++ b/test/pytest/TESTS.md @@ -4,7 +4,7 @@ Reference for anyone reading, running, or adding to `test/pytest/`. The design a the decisions behind the harness are in `design/ISSUE_432_PYTEST_HARNESS.md`. This file covers the tests themselves. -**78 tests in 6 files.** Sixty-three of them test the harness rather than the +**79 tests in 7 files.** Sixty-three of them test the harness rather than the product, and they come first, because a harness that can report a false green makes every other result in this directory worthless. @@ -32,8 +32,9 @@ behaviour, the source of that number is named. - [6. test_docs_cover_the_corpus.py: this document, checked](#6-test_docs_cover_the_corpuspy-this-document-checked) - [7. test_connection.py: the cluster and the direct connection](#7-test_connectionpy-the-cluster-and-the-direct-connection) - [8. test_native_projection.py: the ported suite](#8-test_native_projectionpy-the-ported-suite) -- [9. Adding a test](#9-adding-a-test) -- [10. Traps this corpus records](#10-traps-this-corpus-records) +- [9. test_zonemap_boundaries.py: exact boundaries](#9-test_zonemap_boundariespy-exact-boundaries) +- [10. Adding a test](#10-adding-a-test) +- [11. Traps this corpus records](#11-traps-this-corpus-records) ## 1. How to read a test in here @@ -588,7 +589,22 @@ The mutation makes `PgColumnarProjectionFanoutRow` return without writing. Each builds and installs once, and both harnesses print the `.so` md5 they measured, so an arm where the two differ is void rather than reported. -## 9. Adding a test +## 9. test_zonemap_boundaries.py: exact boundaries + +### `test_exact_zonemap_boundaries` + +Pairs with `test/zonemap_boundaries.sh`. Two monotonic 1,000-row groups put +`1001` exactly at the second group's minimum and `1000` exactly at the first +group's maximum. Heap-row comparisons pin that `<= 1001` and `>= 1000` keep +their boundary rows. Work-done counters, with bloom disabled, pin the +correctness-preserving mirrors: `> 1000` and `= 1001` each remove one group. + +The four one-token mutations from #831 make the corresponding assertion fail: +`<=` and `>=` lose one row, while `>` and `=` remain row-correct but remove no +group. This distinguishes correctness coverage from pruning-effectiveness +coverage rather than relying on incidental fixtures elsewhere in the matrix. + +## 10. Adding a test 0. **Write it twice.** Every test in this tree ships as a `.sh` suite and a pytest test **in the same change** (jd, 2026-09-09). Not ported later, not one or the @@ -615,7 +631,7 @@ an arm where the two differ is void rather than reported. failed the selftest on both majors of the matrix, which is how it was found. A new directory under `test/` inherits every rule the old ones follow. -## 10. Traps this corpus records +## 11. Traps this corpus records Recorded because each one produced a confident wrong result before it was caught, and all are the same family as the defect the layer exists to prevent. diff --git a/test/pytest/test_zonemap_boundaries.py b/test/pytest/test_zonemap_boundaries.py new file mode 100644 index 00000000..dafde360 --- /dev/null +++ b/test/pytest/test_zonemap_boundaries.py @@ -0,0 +1,78 @@ +"""Exact zone-map comparison boundaries and pruning effectiveness (#831).""" + + +def _nodes(plan): + for root in plan: + stack = [root["Plan"]] + while stack: + node = stack.pop() + yield node + stack.extend(node.get("Plans", ())) + + +def _plan(conn, qual): + with conn.cursor() as cur: + cur.execute("SET pgcolumnar.enable_bloom_filter=off") + cur.execute("SET pgcolumnar.enable_vectorization=off") + cur.execute( + "EXPLAIN (ANALYZE, FORMAT JSON, COSTS OFF, TIMING OFF, SUMMARY OFF) " + f"SELECT id FROM zb_c WHERE {qual}" + ) + return cur.fetchone()[0] + + +def _removed(plan): + return next( + node.get("Columnar Chunk Groups Removed by Filter", 0) + for node in _nodes(plan) + if "Columnar Chunk Groups Total" in node + ) + + +def _ids(conn, table, qual): + with conn.cursor() as cur: + cur.execute(f"SELECT id FROM {table} WHERE {qual} ORDER BY id") + return [row[0] for row in cur] + + +def test_exact_zonemap_boundaries(pgc_conn, expect): + with pgc_conn.cursor() as cur: + cur.execute("CREATE TABLE zb_h(id int, v int)") + cur.execute("CREATE TABLE zb_c(id int, v int) USING pgcolumnar") + cur.execute( + "SELECT pgcolumnar.set_options('zb_c', stripe_row_limit => 1000)" + ) + cur.execute("INSERT INTO zb_h SELECT g,g FROM generate_series(1,2000) g") + cur.execute("INSERT INTO zb_c SELECT * FROM zb_h") + cur.execute( + "SELECT count(*) FROM pgcolumnar.row_group " + "WHERE storage_id=pgcolumnar.get_storage_id('zb_c')" + ) + expect.num(cur.fetchone()[0], 2, "premise: fixture has two row groups") + + expect.rows( + _ids(pgc_conn, "zb_c", "v <= 1001"), + _ids(pgc_conn, "zb_h", "v <= 1001"), + "<= keeps the row at a row-group minimum", + ) + expect.num( + _removed(_plan(pgc_conn, "v <= 1001")), 0, + "premise: <= at the second-group minimum removes no group", + ) + expect.rows( + _ids(pgc_conn, "zb_c", "v >= 1000"), + _ids(pgc_conn, "zb_h", "v >= 1000"), + ">= keeps the row at a row-group maximum", + ) + expect.num( + _removed(_plan(pgc_conn, "v >= 1000")), 0, + "premise: >= at the first-group maximum removes no group", + ) + expect.num( + _removed(_plan(pgc_conn, "v > 1000")), 1, + "> excludes the group whose maximum equals the constant", + ) + expect.num( + _removed(_plan(pgc_conn, "v = 1001")), 1, + "= excludes the group lying wholly below the constant", + ) diff --git a/test/run_all_versions.sh b/test/run_all_versions.sh index b6330593..a8c951da 100755 --- a/test/run_all_versions.sh +++ b/test/run_all_versions.sh @@ -286,6 +286,7 @@ SUITES=( wal_envelope write_fsst_compressed write_minmax_fastpath + zonemap_boundaries zonemap_cost zonemap_estimate_sample) diff --git a/test/zonemap_boundaries.sh b/test/zonemap_boundaries.sh new file mode 100755 index 00000000..258634b2 --- /dev/null +++ b/test/zonemap_boundaries.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Exact zone-map comparison boundaries are intentional coverage (#831). +# +# Usage: test/zonemap_boundaries.sh [PG_CONFIG] + +set -uo pipefail +. "$(dirname "${BASH_SOURCE[0]}")/lib.sh" +pgc_setup "${1:-/usr/local/pg17/bin/pg_config}" + +psql_run "CREATE TABLE zb_h(id int, v int); + CREATE TABLE zb_c(id int, v int) USING pgcolumnar; + SELECT pgcolumnar.set_options('zb_c', stripe_row_limit => 1000); + INSERT INTO zb_h SELECT g,g FROM generate_series(1,2000) g; + INSERT INTO zb_c SELECT * FROM zb_h; + ANALYZE zb_h; ANALYZE zb_c;" >/dev/null + +check "premise: the boundary fixture has two row groups" \ + "$(q "SELECT count(*) FROM pgcolumnar.row_group + WHERE storage_id=pgcolumnar.get_storage_id('zb_c');")" "2" + +groups_removed() { + env PATH="$PGC_BINDIR:$PATH" psql -h 127.0.0.1 -p "$PGC_PORT" \ + -U postgres -d "$PGC_DB" -Atq \ + -c "SET pgcolumnar.enable_bloom_filter=off; + SET pgcolumnar.enable_vectorization=off; + EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) + SELECT id FROM zb_c WHERE $1;" 2>&1 | + sed -n 's/.*Columnar Chunk Groups Removed by Filter: \([0-9]*\).*/\1/p' | + head -1 +} + +check_text "<= keeps the row at a row-group minimum" \ + "$(pgc_set_hash "SELECT id FROM zb_c WHERE v <= 1001")" \ + "$(pgc_set_hash "SELECT id FROM zb_h WHERE v <= 1001")" +check "premise: <= at the second-group minimum removes no group" \ + "$(groups_removed 'v <= 1001')" "0" + +check_text ">= keeps the row at a row-group maximum" \ + "$(pgc_set_hash "SELECT id FROM zb_c WHERE v >= 1000")" \ + "$(pgc_set_hash "SELECT id FROM zb_h WHERE v >= 1000")" +check "premise: >= at the first-group maximum removes no group" \ + "$(groups_removed 'v >= 1000')" "0" + +# These mutations remain row-correct, so only work-done counters can see them. +check "> excludes the group whose maximum equals the constant" \ + "$(groups_removed 'v > 1000')" "1" +check "= excludes the group lying wholly below the constant" \ + "$(groups_removed 'v = 1001')" "1" + +check "backend alive" "$(q 'SELECT 1')" "1" +pgc_summary From f8e016f8379d38cb32a3f8e0f452b1afb3bf541b Mon Sep 17 00:00:00 2001 From: "Joshua (D) Drake" <136637981+ChronicallyJD@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:44:58 +0000 Subject: [PATCH 2/2] test: pin strict-less zone-map boundary Co-authored-by: Cursor --- CHANGELOG.md | 8 ++++---- test/pytest/TESTS.md | 14 ++++++++------ test/pytest/test_zonemap_boundaries.py | 4 ++++ test/zonemap_boundaries.sh | 2 ++ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 901dcb5d..d346b3a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,10 +22,10 @@ true until the next version shipped. (#831). The `<=` and `>=` arms put the constant exactly at a row-group minimum or - maximum and compare returned rows with a heap twin. The `>` and `=` mirrors - assert groups removed with bloom disabled, so a conservative pruning - regression cannot hide behind a correct answer. Each of the four one-token - boundary mutations was proved to fail its corresponding assertion. + maximum and compare returned rows with a heap twin. The `<`, `>`, and `=` + mirrors assert groups removed with bloom disabled, so a conservative pruning + regression cannot hide behind a correct answer. Each of the five one-token + strategy mutations was proved to fail its corresponding assertion. - The test harness refuses to measure a binary that was not built from the source under test. diff --git a/test/pytest/TESTS.md b/test/pytest/TESTS.md index 72cbe0d6..0cd94c2b 100644 --- a/test/pytest/TESTS.md +++ b/test/pytest/TESTS.md @@ -597,12 +597,14 @@ Pairs with `test/zonemap_boundaries.sh`. Two monotonic 1,000-row groups put `1001` exactly at the second group's minimum and `1000` exactly at the first group's maximum. Heap-row comparisons pin that `<= 1001` and `>= 1000` keep their boundary rows. Work-done counters, with bloom disabled, pin the -correctness-preserving mirrors: `> 1000` and `= 1001` each remove one group. - -The four one-token mutations from #831 make the corresponding assertion fail: -`<=` and `>=` lose one row, while `>` and `=` remain row-correct but remove no -group. This distinguishes correctness coverage from pruning-effectiveness -coverage rather than relying on incidental fixtures elsewhere in the matrix. +correctness-preserving cases: `< 1001`, `> 1000`, and `= 1001` each remove one +group. + +The five one-token strategy mutations make the corresponding assertion fail: +`<=` and `>=` lose one row, while `<`, `>`, and `=` remain row-correct but +remove no group. This distinguishes correctness coverage from +pruning-effectiveness coverage rather than relying on incidental fixtures +elsewhere in the matrix. ## 10. Adding a test diff --git a/test/pytest/test_zonemap_boundaries.py b/test/pytest/test_zonemap_boundaries.py index dafde360..03c2f53d 100644 --- a/test/pytest/test_zonemap_boundaries.py +++ b/test/pytest/test_zonemap_boundaries.py @@ -50,6 +50,10 @@ def test_exact_zonemap_boundaries(pgc_conn, expect): ) expect.num(cur.fetchone()[0], 2, "premise: fixture has two row groups") + expect.num( + _removed(_plan(pgc_conn, "v < 1001")), 1, + "< excludes the group whose minimum equals the constant", + ) expect.rows( _ids(pgc_conn, "zb_c", "v <= 1001"), _ids(pgc_conn, "zb_h", "v <= 1001"), diff --git a/test/zonemap_boundaries.sh b/test/zonemap_boundaries.sh index 258634b2..ea1693ab 100755 --- a/test/zonemap_boundaries.sh +++ b/test/zonemap_boundaries.sh @@ -30,6 +30,8 @@ groups_removed() { head -1 } +check "< excludes the group whose minimum equals the constant" \ + "$(groups_removed 'v < 1001')" "1" check_text "<= keeps the row at a row-group minimum" \ "$(pgc_set_hash "SELECT id FROM zb_c WHERE v <= 1001")" \ "$(pgc_set_hash "SELECT id FROM zb_h WHERE v <= 1001")"