You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/07/05 07:44:44 UTC

(texera) branch main updated: test(amber): cover WorkflowExecution.getState PAUSED and UNKNOWN branches (#6140)

This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git


The following commit(s) were added to refs/heads/main by this push:
     new 92b7fc9168 test(amber): cover WorkflowExecution.getState PAUSED and UNKNOWN branches (#6140)
92b7fc9168 is described below

commit 92b7fc9168d79379a4871b9c9fd80fcb9df75041
Author: Xinyuan Lin <xi...@uci.edu>
AuthorDate: Sun Jul 5 00:35:05 2026 -0700

    test(amber): cover WorkflowExecution.getState PAUSED and UNKNOWN branches (#6140)
    
    ### What changes were proposed in this PR?
    
    Extends `WorkflowExecutionSpec` to cover the two
    `WorkflowExecution.getState` branches the existing spec never exercised:
    
    - **PAUSED** — a running region whose operators are all paused;
    - **UNKNOWN** — a running operator with mixed worker states (one paused,
    one ready) that aggregates to `UNKNOWN`.
    
    Both are driven with the spec's existing region/operator/worker
    construction (a region carrying an incomplete port keeps its
    `RegionExecution` in `RUNNING`, so operator states are actually
    inspected). The `READY` return branch is intentionally not tested — it
    is dead code, since all-ready workers aggregate to `RUNNING`, so
    `OperatorExecution.getState` never returns `READY`.
    
    No production code is changed; this is test-only.
    
    ### Any related issues, documentation, discussions?
    
    Coverage gaps identified from the Codecov report for `apache/texera`.
    
    ### How was this PR tested?
    
    Extended ScalaTest spec, run locally:
    
    ```
    sbt "WorkflowExecutionService/testOnly *WorkflowExecutionSpec"
    ```
    
    All 14 pass. `scalafmt` and `scalafixAll --check` are clean.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.8 [1M context])
---
 .../execution/WorkflowExecutionSpec.scala          | 48 +++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/amber/src/test/scala/org/apache/texera/amber/engine/architecture/coordinator/execution/WorkflowExecutionSpec.scala b/amber/src/test/scala/org/apache/texera/amber/engine/architecture/coordinator/execution/WorkflowExecutionSpec.scala
index 2bb9391332..d61ac8799b 100644
--- a/amber/src/test/scala/org/apache/texera/amber/engine/architecture/coordinator/execution/WorkflowExecutionSpec.scala
+++ b/amber/src/test/scala/org/apache/texera/amber/engine/architecture/coordinator/execution/WorkflowExecutionSpec.scala
@@ -21,14 +21,16 @@ package org.apache.texera.amber.engine.architecture.coordinator.execution
 
 import org.apache.texera.amber.core.executor.OpExecInitInfo
 import org.apache.texera.amber.core.virtualidentity.{
+  ActorVirtualIdentity,
   ExecutionIdentity,
   OperatorIdentity,
   PhysicalOpIdentity,
   WorkflowIdentity
 }
-import org.apache.texera.amber.core.workflow.PhysicalOp
+import org.apache.texera.amber.core.workflow.{GlobalPortIdentity, PhysicalOp, PortIdentity}
 import org.apache.texera.amber.engine.architecture.rpc.controlreturns.WorkflowAggregatedState
 import org.apache.texera.amber.engine.architecture.scheduling.{Region, RegionIdentity}
+import org.apache.texera.amber.engine.architecture.worker.statistics.WorkerState
 import org.scalatest.flatspec.AnyFlatSpec
 
 class WorkflowExecutionSpec extends AnyFlatSpec {
@@ -48,6 +50,26 @@ class WorkflowExecutionSpec extends AnyFlatSpec {
   private def region(regionId: Long, opId: String): Region =
     Region(RegionIdentity(regionId), Set(op(opId)), Set.empty)
 
+  /**
+    * A region carrying a single (input) port on `opId`. Because a freshly created
+    * `WorkerPortExecution` stays `completed = false`, the region's
+    * `RegionExecution.getState` remains RUNNING (never short-circuits to COMPLETED),
+    * so its operators' states are actually inspected by `WorkflowExecution.getState`.
+    */
+  private def regionWithPort(regionId: Long, opId: String): Region =
+    Region(
+      RegionIdentity(regionId),
+      Set(op(opId)),
+      Set.empty,
+      ports = Set(
+        GlobalPortIdentity(
+          opId = physicalOpId(opId),
+          portId = PortIdentity(id = 0, internal = false),
+          input = true
+        )
+      )
+    )
+
   "WorkflowExecution.initRegionExecution" should "create a new RegionExecution for the given region" in {
     val we = WorkflowExecution()
     val r = region(1, "a")
@@ -143,6 +165,30 @@ class WorkflowExecutionSpec extends AnyFlatSpec {
     assert(we.isCompleted)
   }
 
+  it should "return PAUSED when the only running region's operators are all paused" in {
+    val we = WorkflowExecution()
+    val regionExecution = we.initRegionExecution(regionWithPort(0, "a"))
+
+    val operatorExecution = regionExecution.initOperatorExecution(physicalOpId("a"))
+    val workerExecution = operatorExecution.initWorkerExecution(ActorVirtualIdentity("w0"))
+    workerExecution.update(1L, WorkerState.PAUSED)
+
+    assert(we.getState == WorkflowAggregatedState.PAUSED)
+    assert(!we.isCompleted)
+  }
+
+  it should "return UNKNOWN when a running operator has mixed worker states" in {
+    val we = WorkflowExecution()
+    val regionExecution = we.initRegionExecution(regionWithPort(0, "a"))
+
+    val operatorExecution = regionExecution.initOperatorExecution(physicalOpId("a"))
+    operatorExecution.initWorkerExecution(ActorVirtualIdentity("w0")).update(1L, WorkerState.PAUSED)
+    operatorExecution.initWorkerExecution(ActorVirtualIdentity("w1")).update(1L, WorkerState.READY)
+
+    assert(we.getState == WorkflowAggregatedState.UNKNOWN)
+    assert(!we.isCompleted)
+  }
+
   "WorkflowExecution.getLatestOperatorExecutionOption" should "return None when no operator execution exists for the id" in {
     val we = WorkflowExecution()
     we.initRegionExecution(region(0, "a"))