IntervalOpExecSpec uses an unseeded global Random, making failures unreproducible

Open Beginner friendly
#8,150 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
86/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
scala
Domain
testing-qa

Research direction

Start with common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/intervalJoin/IntervalOpExecSpec.scala, especially the Random import and uses at lines 243, 244, 486, 487, and 495. Run WorkflowOperator/jacoco twice as described, excluding FileScanSourceOpExec, and compare the IntervalJoinOpExec.scala branch counters. Done means the spec retains varied inputs while repeated runs produce reproducible results.

Written by the indexing model from the issue text.

Description

What happened?

IntervalOpExecSpec drives its inputs from the global, unseeded scala.util.Random, so its execution path — and therefore its branch coverage — differs from run to run.

import scala.util.Random.{nextInt, nextLong}
...
val leftOrder  = LazyList.continually(nextInt(10)).take(leftInput.length).toList
val rightOrder = LazyList.continually(nextInt(10)).take(rightInput.length).toList
...
val pointList: Array[Long] = LazyList.continually(nextLong()).take(1000).toArray
val rangeList: Array[Long] = LazyList.continually(nextLong()).take(1000).toArray

scala.util.Random used this way is the shared singleton with no seed, so nothing is reproducible.

Two consequences.

The one that is merely annoying: WorkflowOperator's module-wide branch totals are not stable. Two WorkflowOperator/jacoco runs on the same tree, differing only in an unrelated spec, reported IntervalJoinOpExec.scala at 21 and then 22 missed branch arms. That was isolated by diffing every <sourcefile> between the two reports. Anyone quoting module-wide arm counts from a single run can be off by a few, through no fault of their change.

The one that matters more: a genuine failure here may not reproduce. If an ordering or a nextLong() value trips a real bug in the interval-join logic, the run that catches it cannot be replayed, and a re-run will very likely go green.

The fix is small — seed a local generator, e.g. val rng = new scala.util.Random(42) and use rng.nextInt / rng.nextLong — which keeps the input variety while making every run reproducible.

Note the spec filename is IntervalOpExecSpec.scala, not IntervalJoinOpExecSpec.scala, so a search keyed on the class name misses it.

How to reproduce?
  1. common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/intervalJoin/IntervalOpExecSpec.scala:31 — the import scala.util.Random.{nextInt, nextLong}, then uses at lines 243, 244, 486, 487 and 495.
  2. Run WorkflowOperator/jacoco twice on an unchanged tree, one fresh sbt JVM each, removing common/workflow-operator/target/scala-2.13/jacoco between runs. Compare the <counter type="BRANCH"> figures for IntervalJoinOpExec.scala in the two jacoco.xml reports; they differ between runs.

Exclude FileScanSourceOpExecSpec when doing this — it aborts at suite level on Windows in its own cleanup, and because sbt-jacoco runs unforked and skips saveRuntimeData when the test task fails, an unfiltered run emits an all-zero report rather than a partial one.

Version/Branch

1.3.0-incubating-SNAPSHOT (main)

Was this issue authored using generative AI tooling?

Generated-by: Claude Code (Opus 5)

Dominant language
Scala
Stars
316
Forks
189
Avg merge
2d 20h
Merged PRs (30d)
198

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from apache/texera

All issues in apache/texera

Similar issues

More Scala issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.