Repository navigation
test(goldens): behaviour goldens over every corpus and dialect [W0-02] - #915
Conversation
Pin observable output over the whole internal/benchcorpus corpus so
performance work cannot change behaviour silently:
- tokens: full token dump (type, value, span, quote, Long, Word) under
all 11 accepted dialects, bigquery and redshift included
- parse: ParseWithDialect SQL() or error code/location/hint/message,
every AST models.Location (node Pos, statement starts/ends, comment
spans) via a reflective outline, and ValidateWithDialect, x 11 dialects
- format: FormatWithDialect (2 option sets) and FormatASTChecked
compact/readable/lower/no-dialect renderings
- fingerprint: Normalize and Fingerprint values
- lint: LintWithDialect (own dialect) and Lint violations
- security: ScanSQL and Scan (AST) findings
- transpile: Transpile to all 9 matrix dialects, identity included
- lsp: diagnostics, decoded semantic tokens and document symbols for a
fixed 30 KB-per-dialect document set
Golden files hold one 64-bit hash per corpus file and column ("=" when
equal to the left column), 168 KB in total. -update regenerates them;
-goldens.dump/-goldens.base and scripts/goldens-diff.sh (task
goldens:diff) print the first differing statements with input and a
line diff against a base revision. Also add a test that keeps the
unsynchronised global spanInfo map unwritten by library code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Claude encountered an error after 0s —— View job I'll analyze this and get back to you. |
…goldens Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
…nd comments [W0-02] Address review of #915: - parse golden: new "default" column with gosqlx.Parse (SQL(), positions, wrapped ErrTokenize/ErrSyntax errors), parser.Validate and gosqlx.Validate, the dialect-free paths that wave 1 optimises. Dialect columns unchanged. - tokens golden: also run TokenizeString and tokscratch.String/Bytes and render tkz.Comments; a path section is appended only where it differs from the public Tokenize dump. - span invariant: resolve the ast import by path (aliases, dot imports), flag method values and any spanInfo write outside SetSpan; add a detector self-test. - rename the shared flag -update to -goldens.update to avoid "flag redefined" clashes; task goldens:update unchanged. - formatter and LSP goldens: run ParseWithDialect and NewServer under goldens.Safe so a panic is a golden diff, not a crashed binary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2
|
Claude finished @ajitpratap0's task in 29s —— View job Review of PR #915: behaviour goldens [W0-02]I read Overall: the design is sound. One hash per file and column keeps the committed data to about 168 KB. The Observations
SecurityNothing of concern. The change adds tests, test data and a script. The script uses VerdictI found no blocking issues. Items 1 and 2 are the ones I'd fix before merging, and both are small. The rest are optional. |
|
Claude finished @ajitpratap0's task in 14s —— View job Review of PR #915: behaviour goldens [W0-02]I re-read Overall: the design is sound and I found nothing blocking. It adds only tests, test data, a script and Taskfile tasks, so there is no library risk. The Worth fixing before merge (both small)
Optional
SecurityNothing of concern. The script uses |
Summary
W0-02 of the perf plan, plus critique item 15 (positions, Normalize/Fingerprint and LSP coverage). The behaviour goldens freeze observable output over the whole
internal/benchcorpuscorpus (W0-01: 2,999 statements in 254 files: every golden exceptlsphas 254 rows, the 256 MANIFEST entries minusportable_queries.txtandknown_failures.txt). Wave-1+ perf PRs can then prove "no behaviour change" (AC-STD 2) or list each intended diff.testdata/goldens/)tokenspkg/sql/tokenizerTestGoldenTokensTokenize([]byte): type, value, span, quote, Long, Word (nil-ness included); every captured comment (tkz.Comments).TokenizeString,tokscratch.String(the pathgosqlx.Parse,ParseWithDialectandValidateuse) andtokscratch.Bytesalso run; astring:/scratch:/scratch_bytes:section is appended to the cell only where that path differs from the public dump (none today)parsepkg/sql/parserTestGoldenParsedefault)ParseWithDialect→SQL(), or error code + location + hint + message; everymodels.Locationin the AST (nodePos,StatementStarts/Ends, comment spans), from a reflective outline walk;ValidateWithDialectverdict.defaultcolumn: the dialect-free entry points, which run separate code:gosqlx.Parse(same SQL()/positions, errors with itsErrTokenize/ErrSyntaxwrapping), theparser.Validatefast path andgosqlx.Validateformatpkg/formatterTestGoldenFormatFormatWithDialect(default and upper/indent-4/semicolon),FormatASTCheckedcompact / readable / lower / compact-no-dialectfingerprintpkg/fingerprintTestGoldenFingerprintNormalize,Fingerprintvalueslintpkg/linterTestGoldenLintLintWithDialect(own dialect) andLintsecuritypkg/sql/securityTestGoldenSecurityScanSQLandScan(AST) findings and countstranspilepkg/transpilerTestGoldenTranspileTranspilefrom the corpus dialect to every dialect of the 9x9 rule matrix, identity included (the corpora cover all 9 sources, so all 81 pairs run)lsppkg/lspTestGoldenLSPCompact format. Each line is
<corpus file> <statements> <64-bit hash per column>. A cell hash covers the full output of every statement in the file, in order.=means "same hash as the column to the left", so dialects that agree collapse and the ones that differ stand out. All eight files total 173 KB.Readable diff mode.
task goldens:diff BASE=origin/main(scripts/goldens-diff.sh) dumps the base revision's outputs from a temporary worktree (-goldens.dump). It then runs the working tree against that dump (-goldens.base) and prints, for each changed cell, the first differing statements: the input SQL and a line diff of the output (examples below).Flags and tasks:
-goldens.updateregenerates the goldens (task goldens:update). The flag is namespaced like-goldens.dump/-goldens.baseso it cannot clash with a package's own-updateflag.task goldensruns them.MANIFEST.sha256, so a corpus edit cannot pass for a behaviour change.Robustness:
-race.PANIC: <value>output, without a stack, which would be nondeterministic. Every library call runs undergoldens.Safe, including the formatter golden'sParseWithDialectand the LSP golden'sNewServer.Also added (critique 15):
pkg/sql/ast/span_invariant_test.gofails if any non-test code can write the unsynchronised globalspanInfomap, which would be a race under concurrent use: any reference toSetSpan(call or method value), with the import resolved by path so aliased and dot imports count, and inside packageastanyspanInfowrite (index assignment,++/--, reassignment,delete/clear) outsideSetSpan.TestSpanWritesDetectorchecks the detector on 14 synthetic sources.internal/goldensholds the shared infrastructure (Golden, Render/Compare/Report, Dump, the token/position/error renderers, Corpus, Parallel, Safe) and has its own unit tests.Test Plan
Gates (AC-STD), all on this branch at 29b95cc (origin/main b420e2d merged in, which includes #907 ALTER TABLE commas and #912):
task check(fmt, vet, golangci-lint with 0 issues,test:race): pass.task test:cbinding: pass.go test -count=1 ./pkg/compatibility/...: pass.go run honnef.co/go/tools/cmd/staticcheck@latest ./internal/goldens ./pkg/sql/ast ./pkg/sql/tokenizer ./pkg/sql/parser ./pkg/formatter ./pkg/fingerprint ./pkg/linter ./pkg/sql/security ./pkg/transpiler ./pkg/lsp: clean.Review follow-up (29b95cc):
task goldens:updatethentask goldens: pass. Changed cells: everytokenscell (comments are now rendered; no scratch/string section appears, so all paths agree today) and the newparse[default]column. Every existingparsedialect cell is byte-identical to the previous commit (checked by stripping the last column). The other six files change only in the header line (flag rename).GOMAXPROCS=1 go test -count=2 -run '^TestGolden'(tokenizer, parser, formatter, lsp): pass.go test -race -run '^TestGolden|TestSpan'(tokenizer, parser, formatter, lsp, ast, internal/goldens): pass.gosqlx.Parseerror wrap"%w: %w"→"%w; %w"failsparsein 90[default]cells (no dialect cell). The scratch path settingToken.Word = nilon non-keyword words (SQL()unchanged) failstokensin 2794 cells.Stability:
go test -count=3 -run '^TestGolden' <8 golden pkgs>: pass (3 runs).GOMAXPROCS=1 go test -count=1 -run '^TestGolden' ...: pass. Output does not depend on parallelism.go test -race -count=1 -run '^TestGolden' ...: pass. Race timings on an M4 (10 cores, load ~13): tokens 3.8s, parse 6.1s, format 1.2s, fingerprint 0.8s, lint 1.4s, security 1.1s, transpile 3.4s, lsp 1.0s. Non-race, each is under 1s.Mutation sensitivity. One mutation was injected into library code per golden. The matching golden was run against a clean base dump (
-goldens.base), and the mutation was reverted afterwards. Every golden failed:Token.Quote: 0(value unchanged)ARRAY JOINPoscolumn + 1 (SQL()unchanged)" , "%x→%X(Normalize unchanged)BIGSERIAL[sqlite]of one file)readonlyon TRUE/FALSE/NULLDiff-mode output for the position-only mutation:
and for the transpile mutation:
scripts/goldens-diff.sh HEADwas also run end to end with the transpile mutation in the working tree. It printed the same statement diff and removed its temporary worktree.The SetSpan invariant test also fails when
ast.SetSpan(clause, ...)is added toparseArrayJoin.internal/goldensunit tests cover:AddComparereporting exactly the mutated cell, including cells rendered as=Breaking Changes
None. The PR adds tests, test data, a script and three Taskfile tasks; no library code changes. CHANGELOG is left for the consolidated W0-12 entry. Golden outputs reflect
origin/mainat b420e2d (merged into the branch), which includes the W0-00a lambda/U&fixes and #907.🤖 Generated with Claude Code
https://claude.ai/code/session_01DnbRnTFErhoMJdAjVEeCg2