Skip to content

test: Cover the Variant object header size matrix end to end - #422

Merged
CurtHagenlocher merged 2 commits into
apache:mainfrom
CurtHagenlocher:test/variant-object-header-size-matrix
Aug 23, 2026
Merged

test: Cover the Variant object header size matrix end to end#422
CurtHagenlocher merged 2 commits into
apache:mainfrom
CurtHagenlocher:test/variant-object-header-size-matrix

Conversation

@CurtHagenlocher

Copy link
Copy Markdown
Contributor

What's Changed

Additional test coverage for #420.

#421 fixed MakeObjectHeader / ParseObjectHeader writing field_id_size and offset_size into each other's bits, and pinned both helpers to literal header bytes. That coverage stops at the helper: it says nothing about which widths VariantValueWriter asks for, or whether the body it emits is laid out at the widths the header declares.

VariantObjectHeaderSizeTests builds real objects over the matrix of reachable widths — the dictionary is padded with names sorting ahead of the object's own to drive field IDs into the 2- and 3-byte bands, and the first field's value is padded to drive the end offset into them. Each case asserts the emitted header byte, decodes the object body with a decoder written from the spec rather than through VariantEncodingHelper, checks that the widths were forced for the reason intended (largest ID, end offset), and reads the object back through the library. A second theory covers objects of 300 fields, which pack is_large into bit 6 alongside the two size fields.

Width 4 is unreachable from a real object: a 4-byte field ID needs a dictionary of more than 16,777,216 entries and a 4-byte offset needs more than 16 MiB of field data, so those cells stay covered at the helper level.

apache#421 fixed `MakeObjectHeader` / `ParseObjectHeader` writing `field_id_size`
and `offset_size` into each other's bits, and pinned both helpers to literal
header bytes. That coverage stops at the helper: it says nothing about which
widths `VariantValueWriter` asks for, or whether the body it emits is laid
out at the widths the header declares.

`VariantObjectHeaderSizeTests` builds real objects over the matrix of
reachable widths — the dictionary is padded with names sorting ahead of the
object's own to drive field IDs into the 2- and 3-byte bands, and the first
field's value is padded to drive the end offset into them. Each case asserts
the emitted header byte, decodes the object body with a decoder written from
the spec rather than through `VariantEncodingHelper`, checks that the widths
were forced for the reason intended (largest ID, end offset), and reads the
object back through the library. A second theory covers objects of 300
fields, which pack `is_large` into bit 6 alongside the two size fields.

Width 4 is unreachable from a real object: a 4-byte field ID needs a
dictionary of more than 16,777,216 entries and a 4-byte offset needs more
than 16 MiB of field data, so those cells stay covered at the helper level.

Verified by reintroducing the transposition in `MakeObjectHeader`: 8 of the
13 cases fail, exactly the ones where `field_id_size != offset_size`. The
5 symmetric cases pass either way, which is why the bug survived until now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds end-to-end unit tests that validate Variant object header encoding (field_id_size, offset_size, and is_large) across the reachable size matrix by writing real objects via VariantValueWriter, decoding the raw bytes according to the spec, and then round-tripping via VariantObjectReader. This extends prior helper-level coverage (from #421) to ensure the writer chooses the intended widths and that the emitted body layout matches the declared header widths.

Changes:

  • Introduces VariantObjectHeaderSizeTests covering the cross-product of reachable field_id_size and offset_size combinations (plus large-object is_large cases).
  • Builds fixtures that force field ID width via a padded, sorted metadata dictionary and force offset width via padded field data.
  • Decodes object bodies with a spec-driven decoder (independent of VariantEncodingHelper) and validates header byte, widths, IDs/offsets, and library round-trip.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/Apache.Arrow.Scalars.Tests/VariantObjectHeaderSizeTests.cs Outdated
The spec-side decoder asserted that field offsets strictly increase. Field
IDs are sorted by name, but the values they point at may be stored in any
physical order — `VariantObjectReader.GetFieldValue` says as much, which is
why it slices from a field's start rather than between two offsets. The
assertion therefore pinned the current writer's layout in a block whose
stated job is checking the writer against the spec, and a spec-legal
reordering would have failed it.

Assert what the spec fixes instead: the last offset ends the data region,
and every field start lies inside it. Reintroducing the transposition in
`MakeObjectHeader` still fails the same 8 of 13 cases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@CurtHagenlocher
CurtHagenlocher merged commit 62f2790 into apache:main Aug 23, 2026
14 checks passed
@CurtHagenlocher
CurtHagenlocher deleted the test/variant-object-header-size-matrix branch August 23, 2026 15:27
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