feat(testtool): generate FSST reference data for other implementations - #153
Merged
Conversation
Adds `create_fsst_test_file`, which writes one small Parquet file exercising the FSST encoding's corner cases, modelled on the ALP file in apache/parquet-testing#119: one file rather than a corpus, and every FSST column duplicated by a DELTA_LENGTH_BYTE_ARRAY column holding the same values, so a reader can bit-compare the two without any expected data alongside the file. The corpus is synthetic and seeded, so the file is reproducible and carries no third-party licensing. Four row groups, each training its own symbol table: URLs, nulls-and-empties, escape-forcing values, and long values. The command reads the file back before reporting, because most of what makes it useful is chosen rather than declared — the writer picks the offset encoding per page, the trainer picks the symbol table, and §7.5 may decline FSST for a chunk entirely. Two rounds of that feedback changed the corpus: - The escape section produced no escapes at all. It put a rare code point in every value, so the trainer simply learned it as a symbol. Only every ninth value carries one now, and the file has 78 escape sequences. - A binary chunk fell back under §7.5 and vanished from the summary, which read as a bug in the summary rather than the writer declining. Fallback is now reported explicitly. Also shrank the file from 520 KB to 182 KB uncompressed (80 KB with --compression zstd), since parquet-testing#119 rejected its predecessor for size. Grants Core internals to the TestTool, which every other consuming project already had, so the page walk can decompress a compressed values section. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new ew-test-tool create_fsst_test_file command that generates a small, reproducible Parquet file designed to exercise FSST encoding corner cases, then reads it back to verify FSST columns decode bit-identically to reference columns and to report what was actually written (table details, per-page offset encoding, escape counts). It also extends Core internals access to the TestTool so the command can walk/decompress pages when describing the output.
Changes:
- Add CLI command wiring and help text for
create_fsst_test_file. - Introduce
FsstTestDatato synthesize the corpus, write the file with FSST/FSST_16 columns plus reference columns, then verify and describe the encoded pages. - Grant
EngineeredWood.Parquet.TestToolaccess toEngineeredWood.Coreinternals viaInternalsVisibleTo.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/EngineeredWood.Parquet.TestTool/Program.cs | Adds command dispatch + usage/help text for the new FSST test-file generator. |
| src/EngineeredWood.Parquet.TestTool/FsstTestData.cs | Implements corpus generation, Parquet writing options, verification, and page-walk reporting for FSST/FSST_16. |
| src/EngineeredWood.Core/EngineeredWood.Core.csproj | Adds InternalsVisibleTo for the TestTool so it can use Core internals needed for detailed page inspection. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The binary escape corpus overwrote the last byte of its own prefix. The overwrite index was hardcoded to 24 against a 25-byte prefix, so it ate the trailing '-'. Deriving the offset from the prefix instead is not cosmetic: it lifts the file from 110 escape sequences to 181, and the binary FSST column in the escapes row group goes from 0 escapes to 2 — that column was not exercising the escape path at all. DescribeTable printed `headerSize + body.Length - headerSize`, which is just body.Length, leaving headerSize computed and unused. The whole serialized body is the right thing to report, so the number is unchanged; the dead term is gone and the label is now explained. --compression parsed the entire CompressionCodec enum, so LZO — which the writer cannot emit — was accepted and failed later as a NotSupportedException from inside the page writer. Validates against the codecs the writer supports and fails with a usage error naming them. Found by Copilot review on #153. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Adds
ew-test-tool create_fsst_test_file, which writes one small Parquet file exercising the FSST encoding's corner cases, for use as reference data by other implementations.Modelled on the ALP file in apache/parquet-testing#119: one file rather than a corpus, and every FSST column duplicated by a
DELTA_LENGTH_BYTE_ARRAYcolumn holding the same values — so a reader can bit-compare the two without needing any expected data shipped alongside the file. That predecessor was rejected partly for size, so this one is 182 KB uncompressed (80 KB with--compression zstd).The corpus is synthetic and seeded, so the file is reproducible from source and carries no third-party licensing. Four row groups, each training its own symbol table (§1.4):
urlsnulls_and_emptiesescapeslong_valuesIt verifies rather than asserts
The command reads the file back before reporting, because most of what makes it useful is chosen rather than declared: the writer picks the offset encoding per page, the trainer picks the symbol table, and §7.5 may decline FSST for a chunk outright. Two rounds of that feedback changed the corpus:
Sample output:
Both offset encodings are covered (
long_valuesis the row group where PLAIN beats DELTA), and both symbol table widths appear in every row group.Known coverage gap
No FSST_16 column contains an escape sequence, so the file does not exercise FSST_16 escape decoding. That is not fixable from the writer: Clast.Fsst's 16-bit tables always contain all 256 single-byte symbols, so nothing is ever left to escape. It is also the one place the two variants are genuinely asymmetric, and the one part of the FSST_16 wire format still resting on inference rather than confirmed spec text.
Also
Grants Core internals to the TestTool — every other consuming project already had them — so the page walk can decompress a compressed values section and report page detail for
--compression zstdfiles too.🤖 Generated with Claude Code