Skip to content

test(spark): add incremental read-path relation coverage - #19404

Merged
voonhous merged 3 commits into
apache:masterfrom
yihua:test-incremental-relation-coverage
Jul 31, 2026
Merged

test(spark): add incremental read-path relation coverage#19404
voonhous merged 3 commits into
apache:masterfrom
yihua:test-incremental-relation-coverage

Conversation

@yihua

@yihua yihua commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Describe the issue this Pull Request addresses

The Spark incremental read-path relations are under-covered. The four relations in hudi-spark-datasource/hudi-spark-common sit well below the rest of the module: IncrementalRelationV2 around 51%, IncrementalRelationV1 around 47%, MergeOnReadIncrementalRelationV2 around 62%, and MergeOnReadIncrementalRelationV1 around 74%. Two branches in particular had no coverage: the hoodie.datasource.read.incr.path.glob file filtering used by the batch incremental relations, and the version-8 legacy streaming path that drives IncrementalRelationV2.

Summary and Changelog

This is a test-only change; no production code is modified.

  • Added TestIncrementalReadWithPathGlob (functional). It writes one partition per commit, then runs incremental queries with incr.path.glob restricting to each partition and to a partition that does not exist, asserting the exact per-partition row counts. It is parametrized over table type (COW, MOR) and table version (6, 8). Both the COW and MOR batch incremental read routes build a HoodieIncrementalFileIndex backed by MergeOnReadIncrementalRelationV1 (version 6) / MergeOnReadIncrementalRelationV2 (version 8), so these cases pin filterFileSlices and its empty-result branch for both relations, with includeLogFiles both off (COW) and on (MOR).
  • Extended TestStreamingSource. The existing legacy-streaming test (file group reader disabled) was version 6 only, which reaches IncrementalRelationV1 / MergeOnReadIncrementalRelationV1 but never the V2 relations. Parametrized it by table version and added version-8 cases, so the version-8 legacy streaming path through HoodieStreamSourceV2 drives IncrementalRelationV2 (COW) and MergeOnReadIncrementalRelationV2 (MOR).

Deliberate overlap and how duplication was avoided: TestCOWDataSourceStorage already exercises incr.path.glob for COW at the default table version and asserts total counts only. The new glob test does not reproduce that. It extends the glob coverage to table version 6 and to MOR, and pins the per-partition result (the partition of every returned row) plus the glob-matches-nothing empty branch, so it fails if the file filtering is wrong rather than merely non-empty. The streaming change folds new version-8 cases into the existing suite and helper rather than adding a near-duplicate class.

Impact

None. Tests only.

Risk Level

none

Documentation Update

none

Contributor's checklist

  • Read through contributor's guide
  • Enough context is provided in the sections above
  • Adequate tests were added if applicable

@codecov-commenter

codecov-commenter commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.75%. Comparing base (633d142) to head (bbb3ac3).
⚠️ Report is 14 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19404      +/-   ##
============================================
- Coverage     75.56%   74.75%   -0.81%     
+ Complexity    32651    32383     -268     
============================================
  Files          2574     2576       +2     
  Lines        142995   143558     +563     
  Branches      17530    17776     +246     
============================================
- Hits         108051   107320     -731     
- Misses        26908    28174    +1266     
- Partials       8036     8064      +28     
Components Coverage Δ
hudi-common 81.87% <ø> (-0.41%) ⬇️
hudi-client 80.67% <ø> (-1.17%) ⬇️
hudi-flink 83.97% <ø> (-0.06%) ⬇️
hudi-spark-datasource 66.22% <ø> (-2.12%) ⬇️
hudi-utilities 72.15% <ø> (+0.95%) ⬆️
hudi-cli 15.32% <ø> (ø)
hudi-hadoop 61.80% <ø> (-1.70%) ⬇️
hudi-sync 70.85% <ø> (+0.12%) ⬆️
hudi-io 79.60% <ø> (+0.02%) ⬆️
hudi-timeline-service 77.57% <ø> (-5.88%) ⬇️
hudi-cloud 64.00% <ø> (ø)
hudi-kafka-connect 53.20% <ø> (-0.77%) ⬇️
Flag Coverage Δ
common-and-other-modules 49.35% <ø> (+0.13%) ⬆️
flink-integration-tests 48.81% <ø> (-0.05%) ⬇️
hadoop-mr-java-client 43.35% <ø> (+0.02%) ⬆️
integration-tests 13.58% <ø> (-0.06%) ⬇️
spark-client-hadoop-common 48.68% <ø> (-0.04%) ⬇️
spark-java-tests 47.29% <ø> (-4.11%) ⬇️
spark-scala-tests 45.76% <ø> (-0.34%) ⬇️
utilities 36.54% <ø> (-0.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 179 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added the size:M PR with lines of changes in (100, 300] label Jul 29, 2026
@yihua
yihua marked this pull request as ready for review July 30, 2026 19:30

@hudi-agent hudi-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This is a test-only PR that adds coverage for the Spark incremental read-path relations — a new incr.path.glob per-partition filtering test parametrized over table type and version, plus version-8 cases for the legacy streaming source. I traced the glob-to-partition mappings (/2016/*/*/*2016/03/15, etc.), the commit boundaries, and the empty-result branch, and the assertions line up correctly. No correctness issues found. A few style/readability suggestions in the inline comments. Please take a look, and this should be ready for a Hudi committer or PMC member to take it from here. One redundant assertion to remove; everything else is clean.

cc @yihua

@hudi-agent hudi-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This PR adds test-only coverage for the Spark incremental read-path relations. It adds TestIncrementalReadWithPathGlob to exercise the incr.path.glob filtering branch across COW/MOR and table versions 6 and 8, and parametrizes TestStreamingSource by table version to reach the V2 relations. No issues flagged from this automated pass; a Hudi committer or PMC member can take it from here for a final review.

cc @yihua

yihua added 2 commits July 30, 2026 23:29
The assertEquals map comparison already implies the per-partition sums are equal, so the follow-up assertTrue can never catch a distinct failure. Remove it and the now-unused assertTrue import.
@yihua
yihua force-pushed the test-incremental-relation-coverage branch from 1c1a978 to 60db2bf Compare July 31, 2026 06:41

@voonhous voonhous left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Did a deep pass over these relations' git history and ran the new tests locally: all 4 glob cases and both v8 streaming cases pass, and the routing claims check out (COW batch incremental really does go through the MOR relations' filterFileSlices; v8 + FGR-off really drives the V2 relations). Inline comments below, ordered major -> nit: two asks on the new tests themselves, plus historically-motivated coverage gaps in the same relations that are either cheap to close in this diff or worth a tracked follow-up.

