Repository navigation
Vendors the conformance corpus and runs every case under pg_regress - #8
Merged
Merged
Conversation
The corpus, not the reference's code, is the arbiter of conformance, so the case files, manifest.json, the schemas and the corpus README are copied byte for byte from uxid-ex at v2.10.0, with the repo, tag, commit and corpus_hash in conformance/SOURCE.json. The generator source under the tag's conformance/source/ is not vendored: a port does not need it to run the cases. The corpus is marked -text so no checkout converts its line endings. scripts/corpus-check.sh, POSIX sh with no jq, recomputes corpus_hash over the case files in the manifest's order and counts each file's lines against its case_count; the gate now runs it under sh. The conformance regression test loads each file with psql's \copy as CSV with quote and delimiter bytes no case contains, checks the loaded lines hash to corpus_hash, and runs all 96 cases through a runner defined in the test, one row per case in manifest order. Refs: uxpg-bem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bead: uxpg-bem
What this changes
The corpus, vendored.
conformance/holds uxid-ex's conformance corpus at the tagv2.10.0(commit57235777cb29c70f751552ce7aa20ab5fe71fb74): the five case files,manifest.json, the six files underschema/and the corpusREADME.md, each read from the tag's objects and compared withcmpagainstgit show v2.10.0:conformance/<path>(all equal, and each blob id equals the tag's). The generator source under the tag'sconformance/source/is not vendored: a port does not need it to run the cases.conformance/SOURCE.jsonrecordsrepo,tag,shaandcorpus_hash..gitattributesmarksconformance/**as-text, so no checkout converts line endings under the hash.The hash and count check.
scripts/corpus-check.shis POSIX sh using only POSIX utilities (no jq: the manifest is one line of sorted-key JSON, read withsedandtr; SHA-256 fromsha256sum,shasumoropenssl, whichever is installed). It checks thatSOURCE.jsonhas exactly its four keys and names the repo, tag and commit the script expects; that the manifest is corpus version 1 with SOURCE.json's hash and entries of exactlycase_count,fileandkind; and that each case file iscase_countlines, each ending in a newline, none empty, each with a case id starting with its kind. It then recomputescorpus_hashover the case files' bytes in the manifest's order. Any mismatch exits non-zero, and nothing rewrites a hash or a count. The gate's corpus step now runs it undershwith no fallback for a missing script, and CI'sgatejob runs the gate.The runner.
test/sql/conformance.sql(added toREGRESS) loads each file with psql's\copyinto a staging table as CSV, with quote byte 0x01 and delimiter byte 0x02. No case file contains either byte, so each line arrives whole as one text value, withclient_encodingset to UTF-8 because some lines carry non-ASCII bytes. It checks the loaded lines hash back tocorpus_hashand that each file's line count matches itscase_count. A runner defined only in the test (pg_tempfunctions; the extension script is unchanged) then runs every case, one output row per case in manifest order, with no skip list:uxid_encodewith the case's fixedrand;uxid_from;uxid_decode_atwith the clock injected at the window's first millisecond, at 1700000000000 and at its last millisecond (the corpus README's window), plusuxid_decode_errorreturning NULL;uxid_decode_at(SQLSTATE 22P02, message exactlyuxid: <reason>) anduxid_decode_error; invalid generate throughuxid_check_request(22023,uxid: <name>: ...), an absent option passed as NULL, its default;uxid_monotonic_stepwithinitial_seed,stepsandoverflow_seedhanded in as values (the overflow seed at most once, and checked as drawn exactly when the case carries one), each id throughuxid_encode, lower case.A case carrying a key the runner does not know (at the top, in its input, in its expected answer) fails with that key named. A JSON null prefix reaches the functions as SQL NULL, which they read as no prefix. The output prints 96 rows (35 encode, 12 deterministic, 18 decode, 25 invalid, 6 monotonic), every one
pass, then a tally row. A last query runs the runner on crafted lines that are not the corpus's, so the expected output pins the reason on a failing row: an unknown key in each of five places, a case id of another kind, a line that is not JSON, a wrong answer, a refusal of another name, and a null prefix (which passes).Paths
The
\copypaths are relative:make installcheckruns pg_regress, and so psql, at the top of the tree, and the test does\cd conformancebefore the loads and\cd ..after. That holds in the local gate's container copy of the tree, and in CI'sinstallcheckjobs in the pgxn/pgxn-tools container, which runmake installcheckin the checkout. The loads use COPY's older option spelling (CSV QUOTE E'\x01' DELIMITER E'\x02'), which keeps each\copyline inside the lint's line width. psql does not interpolate variables in a\copyline, so the line cannot be shortened that way.Evidence
mise run gate) green on PostgreSQL 18.6: 17 of 17 regression tests pass, sqlfluff lint clean, the corpus check printscorpus: v2.10.0 (57235777cb29c70f751552ce7aa20ab5fe71fb74), 5 case files, 96 cases, sha256:4f7572c8c1a60134b2955f02b34c82a839d0c3ab95d4218cc2df5a85eeb2bebb. The commit's tree is byte-identical to the tree that gate ran green on, so it was committed without a second gate run.sh -nand runs clean under macOS/bin/sh, under/bin/dash, and under the gate image's/bin/sh(dash). Run on a copy of the corpus with one change at a time, it exits 1 naming the fault for each of: a trailing byte, one changed case byte, a wrongcase_count, a wrongshain SOURCE.json, an extra SOURCE.json key, an extra manifest entry key, a missing case file,corpus_version2, and both hashes rewritten to the same wrong value.-- sabotage:comment. Every mutation turned the conformance test red on an assertion and was restored byte-equal: the deterministic marker (12 deterministic rows fail), the compact time's window step (decode/s-compact-guard-last-validfails), the decode refusal's SQLSTATE (16 decode-refusal rows fail), the monotonic step rule's<=(monotonic/xs-compact-overflow-clock-backfails), the CSV quote byte on one load (the hash check readsfand 35 rows fail), the runner's unknown-key check (the probe reasons go empty), and the last decode clock moved one past the window (decode/s-compact-guard-last-validfails).Earlier tests
The per-function regression files that carry corpus cases by hand (
encode,from,decode,decode_refusals,check_request,monotonic_step) stay. They pin each function's behaviour with their own sabotage notes. The runner now runs every corpus case as well, so as corpus coverage they overlap; whether any should go is left to review. Two comments that said "until the corpus runner runs them" now nameconformance.sql.Provenance
.gitattributes(conformance/** -text), the gate's corpus step inmise.toml(runs undersh, no fallback),Makefile(REGRESS), the two test comments above with their expected output, andCLAUDE.md, whose sentences about the corpus now describe the tree as it is.changelog.d/README.mdsays tests and gate changes take none.