andygrove opened a new issue, #6615:
URL: https://github.com/apache/datafusion-comet/issues/6615
## What / Why
Comet SQL tests (`CometSqlFileTestSuite`, with fixtures under
`spark/src/test/resources/sql-tests/`) can now express most of what the Scala
expression suites check:
- per-file `Config` / `ConfigMatrix` for ANSI, time zones, dictionary
encoding, shuffle mode, batch size and allowIncompatible;
- `MinSparkVersion` / `MaxSparkVersion` gates;
- query modes for native coverage, fallback reasons, errors, tolerance, and
native versus codegen dispatch (`expect_native` / `expect_dispatch`).
Every query is compared against Spark, and constant folding is disabled so
all-literal queries run in Comet.
Expression coverage is still split between those fixtures and the Scala
suites. About 1,160 Scala test definitions across 45 suites are in scope here.
This epic moves their coverage into SQL tests.
**The goal is to lose no coverage, not to translate every test one for one.**
- A Scala test is deleted once a fixture covers what it covered: the same
inputs, configs and assertion strength, or stronger.
- Tests that genuinely need Scala stay.
- Each sub-issue accounts for every test in its scope, so nothing is dropped
silently.
## Analysis
I classified every test in the expression suites by static analysis of
`main` at 3bc2faa934. That includes the expression-level tests in the
aggregate, window and generate operator suites. Each sub-issue lists its tests
with a verdict and a target fixture.
The verdicts come from reading the code, not from running fixtures, so treat
each target as a starting point. If a conversion turns out not to preserve
coverage, keep the Scala test and note why in the sub-issue.
| Area | Issue | Tests | Covered | Convert | Blocked | Split | Keep |
|---|---|---|---|---|---|---|---|
| Math and arithmetic | | 40 | 7 | 25 | 5 | 0 | 3 |
| Decimal arithmetic | | 21 | 0 | 10 | 2 | 0 | 9 |
| Cast from boolean, integral, floating-point, decimal | | 118 | 1 | 112 |
1 | 0 | 4 |
| Cast from string | | 48 | 0 | 47 | 1 | 0 | 0 |
| Cast from date, timestamp, binary, complex types | | 44 | 0 | 43 | 0 | 0
| 1 |
| Datetime | | 57 | 6 | 42 | 1 | 0 | 8 |
| String | | 56 | 18 | 36 | 1 | 0 | 1 |
| Regex | | 95 | 14 | 58 | 8 | 0 | 15 |
| Arrays and higher-order functions | | 81 | 3 | 43 | 23 | 8 | 4 |
| Maps and structs | | 45 | 1 | 24 | 17 | 2 | 1 |
| Generators (explode, posexplode) | | 43 | 1 | 40 | 0 | 0 | 2 |
| Aggregates | | 127 | 0 | 90 | 4 | 8 | 25 |
| Window functions and float sort keys | | 64 | 25 | 35 | 0 | 2 | 2 |
| Collation (Spark 4) | | 73 | 6 | 49 | 2 | 4 | 12 |
| Hash and bitwise | | 57 | 10 | 45 | 1 | 0 | 1 |
| Conditional, JSON, CSV, Variant, misc | | 93 | 5 | 38 | 3 | 4 | 43 |
| Float semantics sweep (412 runtime cases) | | 5 | 0 | 1 | 0 | 4 | 0 |
| Codegen dispatcher | | 89 | 1 | 23 | 2 | 2 | 61 |
| **Total** | | **1156** | **98** | **761** | **71** | **34** | **192** |
- **Covered:** an existing fixture already covers the test.
- **Convert:** expressible in SQL tests today.
- **Blocked:** needs one of the framework changes below first.
- **Split:** part converts, part stays.
- **Keep:** stays in Scala.
Three findings shape the work.
1. **Few tests are covered today.** The fixtures are thinner than the Scala
tests:
- aggregates are grouped only by string keys;
- many fixtures use `tolerance=` where the Scala test compares exactly;
- cast fixtures are non-ANSI only, with no `try_cast`;
- datetime fixtures have far fewer formats, time zones and edge values;
- most array and map fixtures run one-row batches.
Most of the work is therefore extending fixtures, not deleting tests.
2. **Some existing tests, Scala and SQL, don't test what they claim.** These
need fixing as part of the move:
- **Regex escapes.** Spark drops the backslash before an unknown escape,
so `'\d'` is `d`. Seven regex fixtures, and the Scala `rlike` tests, never test
`\d`, `\w`, anchors or backreferences.
- **NaN under tolerance.** `query tolerance=` skips the comparison when
either side is NaN. The NaN results of every per-function math fixture and
`corr.sql`'s NaN permutations are never compared.
- **Literal casts.** `CometCast` folds a cast of a literal on the JVM, so
literal casts in the cast fixtures never run native code.
- **NULL literals.** Spark's `NullPropagation` folds NULL-literal
arguments before Comet sees them; the contributor guide's own `ascii(NULL)`
example is affected.
- **Comet compared with Comet.** About 20 cast tests use a helper,
`assertDataFrameEqualsWithExceptions`, that compares Comet with Comet.
- **Vacuous Scala tests**, for example:
- three "null group key" aggregate tests build their keys with
`null.asInstanceOf[Int]`, which is `0`;
- a cast test maps over a lazy `Iterator` and never runs;
- `try_add` / `try_subtract` / `try_multiply` are constant-folded by
Spark;
- the INT96 conversion legs compare Spark with Spark.
3. **About 71 tests need framework changes first.**
- Structured error parity: `expect_error` checks only a message substring
and never checks that Comet ran the query.
- Optimizer-rule control: a fixture can't keep ConstantFolding, which the
folded-literal tests need, or exclude `NullPropagation` /
`ConvertToLocalRelation`.
## Ground rules for every PR
1. **Account for every Scala test in scope.** Each one is converted, cited
as already covered, or kept with its reason. The table in each sub-issue is the
checklist.
2. **Delete each converted Scala test in the same PR that adds its
coverage.** When a suite is empty, delete it and remove it from the suite lists
in `.github/workflows/pr_build_linux.yml` and `pr_build_macos.yml`. A stale
name there doesn't fail CI: `CometExpressionCoverageSuite` is still listed,
although #2854 deleted it.
3. **Make sure the fixture reaches Comet.**
- Read expression inputs from Parquet tables, not from inline `VALUES`,
literal casts or NULL literals.
- Use one-file inserts (`INSERT ... SELECT /*+ COALESCE(1) */ ...` or
`range(0, n, 1, 1)`) when batch shape or row order matters.
- The docs sub-issue lists all of the traps.
4. **Check special float values exactly.** Put NaN, ±Infinity and
signed-zero results in a plain `query`, and write negative zero as
`double('-0.0')`.
5. **Keep mechanism checks.** Where the Scala test pinned native versus
dispatch, pin it with `expect_native` / `expect_dispatch`.
6. **Random-data tests convert to curated values** that include the
generator's edge values. The fuzz suites keep the random coverage:
`CometFuzzTestSuite`, `CometFuzzAggregateSuite`, `CometFuzzMathSuite` and
`CometCodegenFuzzSuite`.
7. **Spot-check regression tests named after an issue:** confirm the fixture
fails with the fix reverted.
8. **Run every profile.** Pull request CI runs only the default Spark
profile, and fixtures carry version gates, so these PRs need the
`run-all-spark-profiles` label.
9. **Watch CI bucket balance.** Moving aggregate and window coverage shifts
CI time from the `exec` bucket to the `expressions` bucket. Rebalance if
`expressions` grows much longer than the others.
## What stays in Scala
- Plan shape: operator counts, canonicalization, exchange reuse,
mixed-engine partial/final safety.
- Metrics, and explain / COMET-INFO text.
- Serde and proto internals, and unit tests of helpers such as the
`CometRegex` analyzer and the time-zone ID mapping.
- UDF registration.
- DataFrame-only inputs: MakeDecimal, non-nullable struct fields,
negative-scale decimals, an empty `InSet`.
- `Unevaluable` expressions such as `Days` / `Hours`.
- Raw NaN payload bits.
- Parquet layouts SQL can't write.
- The fuzz suites.
- Comet-only failures that intentionally differ from Spark.
## Work
Suggested order:
1. Start with the framework and docs issues.
- The tolerance fix is small, and it changes how the math and aggregate
conversions are written.
- The error-parity and optimizer-rule issues unblock the tests counted as
blocked in the table.
2. The area issues are independent of each other and can proceed in
parallel. Window, hash/bitwise and generators are the most mechanical. Float
semantics is the lowest priority.
### Framework and docs (do first)
- [ ] (to be filed) test: `query tolerance=` in Comet SQL tests passes when
either side is NaN
- [ ] (to be filed) test: add a Comet SQL test error mode that checks native
execution and error-class parity
- [ ] (to be filed) test: let Comet SQL tests keep ConstantFolding, exclude
optimizer rules and change configs mid-file
- [ ] (to be filed) docs: document the ways a Comet SQL test can silently
miss Comet
### By area
- [ ] (to be filed) test: move math and arithmetic coverage from Scala
suites to Comet SQL tests
- [ ] (to be filed) test: move decimal arithmetic coverage from Scala suites
to Comet SQL tests
- [ ] (to be filed) test: move cast coverage for boolean, integral,
floating-point and decimal sources to Comet SQL tests
- [ ] (to be filed) test: move cast coverage for string sources to Comet SQL
tests
- [ ] (to be filed) test: move cast coverage for date, timestamp, binary and
complex-type sources to Comet SQL tests
- [ ] (to be filed) test: move datetime expression coverage from Scala
suites to Comet SQL tests
- [ ] (to be filed) test: move string expression coverage from Scala suites
to Comet SQL tests
- [ ] (to be filed) test: move regex coverage to Comet SQL tests and fix
fixtures whose patterns lose their backslashes
- [ ] (to be filed) test: move array expression coverage from Scala suites
to Comet SQL tests
- [ ] (to be filed) test: move map and struct expression coverage from Scala
suites to Comet SQL tests
- [ ] (to be filed) test: move explode/posexplode coverage from
CometGenerateExecSuite to Comet SQL tests
- [ ] (to be filed) test: move aggregate function coverage from
CometAggregateSuite to Comet SQL tests
- [ ] (to be filed) test: move window function coverage from
CometWindowExecSuite to Comet SQL tests
- [ ] (to be filed) test: move the Spark 4 collation suites to Comet SQL
tests
- [ ] (to be filed) test: move hash and bitwise expression coverage from
Scala suites to Comet SQL tests
- [ ] (to be filed) test: move conditional, JSON, CSV, Variant and other
expression coverage to Comet SQL tests
- [ ] (to be filed) test: move CometFloatSemanticsSuite's matching cases to
Comet SQL tests
- [ ] (to be filed) test: move expression-level codegen dispatcher tests to
Comet SQL tests
Related:
- #4616: testing dual-implementation expressions across the routing matrix.
The `routing_*` fixtures are its home.
- #3406: point "Adding a New Expression" at SQL tests.
- #4770: collation suite shim. Most of its duplication goes away once those
tests are fixtures gated on 4.0.
- #5968: float rendering through SQL tests.
- #4765: an earlier, closed attempt at four temporal tests.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]