Skip to content

test(amber): add unit test coverage for EmptyReplayLogger and ReplayLogGenerator#5554

Open
aglinxinyuan wants to merge 1 commit into
apache:mainfrom
aglinxinyuan:test-empty-replay-logger-and-replay-log-generator
Open

test(amber): add unit test coverage for EmptyReplayLogger and ReplayLogGenerator#5554
aglinxinyuan wants to merge 1 commit into
apache:mainfrom
aglinxinyuan:test-empty-replay-logger-and-replay-log-generator

Conversation

@aglinxinyuan

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Pin behavior of two previously-uncovered modules in engine/architecture/logreplay. No production-code changes.

Spec Source class Tests
EmptyReplayLoggerSpec EmptyReplayLogger 9
ReplayLogGeneratorSpec ReplayLogGenerator 10

Both spec files follow the <srcClassName>Spec.scala one-to-one convention.

Behavior pinned — EmptyReplayLogger

Surface Contract
drainCurrentLogRecords(step) returns an empty Array[ReplayLogRecord] regardless of step (positive, zero, Long.MaxValue, negative); returns a non-null array; element type is ReplayLogRecord (compile-time enforced)
markAsReplayDestination no-op for any EmbeddedControlMessageIdentity; does not accumulate state
logCurrentStepWithMessage no-op for any (step, channelId, msg) triple, including msg = None and 100 successive calls
Trait conformance usable through the ReplayLogger interface

Behavior pinned — ReplayLogGenerator.generate

Surface Contract
getStorage(None) (EmptyRecordStorage) returns (empty queue, empty queue)
empty VFSRecordStorage file returns (empty queue, empty queue)
only ProcessingStep records enqueues all into the steps queue, preserving insertion order
only MessageContent records enqueues all into the messages queue, preserving insertion order
interleaved steps + messages partitions correctly by type, preserving per-type order
ReplayDestination(id) matching replayTo short-circuits — records after the cut are NOT enqueued
ReplayDestination(id) NOT matching replayTo is silently skipped, iteration continues
multiple matching ReplayDestination stops at the FIRST one
unknown record type (e.g. TerminateSignal) throws RuntimeException with a diagnostic message

Notes

While writing ReplayLogGeneratorSpec I discovered a production stream-leak in ReplayLogGenerator.generate: when it hits the matching ReplayDestination it short-circuits via a non-local return, leaving the SequentialRecordReader's underlying Input stream open. On Windows the leaked file handle blocks subsequent temp-dir deletion. The spec's cleanup helper tolerates the resulting FileSystemException so the case still passes; the real fix is at the source and is out of scope for a test-coverage PR (will file a follow-up issue).

ReplayLogGeneratorSpec uses a temp-dir-backed VFSRecordStorage[ReplayLogRecord] and the production AmberRuntime.serde (suite-local ActorSystem injected via reflection, torn down in afterAll) — same harness pattern as CheckpointSubsystemSpec / ClientEventSpec / VFSRecordStorageSpec.

Any related issues, documentation, discussions?

Closes #5550.

How was this PR tested?

Pure unit-test additions; verified locally with:

  • sbt "WorkflowExecutionService/testOnly org.apache.texera.amber.engine.architecture.logreplay.EmptyReplayLoggerSpec org.apache.texera.amber.engine.architecture.logreplay.ReplayLogGeneratorSpec" — 19 tests, all green
  • sbt scalafmtCheckAll — clean
  • CI to confirm

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Sonnet 4.5)

…ogGenerator

Pins behavior of two previously-uncovered modules in
`engine/architecture/logreplay`:
  - `EmptyReplayLogger` — null-object ReplayLogger whose drain returns
    an empty array and whose log/markAsReplayDestination are no-ops
  - `ReplayLogGenerator` — pure decoder that partitions stored records
    into (steps, messages) queues and short-circuits at the matching
    ReplayDestination

Closes apache#5550
Copilot AI review requested due to automatic review settings June 8, 2026 00:01
@github-actions github-actions Bot added the engine label Jun 8, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds ScalaTest unit coverage for two previously-untested log replay components under amber/engine/architecture/logreplay, pinning expected behavior without modifying production code.

Changes:

  • Add EmptyReplayLoggerSpec to verify the null-object logger remains a no-op and always returns an empty Array[ReplayLogRecord].
  • Add ReplayLogGeneratorSpec to validate ReplayLogGenerator.generate partitions records correctly, handles replay-destination cut semantics, and throws on unknown record types.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
amber/src/test/scala/org/apache/texera/amber/engine/architecture/logreplay/ReplayLogGeneratorSpec.scala New unit spec covering record partitioning, replay cut semantics, and error behavior for ReplayLogGenerator.generate using temp-dir-backed storage.
amber/src/test/scala/org/apache/texera/amber/engine/architecture/logreplay/EmptyReplayLoggerSpec.scala New unit spec pinning no-op behavior and return-type/trait conformance for EmptyReplayLogger.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +54 to +71
private def setAmberRuntimeField(name: String, value: AnyRef): Unit = {
val field = AmberRuntime.getClass.getDeclaredField(name)
field.setAccessible(true)
field.set(AmberRuntime, value)
}

override protected def beforeAll(): Unit = {
super.beforeAll()
setAmberRuntimeField("_actorSystem", testSystem)
setAmberRuntimeField("_serde", testSerde)
}

override protected def afterAll(): Unit = {
setAmberRuntimeField("_serde", null)
setAmberRuntimeField("_actorSystem", null)
TestKit.shutdownActorSystem(testSystem)
super.afterAll()
}
.sorted(java.util.Comparator.reverseOrder())
.forEach { child =>
try Files.deleteIfExists(child)
catch { case _: java.nio.file.FileSystemException => () }
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.16%. Comparing base (afc5f98) to head (4b4d8e9).
⚠️ Report is 2 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5554      +/-   ##
============================================
+ Coverage     52.09%   52.16%   +0.06%     
- Complexity     2471     2484      +13     
============================================
  Files          1067     1067              
  Lines         41273    41273              
  Branches       4437     4437              
============================================
+ Hits          21502    21528      +26     
+ Misses        18509    18483      -26     
  Partials       1262     1262              
Flag Coverage Δ *Carryforward flag
access-control-service 64.61% <ø> (ø) Carriedforward from afc5f98
agent-service 33.76% <ø> (ø) Carriedforward from afc5f98
amber 53.28% <ø> (+0.16%) ⬆️
computing-unit-managing-service 1.65% <ø> (ø) Carriedforward from afc5f98
config-service 56.06% <ø> (ø) Carriedforward from afc5f98
file-service 38.32% <ø> (ø) Carriedforward from afc5f98
frontend 46.40% <ø> (ø) Carriedforward from afc5f98
pyamber 90.69% <ø> (ø) Carriedforward from afc5f98
python 90.83% <ø> (ø) Carriedforward from afc5f98
workflow-compiling-service 58.69% <ø> (ø) Carriedforward from afc5f98

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aglinxinyuan aglinxinyuan requested a review from Yicong-Huang June 8, 2026 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add unit test coverage for EmptyReplayLogger and ReplayLogGenerator

3 participants