* below EIGHT) and [[HoodieStreamSourceV2]] (table version EIGHT and above), taken when the file
* group reader is disabled. This drives the standalone incremental relations
* ([[IncrementalRelationV1]] / [[MergeOnReadIncrementalRelationV1]] for version 6,
* [[IncrementalRelationV2]] / [[MergeOnReadIncrementalRelationV2]] for version 8) via `getBatch`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Follow-up suggestion: the fallback/full-table-scan blocks of these two standalone relations (IncrementalRelationV1.scala:235-272, IncrementalRelationV2.scala:225-259, including the parallelized file-existence probe from #10480) are reachable by no test in the repo, and they are most of the missing 47%/51% coverage this PR's description cites. The cheapest close is not via streaming: TestLegacyParquetReadPath.testCowIncrementalReadEqualsFileGroupReader already constructs both relations directly (lines 317-319); a variant that sets INCREMENTAL_FALLBACK_TO_FULL_TABLE_SCAN=true after aggressive cleaning and asserts both still equal the file-group-reader result would cover it in ~15 lines. Fine to defer -- if so, please file the follow-up issue.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Deferred to #19443 (item 1) -- extending TestLegacyParquetReadPath with the fallback-after-clean variant is out of scope for this PR.

import scala.collection.JavaConverters._

/**
* Coverage for the {@code hoodie.datasource.read.incr.path.glob} file-slice filtering branch of the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: this covers the file-slice copy of the glob only. The standalone COW relations carry a second, independently-written implementation of the same option over regularFileIdToFullPath/metaBootstrapFileIdToFullPath (IncrementalRelationV1.scala:196-207, V2.scala:181-192, including a meta-bootstrap arm the MOR copy lacks), reachable only from the legacy stream sources -- and no test sets INCR_PATH_GLOB on that path. The streaming suite's table is unpartitioned, so the natural home is the direct-construction test in TestLegacyParquetReadPath (lines 317-319). A follow-up issue would do.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Deferred to #19443 (item 2); agreed the streaming suite is the wrong home for it since its table is unpartitioned.

}

test("test cow stream source with legacy file group reader disabled on table version 8") {
testLegacyIncrementalStreamSource(COPY_ON_WRITE, HoodieTableVersion.EIGHT)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit, feel free to ignore: adjacent gap while you are raising IncrementalRelationV2 coverage -- INCREMENTAL_READ_SCHEMA_USE_END_INSTANTTIME is set by no test in the repo (grep hits only DataSourceOptions.scala and the two relations), so the useEndInstantSchema=true branch (IncrementalRelationV1.scala:121-129, V2.scala:106-114, from HUDI-1301/#2125) is uncovered. One extra option on the direct-construction test in TestLegacyParquetReadPath would cover ~10 lines per relation. Optional / follow-up.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Deferred to #19443 (item 3).

- MOR glob arms write log-only file slices via the in-memory index and
  assert merged upsert values plus inputFiles paths per glob
- thread enableInlineCluster through addDataToQuery and cluster in the
  legacy streaming test to reach the replaced-file filtering of the
  legacy incremental relations
- pin the legacy (non file-group-reader) plan shape in the streaming test
- add a TestIncrementalReadWithFullTableScan case pinning the divergent
  v6/v8 default of incr.fallback.fulltablescan.enable on a cleaned span

@voonhous voonhous left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@voonhous
voonhous enabled auto-merge (squash) July 31, 2026 10:53
@hudi-bot

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands @hudi-bot supports the following commands:
  • @hudi-bot run azure re-run the last Azure build

@github-actions github-actions Bot added size:L PR with lines of changes in (300, 1000] and removed size:M PR with lines of changes in (100, 300] labels Jul 31, 2026
@voonhous
voonhous merged commit c9dbde0 into apache:master Jul 31, 2026
74 of 75 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L PR with lines of changes in (300, 1000]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants