test(amber): cover exportOperatorsAsZip and the remaining ResultExportService entry points - #7816
Open
eugenegujing wants to merge 2 commits into
Open
test(amber): cover exportOperatorsAsZip and the remaining ResultExportService entry points#7816eugenegujing wants to merge 2 commits into
eugenegujing wants to merge 2 commits into
Conversation
…tService entry points Extend ResultExportServiceSpec from 40 to 60 tests: exportOperatorsAsZip's no-execution throw, archive naming, per-operator format dispatch with unknown-type CSV fallback, the NonClosingOutputStream multi-entry contract, and the empty-operator placeholder for both a missing result URI and a stored-but-zero-row table; exportSingleOperatorToDataset's per-format upload and partial-success policy; getOperatorDocument's null, real-document and WarehouseReadGuard-refusal branches; and the surrounding edge cases — CSV chunk-boundary and special-character round-trips, streamCellData's index limits, latest-execution resolution, and the duplicate-operator archive abort. Result-bearing tests store real Iceberg tables via the arrangement ExecutionResultServiceSpec already uses, which also retires the spec's stale "needs a live Iceberg catalog" banner.
Contributor
Automated Reviewer SuggestionsBased on the
|
Contributor
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 381 | 0.233 | 24,826/34,260/34,260 us | 🟢 -31.4% / 🔴 +128.5% |
| 🟢 | bs=100 sw=10 sl=64 | 804 | 0.491 | 125,218/137,667/137,667 us | 🟢 -19.7% / 🔴 +29.8% |
| ⚪ | bs=1000 sw=10 sl=64 | 925 | 0.565 | 1,076,062/1,146,346/1,146,346 us | ⚪ within ±5% / 🔴 +13.5% |
Baseline details
Latest main 2edbdf9 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 381 tuples/sec | 388 tuples/sec | 780.31 tuples/sec | -1.8% | -51.2% |
| bs=10 sw=10 sl=64 | MB/s | 0.233 MB/s | 0.237 MB/s | 0.476 MB/s | -1.7% | -51.1% |
| bs=10 sw=10 sl=64 | p50 | 24,826 us | 22,224 us | 12,590 us | +11.7% | +97.2% |
| bs=10 sw=10 sl=64 | p95 | 34,260 us | 49,960 us | 14,995 us | -31.4% | +128.5% |
| bs=10 sw=10 sl=64 | p99 | 34,260 us | 49,960 us | 19,141 us | -31.4% | +79.0% |
| bs=100 sw=10 sl=64 | throughput | 804 tuples/sec | 805 tuples/sec | 1,006 tuples/sec | -0.1% | -20.1% |
| bs=100 sw=10 sl=64 | MB/s | 0.491 MB/s | 0.491 MB/s | 0.614 MB/s | 0.0% | -20.0% |
| bs=100 sw=10 sl=64 | p50 | 125,218 us | 119,979 us | 99,387 us | +4.4% | +26.0% |
| bs=100 sw=10 sl=64 | p95 | 137,667 us | 171,545 us | 106,056 us | -19.7% | +29.8% |
| bs=100 sw=10 sl=64 | p99 | 137,667 us | 171,545 us | 113,689 us | -19.7% | +21.1% |
| bs=1000 sw=10 sl=64 | throughput | 925 tuples/sec | 912 tuples/sec | 1,043 tuples/sec | +1.4% | -11.3% |
| bs=1000 sw=10 sl=64 | MB/s | 0.565 MB/s | 0.557 MB/s | 0.637 MB/s | +1.4% | -11.3% |
| bs=1000 sw=10 sl=64 | p50 | 1,076,062 us | 1,093,310 us | 965,215 us | -1.6% | +11.5% |
| bs=1000 sw=10 sl=64 | p95 | 1,146,346 us | 1,138,790 us | 1,009,610 us | +0.7% | +13.5% |
| bs=1000 sw=10 sl=64 | p99 | 1,146,346 us | 1,138,790 us | 1,039,108 us | +0.7% | +10.3% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,524.55,200,128000,381,0.233,24826.10,34259.61,34259.61
1,100,10,64,20,2486.62,2000,1280000,804,0.491,125218.43,137667.15,137667.15
2,1000,10,64,20,21618.79,20000,12800000,925,0.565,1076061.97,1146346.35,1146346.35
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7816 +/- ##
============================================
- Coverage 91.50% 91.37% -0.14%
+ Complexity 4501 4475 -26
============================================
Files 1177 1169 -8
Lines 47489 47148 -341
Branches 5324 5288 -36
============================================
- Hits 43457 43080 -377
- Misses 2366 2405 +39
+ Partials 1666 1663 -3
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this PR?
This PR extends
amber/src/test/scala/org/apache/texera/web/service/ResultExportServiceSpec.scala(40 → 60 tests) to cover the threeResultExportServicemethods that previously had zero test references anywhere in the repository —exportOperatorsAsZip,exportSingleOperatorToDatasetandgetOperatorDocument— together with the edge cases of the export paths that reach them.exportOperatorsAsZip: throwsWebApplicationExceptionwhen the workflow never ran (where the siblingexportOperatorResultAsStreamreturns(null, None)for the same condition); names the archive<workflowName>-<yyyy-MM-dd_HH-mm-ss>.zip; dispatches each entry through the per-format writer on that operator's ownoutputType, with an unrecognised type falling back to CSV; routes every entry throughNonClosingOutputStreamso one entry's writer closing its stream cannot close the sharedZipOutputStream(asserted by a later entry surviving an earlier writer's close — the wrapper was already unit-tested in isolation, but nothing checked that the ZIP path uses it); and substitutes a<id>-empty.txtplaceholder instead of aborting the archive, covered for both halves of the guard — an operator with no stored result URI, and an operator whose stored result table exists but holds zero rows.exportSingleOperatorToDataset(driven throughexportToDataset): uploads each operator's rows to the file service in that operator's own format with the exact bodies asserted against a stub upload server, turns a thrown per-operator failure into an error entry instead of aborting the batch, reports a stored-but-empty result as having nothing to export, and pins the partial-success policy as characterization — when some operators export and some fail, the response issuccesscarrying only the success lines.getOperatorDocument: returns null when the operator stored no result URI, opens the stored result document with its count and contents read back, and refuses a result stored in a per-user warehouse while the feature is off (WarehouseUnavailableExceptionvia theWarehouseReadGuardfrom [BYO-S3] Feature flag (storage.warehouse.enabled, default off) #6930).CHUNK_SIZE10, exercised one-under, exactly-one and one-over); CSV values containing a comma, a double quote, a newline and non-ASCII text round-trip through the streamed export;streamCellDataaccepts the maximum row and column index and rejects the out-of-range ones with their exact reasons, while negative indexes are pinned as characterization because the>=guards let them through to an internal reader error and an array-index error; a result stored under an older execution is not exported once a newer execution exists, and the newer execution's rows win when both stored results; and requesting the same operator twice aborts the archive mid-stream with a duplicate-entryZipException, pinned as characterization since the client has already received its 200 by then.Tests that need actual rows open real Iceberg result tables, following the arrangement
ExecutionResultServiceSpecalready uses in amber unit tests. The section banner and class scaladoc described the request-level tests as stopping short of opening a result document, so they are updated to describe what these tests now do. No production code is changed.Any related issues, documentation, discussions?
Closes #7814
How was this PR tested?
All changes are new or extended unit tests in
ResultExportServiceSpec; run them withSTORAGE_ICEBERG_CATALOG_TYPE=postgres sbt "WorkflowExecutionService/testOnly org.apache.texera.web.service.ResultExportServiceSpec"— 60 succeeded, 0 failed, and the suite was verified idempotent by running twice back-to-back against the same catalog database. Key assertions were mutation-checked by hand-editing production code and confirming that exactly the intended tests fail: replacing theNonClosingOutputStreamwrapper with the raw stream, making the wrapper'sclose()close the underlying stream, skipping the empty-operator placeholder branch, dropping the zero-row half of both placeholder guards, forcing the ZIP dispatch to CSV, dropping the timestamp from the archive name, returning(null, None)instead of throwing when there is no execution, breaking the result-document lookup, removing theWarehouseReadGuardcheck, appending the dropped error lines to a partial-success response, cutting the CSV chunk loop to a single chunk, and resolving the oldest execution instead of the latest. Every mutation was reverted byte-exact afterwards, andscalafmtCheckpasses.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Fable 5, Claude Opus 5)