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

aglinxinyuan 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 71812eb2bb test(amber): add unit test coverage for Schedule iterator 
semantics (#4562)
71812eb2bb is described below

commit 71812eb2bb7c38f5b2a0c86c46e2383c75bbecc9
Author: Xinyuan Lin <[email protected]>
AuthorDate: Sat May 2 02:04:19 2026 -0700

    test(amber): add unit test coverage for Schedule iterator semantics (#4562)
    
    ### What changes were proposed in this PR?
    
    Add `ScheduleSpec` covering the iterator semantics of `Schedule`
    
(`amber/src/main/scala/org/apache/texera/amber/engine/architecture/scheduling/Schedule.scala`):
    
    - `getRegions` flattens all level sets across the map
    - Iteration order follows ascending level keys, starting from the
    minimum
    - `hasNext` / `next()` semantics including empty schedule, exhaustion,
    and non-zero starting level keys
    - Gap-stop behavior on non-contiguous level keys
    
    ### Any related issues, documentation, discussions?
    
    Closes #4561
    
    ### How was this PR tested?
    
    `sbt "WorkflowExecutionService/testOnly
    org.apache.texera.amber.engine.architecture.scheduling.ScheduleSpec"` —
    7/7 tests pass.
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Claude Opus 4.7)
    
    ---------
    
    Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
---
 .../architecture/scheduling/ScheduleSpec.scala     | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git 
a/amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/ScheduleSpec.scala
 
b/amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/ScheduleSpec.scala
new file mode 100644
index 0000000000..81ca54c1dd
--- /dev/null
+++ 
b/amber/src/test/scala/org/apache/texera/amber/engine/architecture/scheduling/ScheduleSpec.scala
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.texera.amber.engine.architecture.scheduling
+
+import org.apache.texera.amber.core.executor.OpExecInitInfo
+import org.apache.texera.amber.core.virtualidentity.{
+  ExecutionIdentity,
+  OperatorIdentity,
+  PhysicalOpIdentity,
+  WorkflowIdentity
+}
+import org.apache.texera.amber.core.workflow.PhysicalOp
+import org.scalatest.flatspec.AnyFlatSpec
+
+class ScheduleSpec extends AnyFlatSpec {
+
+  private def region(regionId: Long, opId: String): Region = {
+    val physicalOp = PhysicalOp(
+      PhysicalOpIdentity(OperatorIdentity(opId), "main"),
+      WorkflowIdentity(0),
+      ExecutionIdentity(0),
+      OpExecInitInfo.Empty
+    )
+    Region(RegionIdentity(regionId), Set(physicalOp), Set.empty)
+  }
+
+  "Schedule.getRegions" should "return all regions across all levels" in {
+    val r0 = region(0, "a")
+    val r1a = region(1, "b")
+    val r1b = region(2, "c")
+    val schedule = Schedule(Map(0 -> Set(r0), 1 -> Set(r1a, r1b)))
+
+    assert(schedule.getRegions.toSet == Set(r0, r1a, r1b))
+  }
+
+  it should "return an empty list when the schedule is empty" in {
+    assert(Schedule(Map.empty).getRegions.isEmpty)
+  }
+
+  "Schedule" should "iterate level sets in ascending key order starting from 
the minimum level" in {
+    val r0 = region(0, "a")
+    val r1 = region(1, "b")
+    val r2 = region(2, "c")
+    val schedule = Schedule(Map(1 -> Set(r1), 0 -> Set(r0), 2 -> Set(r2)))
+
+    assert(schedule.toList == List(Set(r0), Set(r1), Set(r2)))
+  }
+
+  it should "report hasNext as false for an empty schedule" in {
+    assert(!Schedule(Map.empty).hasNext)
+  }
+
+  it should "report hasNext as false after the last contiguous level is 
consumed" in {
+    val schedule = Schedule(Map(0 -> Set(region(0, "a")), 1 -> Set(region(1, 
"b"))))
+    schedule.next()
+    schedule.next()
+    assert(!schedule.hasNext)
+  }
+
+  it should "reject construction when level keys contain a gap" in {
+    assertThrows[IllegalArgumentException] {
+      Schedule(Map(0 -> Set(region(0, "a")), 2 -> Set(region(2, "b"))))
+    }
+  }
+
+  it should "reject construction when level keys do not start at zero" in {
+    assertThrows[IllegalArgumentException] {
+      Schedule(Map(3 -> Set(region(3, "a")), 4 -> Set(region(4, "b"))))
+    }
+  }
+
+}

Reply via email to