mengw15 opened a new issue, #8104:
URL: https://github.com/apache/texera/issues/8104
### Task Summary
`SyncExecutionResource` is at **76.1 % with 72 uncovered lines**. Most of
that is the reactive wiring around a live execution, but a self-contained group
is not: the pre-flight workflow validation, the error classifier that decides
whether a failure was a compilation problem, the request-limit caps, and the
two teardown helpers. All of them are reachable without starting an engine —
the same way #8035 covered `WorkflowExecutionService`, by handing the compiler
a workflow that cannot compile.
Pure EXTEND of `SyncExecutionResourceSpec`.
### Behavior to add
**`SyncExecutionResource`**
(`amber/src/main/scala/org/apache/texera/web/resource/SyncExecutionResource.scala`,
codecov 76.1 % — EXTEND)
- **`validateWorkflow`** (905–925) — compiles a `LogicalPlanPojo` against a
fresh `WorkflowContext` and returns `Map.empty` when it succeeds. When
compilation throws it builds a one-entry map:
- `errorMsg` comes from `Option(e.getMessage).getOrElse("Compilation
failed")` — cover a failure whose message is `null` so the literal fallback is
used;
- the operator id is extracted with `"""operator[- ]?(\S+)""".r` from the
lower-cased message — cover a message that names an operator (both the
`operator foo` and `operator-foo` spellings, since the pattern allows an
optional separator) and one that does not, so the `"workflow"` fallback is
taken.
Drive the failure with a plan that genuinely cannot compile — a scan
source with no file selected is enough, and needs no fixtures on disk.
- **`handleExecutionError`** (490–496) — `isCompilationError` is `errorMsg
!= null && (contains "compilation" || "Compilation" || "operator" ||
"schema")`. Each clause needs its own message to be taken: pass an exception
per keyword, one whose message matches none of them, and one whose message is
`null` so the null-guard short-circuits. Assert the resulting
`SyncExecutionResult` classifies the failure correctly in each case.
- **Request limit caps** (144–146) — `maxOperatorResultCellCharLimit` is
`Math.min(request.maxOperatorResultCellCharLimit,
MAX_OPERATOR_RESULT_CELL_CHARS)`, and the sibling `maxOperatorResultCharLimit`
is capped the same way. Cover a request below the cap (value passes through)
and one above it (value is clamped).
- **`shutdownPreviousExecution`** (350–360) — the guard `previousEs != null
&& previousEs.client != null`. Cover: no previous execution; a previous
execution with a null client; one with a live client that is shut down. Then
cover the `catch` arm by making `shutdown()` throw, and assert the failure is
swallowed and logged rather than propagating.
- **`killExecution`** (363–380) — the `if (executionService.client != null)`
guard, the two state-store updates (end timestamp, and the metadata store
moving to `KILLED`), and the `catch` arm when one of them throws. Assert the
recorded state rather than the log line.
Determinism notes:
- Mock the client and the execution/state stores; never start an
`AmberClient` or a real execution.
- `killExecution` stamps `System.currentTimeMillis()` — assert that an end
timestamp was set, never its value.
- Assert on the returned `SyncExecutionResult` fields and the state stores,
not on logger output.
- Keep each case self-contained: build its own request and stores rather
than sharing mutable fixtures across tests.
Out of scope: `targetResultsObservable`, `terminalStateObservable` and
`consoleErrorObservable` (242–298) — that is the reactive wiring around a
running execution and belongs to the integration tier.
### Task Type
- [ ] Refactor / Cleanup
- [ ] DevOps / Deployment / CI
- [x] Testing / QA
- [ ] Documentation
- [ ] Performance
- [ ] Other
--
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]