Skip to content

test(jni): assert the Java and Rust expression tag tables agree - #9454

Open
jackylee-ch wants to merge 1 commit into
vortex-data:developfrom
jackylee-ch:jni-expression-tag-parity-tests
Open

test(jni): assert the Java and Rust expression tag tables agree#9454
jackylee-ch wants to merge 1 commit into
vortex-data:developfrom
jackylee-ch:jni-expression-tag-parity-tests

Conversation

@jackylee-ch

Copy link
Copy Markdown
Contributor

Rationale for this change

Expression hands four byte tags to the native side, each with its own reader in expression.rs: BinaryOpparse_op, DuplicateHandlingparse_duplicate_handling, TimeUnitTimeUnit::try_from, DType → the table in literalNull. Three of the four javadocs say the values must match the Rust table; nothing checked it. Drift compiles on both sides, and the two failure modes differ: a tag past the end of a table throws at runtime, but a tag that collides with a sibling decodes to the wrong operator or unit and returns an expression that reads valid.

What changes are included in this PR?

Test only, one new file. Each table is pinned twice — the constants against the bytes Rust matches, and every constant through the native call that consumes it.

Both temporal types are covered because between them they reject enough units to tell the five TimeUnit tags apart: Timestamp takes everything but DAYS, Date only DAYS and MILLISECONDS.

Verified non-vacuous: eight mutations of the Java tables, covering both off-the-end and colliding tags, each fail a targeted test. :vortex-jni:test goes from 32 to 46, no failures.

What APIs are changed? Are there any user-facing changes?

None.

AI assistance

Prepared with agentic AI assistance. I read both sides of each table and confirmed the mutations fail.

Expression hands four byte tags across the JNI boundary, and each one has
its own reader on the Rust side: BinaryOp is read by parse_op,
DuplicateHandling by parse_duplicate_handling, TimeUnit by
TimeUnit::try_from, and DType by the table in literalNull. Three of the
four javadocs state that the values must match the Rust table, but nothing
enforced it, and drift compiles cleanly on both sides.

The two drift shapes fail differently. A tag past the end of a table
reaches the other => arm and throws at runtime. A tag that collides with a
sibling decodes to the wrong operator or the wrong time unit and returns an
expression that reads valid, so it surfaces later as a wrong scan result
rather than an error.

Pin each table twice: the constants against the bytes Rust matches, and
every constant through the native call that consumes it. Both temporal
types are exercised because between them they reject enough units to
distinguish the five TimeUnit tags -- Timestamp accepts everything but
Days, Date only Days and Milliseconds -- and Date names the unit it
rejected.

Signed-off-by: jackylee <qcsd2011@gmail.com>
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.

1 participant