-
Notifications
You must be signed in to change notification settings - Fork 278
tests: Add SQL test files covering edge cases for (almost) every Comet-supported expression #3328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Introduce a sqllogictest-inspired framework for writing Comet tests as plain .sql files instead of Scala code. Convert 11 tests from CometExpressionSuite to demonstrate the approach. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ~115 SQL test files covering edge cases for every Comet-supported expression, using the SQL file-based test framework. Tests cover NULL inputs, boundary values, special values (NaN, Infinity, empty strings), and type variety. Adds two new query modes to the test framework: - `query expect_fallback(reason)` - verifies fallback reason AND results - `query ignore(reason)` - skips query (for known bugs with issue links) Includes happy-path tests with configs enabled for incompatible expressions (case conversion, regexp, date_format, from_unix_time, init_cap). Known bugs filed: - apache#3326 (space(-1) crash) - apache#3327 (map_from_arrays(NULL) crash) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3328 +/- ##
============================================
+ Coverage 56.12% 60.07% +3.94%
- Complexity 976 1477 +501
============================================
Files 119 175 +56
Lines 11743 16167 +4424
Branches 2251 2682 +431
============================================
+ Hits 6591 9712 +3121
- Misses 4012 5111 +1099
- Partials 1140 1344 +204 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Are we able to use the standard .slt format or do we require additional features? There's an MIT-licensed parser from the Apache Calcite team here: https://github.com/hydromatic/sql-logic-test |
pr-description.md
Outdated
|
|
||
| - **`SqlFileTestParser.scala`** — Parses `.sql` test files into a structured `SqlTestFile` representation. Each file can contain: | ||
| - `-- Config: key=value` — Spark SQL configs to set for the entire file | ||
| - `-- ConfigMatrix: key=value1,value2` — Generates one test per combination of values (e.g., dictionary encoding on/off) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, we can toggle ANSI mode by ConfigMatrix: spark.sql.ansi.enabled=true,false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct, we can also (later) add config parameters when running the whole suite, maybe via maven profiles
This is inspired by slt but there are some key differences.
|
hsiang-c
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome!
It is also worth pointing out that the test runner is ~300 LOC and extends Example output: |
…expression tests Add 8 new SQL test files for previously untested expressions (GetArrayItem, GetStructField, GetMapValue, GetArrayStructFields, ArrayFilter, ScalarSubquery, decimal ops, WidthBucket). Reorganize all 131 SQL test files into 13 category subdirectories (math, string, array, map, struct, aggregate, datetime, conditional, bitwise, hash, cast, decimal, misc). Add MinSparkVersion directive support to the test framework for version-gated tests. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
de72ab5 to
53fc897
Compare
| } | ||
|
|
||
| // Discover and register all .sql test files | ||
| discoverTestFiles(testResourceDir).foreach { file => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can parallelize the foreach and run tests in parallel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try this as follow on PR if that is ok.
| } | ||
|
|
||
| /** Generate all config combinations from a ConfigMatrix specification. */ | ||
| private def configCombinations( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be good to name configMatrix ?
| /** A SQL query whose results are compared between Spark and Comet. */ | ||
| case class SqlQuery(sql: String, mode: QueryMode = CheckOperator) extends SqlTestRecord | ||
|
|
||
| sealed trait QueryMode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| sealed trait QueryMode | |
| sealed trait QueryAssertionMode |
| case class SqlQuery(sql: String, mode: QueryMode = CheckOperator) extends SqlTestRecord | ||
|
|
||
| sealed trait QueryMode | ||
| case object CheckOperator extends QueryMode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checkCoverageAndAnswer
?
| val records = Seq.newBuilder[SqlTestRecord] | ||
| val tables = Seq.newBuilder[String] | ||
|
|
||
| var i = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we name i better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I addressed this and your other comments
…Matrix Ignore get_array_item dynamic index test (apache#3332) and width_bucket tests (apache#3331) with links to tracking issues. Rename configCombinations method to configMatrix for clarity. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
caa7aeb to
9a711b4
Compare
- Rename QueryMode to QueryAssertionMode - Rename CheckOperator to CheckCoverageAndAnswer - Rename loop variable i to lineIdx in SqlFileTestParser Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@shehabgamin you may be interested in this |
| -- specific language governing permissions and limitations | ||
| -- under the License. | ||
|
|
||
| -- ConfigMatrix: parquet.enable.dictionary=false,true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many of the tests run with dictionary encoding on and off, and this is because this is what we do in existing Scala-based tests, so I left it for now. However, this is pointless because most of these tests only insert a few rows. I will fix this in a future PR.
Add literal value test coverage for all expression test files to ensure Comet's native engine handles literal arguments correctly, not just column references. For N-argument functions, test all combinations of literal/column arguments (col+lit, lit+col, lit+lit, etc.). Disable Spark's ConstantFolding optimizer rule in the test runner so literal-only expressions reach Comet's native engine rather than being folded away at plan time. Mark queries that expose native engine bugs with ignore directives linked to filed GitHub issues: - apache#3336: datetime scalar panics (hour, minute, second, unix_timestamp) - apache#3337: Substring/StringSpace scalar panics - apache#3338: array literal index out of bounds - apache#3339: concat_ws NULL separator crash - apache#3340: sha2 literal crash - apache#3341: bit_count scalar panic - apache#3342: DateTrunc/TimestampTrunc literal crash - apache#3343: all-literal RLIKE crash - apache#3344: replace() empty-string search wrong result - apache#3345: array_contains literal result mismatch - apache#3346: array_contains empty array returns null instead of false Mark expected fallback cases with expect_fallback directives: - lpad/rpad: scalar str argument not supported - initcap: moved literal tests to init_cap_enabled.sql Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
I will add ansi tests in a follow on PR |
Summary
Closes #2611
CometSqlFileTestSuiteandSqlFileTestParserignoredirectives linked to GitHub issuesexpect_fallbackdirectivesHow the SQL file test framework works
Overview
CometSqlFileTestSuiteautomatically discovers.sqltest files underspark/src/test/resources/sql-tests/expressions/and registers each one as a ScalaTest test case. This allows expression tests to be written as plain SQL files rather than Scala code.SQL file format
Each
.sqlfile contains a sequence of statements and queries, separated by blank lines:File-level directives (in comment headers):
-- Config: key=value— sets a Spark SQL config for all queries in the file-- ConfigMatrix: key=val1,val2,...— runs the entire file once per value (generates combinatorial test cases)-- MinSparkVersion: X.Y— skips the test on older Spark versionsRecord types:
statement— executes DDL/DML (CREATE TABLE, INSERT, etc.) without checking resultsquery— executes a SELECT and compares Comet results against Spark, verifying both correctness and native execution coverageQuery assertion modes:
query— (default) checks that results match Spark AND that all operators ran natively in Cometquery spark_answer_only— checks results match Spark but does not verify native executionquery tolerance=1e-6— checks results match within a floating-point tolerancequery expect_fallback(reason)— checks results match Spark AND verifies that Comet fell back to Spark with a reason string containing the given textquery ignore(reason)— skips the query entirely (used for known bugs, with a link to the GitHub issue)Test runner (
CometSqlFileTestSuite)The test runner:
.sqlfiles recursively undersql-tests/SqlFileTestParserConfigMatrix(e.g.,parquet.enable.dictionary=false,trueproduces two test cases per file)ConstantFoldingoptimizer rule so that literal-only expressions are evaluated by Comet's native engine rather than being folded away at plan timeTest file organization
Test files are organized into category subdirectories:
Native engine issues discovered
These issues were found by testing literal argument combinations with constant folding disabled: