Repository navigation
Conversation
The runner discovers the operators that implement the trait, configures each from its schema, runs it through the engine and through its generated script, and compares. An operator that cannot be run is reported as a row with the reason rather than passed over, since an operator missing from the report is a fact the report has to carry. `OperatorBehaviorSpec` is what turns that into tests: one per operator per configuration its schema offers, named so a single operator can be run alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8362 +/- ##
============================================
- Coverage 92.72% 92.72% -0.01%
- Complexity 4946 4950 +4
============================================
Files 1242 1243 +1
Lines 52671 52623 -48
Branches 6519 6506 -13
============================================
- Hits 48838 48793 -45
Misses 2214 2214
+ Partials 1619 1616 -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:
|
Three examples where one carries the point, and a cross-reference the reader can follow without being told to. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…erator's issue The row pointed at the issue for Substring Search and Unnest String, which this operator was never part of. That issue closes with the change that answers those two, and this one still raises. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The row said the platform raised on an empty cell. The operator answers one now, so the variant runs like every other. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…re in Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both had been withheld for drawing a different picture on every run, which stopped being true once their placement was seeded. The registration is inert until the operator implements the trait, so it can sit here rather than making the change that gives them their generator depend on this one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Which tier an operator lands in is the one thing the per-operator runs do not check, so it is what this spec is for. Every visualization, the scorer, an estimator and an advanced trainer each state where they route and why that is not the tier they used to be in. All of them land before this change does, so the assertions hold when it merges rather than needing to be added back afterwards. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One assertion per line, like every other test here. The loop it replaced was the only one of its kind in the file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One said the coverage report prints the withheld runs together. It no longer prints them, so what is left is the reason that does not depend on a reader: one table means the next exemption has an obvious home. The other pointed at `TransformHandler.unfillableVariants`, which does not exist. What it meant is `nullsKeepFilled`, the one thing a handler still says about its own table rather than about its operator. `withheldRunsFor` was public for the report that read it. Its only caller now is beside it, so it says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
carloea2
left a comment
There was a problem hiding this comment.
The transform verification runner looks good.
The configuration generator produces it; this is the label a withholding would have to name. A paragraph the one below it already carried goes with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
e450a54 to
f1e3d14
Compare
carloea2
left a comment
There was a problem hiding this comment.
Reviewed alongside the related export and verification PRs. These findings are based on code inspection and focused Python checks, not a full Scala suite run.
a8a3653 to
eb8b5aa
Compare
Every other verify spec runs one operator's fragment with the harness binding its placeholders, so a fault that only appears once fragments share a script and a directory has nowhere to show. Three of those are pinned here: a column named after a placeholder, two charts writing one file, and a branch that ends the process the other branches still need. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
eb8b5aa to
b052093
Compare
No withheld row names the hostile column run, and no row builds its label through the helper. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@carloea2 the finding is fixed: a connected plan is now translated and run end to end. Would you take another look when you have a moment? |
carloea2
left a comment
There was a problem hiding this comment.
The translated chain and branch tests now run through the real translator. Looks good.
carloea2
left a comment
There was a problem hiding this comment.
Visualization verification compares only one Plotly figure. Bullet and Gauge can produce one figure per input row, but standalone writes only the first figure. A wrong second figure can pass. Please compare every produced figure and add a multirow test.
carloea2
left a comment
There was a problem hiding this comment.
The only full plan Union test gives both inputs the same file. Wiring the first input twice and dropping the second still passes. Please use distinct input data and assert a value unique to each port.
carloea2
left a comment
There was a problem hiding this comment.
The full plan tests only create links from output port 0. A Split or If workflow can wire output port 1 incorrectly and every connected plan test still passes. Please add a connected plan that uses both output ports and verify each branch separately.
The union plan gave both of its inputs the same file, so a plan that wired one upstream twice and dropped the other read the same rows and passed. Each port now reads a file of its own, and the assertion is on the union's own frame rather than on everything the run printed: a dropped upstream is still a leaf of the plan, and printing that leaf puts its rows in stdout anyway. Every plan here also read its upstream's port 0, so a translator that handed each downstream the first frame its upstream produced would pass all of them. The new plan wires both of a split's output ports into branches of their own and reads each branch separately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A bullet or gauge chart draws a figure per input row: both paths put all of them on the page they render, but the exported script writes only the first to its output.json, and that file was the side being compared. Nine of the ten figures a run drew went unread, so a wrong one passed. Those two operators are now compared against the page, which is the side holding every figure. The ten agreed already, so this closes the hole rather than a defect. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
All three fixed: each union port now reads its own file and the assertion is on the union's own frame, a new plan wires both of a split's output ports and reads each branch separately, and the Plotly comparison now reads every figure a run drew rather than the first. That last one lands in #8359 and #8509, where compare.py and the comparator live. |
The epilogue writes a declared-integral column as an integer, the way the engine's writer does, and the schemas to go by are the ones this run already has in hand from the Texera path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
carloea2
left a comment
There was a problem hiding this comment.
The connected plan checks now cover the separate output routes and distinct source inputs. Looks good.
A table with no rows carries no columns in the engine, which is the design apache#8488 settled on. Candlestick, Contour, Scatter Matrix, Sort and Strip Chart read a column by name, so each raises on the empty table. The generated script reads the same empty file into the same columnless frame and raises the same error, which a forced run of the script confirmed for all five. Each row states that reason, the way the scorer's empty-table row already does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t keeps its columns The script is handed an empty input with its columns now, as an exported script is, so these operators no longer fail on both paths. The engine still hands them a table of no columns and they fail on the columns they read. The script handles the same empty table: Sort and the chart operators return an empty result, an empty chart or their own error page. The reason each row states says that instead. Bar Chart, Filled Area Plot and Network Graph join the rows for the same reason. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sklearn Prediction and Sklearn Testing were withheld because a JSONL fixture could not carry a fitted model. Both paths now unpickle a model cell the way the worker does, and their curated fixtures carry one. The model comparison predicts on the first port without a BINARY column. It took port 0, which for these two is the model itself. Testing's isRegression is not swept, since it has to match the model the port carries; a regression scenario covers the other branch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…very bullet and gauge figure Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@carloea2 Since your approval the canonical table carries edge values (doubles Java writes in E notation, years outside pandas' range, digit strings), and Bullet and Gauge are compared by every figure they write. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
carloea2
left a comment
There was a problem hiding this comment.
Read the runner, routing rules and whole-plan tests. With the exact prerequisite implementations supplied locally, 41 tests pass: 29 canonical-fixture checks, all 8 translated plans, and 4 executions through the actual runner. Those exercise native and generated Limit and Union variants, plus real Python UDF and exported Pie and Contour variants, including nulls, empty input and error pages. Formatting passes.
sbt -batch 'WorkflowCompilingService/testOnly *CanonicalFixtureSpec *TranslatedPlanRunSpec *RunnerExecutionReviewSpec -- -oDF' 'scalafmtCheckAll'
No new runner-specific finding. The branch alone cannot compile yet, and the other routing assertions still need their operator export prerequisites. This is not merge ready until those and CI are cleared.
…ts DOUBLE columns A specialDoubles run beside nulls and emptyTable. Withheld, with the reason, for the 56 sklearn operators and the three charts whose library refuses a NaN or an infinity on both paths; the two dummy classifiers never read a feature and run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every withheld run is ByDesign now; nothing reads PendingFix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The six plans that the engine can also run move from TranslatedPlanRunSpec to amber's WorkflowParitySpec, which runs each in the engine and compares every leaf with the script's. File Scan, which needs an upstream to name its files, joins them. The two plans only the script can answer stay where they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@carloea2 the end-to-end layer now also runs each plan in the Texera engine and compares every leaf with the script's output ( |
A withheld run whose reason is that both paths raise now runs, and passes only when each does: a script that answers where the engine refuses is as wrong as a different answer. Every such row held, but one: the dummy classifier fits on nothing, into a model that cannot predict, so its empty table stays withheld with that reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
They run, so the list of runs not run was the wrong home for them. Each list now says what it holds: variantsNotRun the runs that cannot be set up, variantsBothRefuse the runs both paths must refuse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read over the shared table's JSON, an archive or a typed line has no answer, so both paths must refuse those. A large binary needs object storage, which the harness does not give the executor, so it is not run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What changes were proposed in this PR?
The runner discovers the operators that implement the trait, configures each
from its schema, runs it through the engine and through its generated script,
and compares. An operator that cannot be run is reported as a row with the
reason rather than passed over, since an operator missing from the report is
a fact the report has to carry.
OperatorBehaviorSpecis what turns that into tests: one per operator perconfiguration its schema offers, named so a single operator can be run alone.
Every operator reads one canonical table, and it now also carries the values a type reaches only at its edges. That means a double at 1e7 and past it, and one under 1e-3, which Java writes in E notation. It means timestamps in 1600, 2262, 2500 and 9999, outside pandas' nanosecond range. And it means text of digits with leading zeros, which a reader must not take for a number. Without them, a difference that only shows at those values is never asked about.
Bullet and Gauge are compared by the figures their script writes, now that it writes every one rather than the first.
A whole workflow is compared too.
WorkflowParitySpec, in amber's integration tests, runs each plan in the engine and through its translated script, and compares every leaf. Rows compare as a set unless the leaf's operator declares an order, since the engine runs most operators on several workers. The plans are the ones aimed at how fragments go wrong together: a chain, a holed integer column, a cast timestamp, a Union, both branches of a Split, a column named like a placeholder, and File Scan reading the paths its upstream names.TranslatedPlanRunSpeckeeps the two the engine has nothing to compare with: two charts in one plan, and a chart that cannot be drawn.amber's tests take the compiling service's and workflow-operator's classes and test resources, not the modules themselves. The compiling service brings dropwizard 4, which would evict the dropwizard 1 amber is built on.
Runs whose reason is that both paths raise are no longer skipped. They sit in their own list,
variantsBothRefuse, run like any other, and pass only when the engine and the script both refuse, since a script that answers where the engine refuses is as wrong as a different answer. Only a run named there may pass on two errors, so a broken environment cannot turn the suite green. The one exception found is the dummy classifier on an empty table: it fits on nothing into a model that cannot predict, so it stays invariantsNotRunwith that reason. File Scan reads the canonical table's own JSON, which both paths refuse as an archive and as a typed line, so those variants are listed there too. Its archives and typed lines are compared on real files, in the scenarios #8364 and #8363 add. A large binary is written to object storage, which the harness does not give the executor, so that variant is invariantsNotRun.Any related issues, documentation, discussions?
Part of #8325, 23 of 27; that issue lists the set in order. The edge values pass only once #8341, #8704, #8357, #8709, #8710 and #8597 are in. Each of those fixes how one path reads or writes them. All of them come earlier in the set or merge before it. An empty table runs on every operator once #8766 is in, which hands a port that carried no rows its declared columns.
Closes #8425, the task this change is the whole of.
The workflow-level comparison answers the review that asked for plans run end to end. It calls
runTranslatedfrom #8358.How was this PR tested?
The tests in this change cover it. The whole set is exercised together once the last piece lands: every operator run through the engine and through its generated script, and the two answers compared.
Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5, Claude Opus 5.5)