Skip to content

Commit ea09ba2

Browse files
committed
Add synchronization when sending events to sbt (fix ArrayIOBException).
Partest shows a single `Task` to sbt and does all the concurrency and running subtasks itself, which isn't really how this should work, so sbt doesn't expect the task to send back events concurrently: `EventHandler.handle` adds events to an `ArrayList` when forking (see [ForkMain][2]), and is called after each test, and if it happens on two threads at exactly the wrong moment: ``` Caused by: sbt.ForkMain$ForkError: java.lang.ArrayIndexOutOfBoundsException: 15 at java.util.ArrayList.add(ArrayList.java:459) at sbt.ForkMain$Run$2$1.handle(ForkMain.java:294) at scala.tools.partest.sbt.SBTRunner$$anon$1.onFinishTest(SBTRunner.scala:70) at scala.tools.partest.nest.SuiteRunner.runTest(Runner.scala:781) at scala.tools.partest.nest.SuiteRunner.$anonfun$runTestsForFiles$2(Runner.scala:788) at scala.tools.partest.package$$anon$2.call(package.scala:135) ``` See scala/scala#5663 ([build log][1] or the failed run). [1]: https://scala-ci.typesafe.com/job/scala-2.12.x-validate-test/4300/consoleFull [2]: https://github.com/sbt/sbt/blob/v0.13.13/testing/agent/src/main/java/sbt/ForkMain.java#L294
1 parent d150e65 commit ea09ba2

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

src/partest/scala/tools/partest/sbt/SBTRunner.scala

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,18 @@ class SBTRunner(val config: RunnerSpec.Config,
6464
javacCmdPath = Option(javacCmd).map(_.getAbsolutePath) getOrElse PartestDefaults.javacCmd,
6565
scalacExtraArgs = scalacArgs,
6666
javaOpts = javaOpts,
67-
scalacOpts = scalacOpts) {
67+
scalacOpts = scalacOpts) { self =>
6868

6969
override def onFinishTest(testFile: File, result: TestState): TestState = {
70-
eventHandler.handle(new Event {
71-
def fullyQualifiedName: String = testFile.testIdent
72-
def fingerprint: Fingerprint = partestFingerprint
73-
def selector: Selector = new TestSelector(testFile.testIdent)
74-
val (status, throwable) = makeStatus(result)
75-
def duration: Long = -1
76-
})
70+
self.synchronized {
71+
eventHandler.handle(new Event {
72+
def fullyQualifiedName: String = testFile.testIdent
73+
def fingerprint: Fingerprint = partestFingerprint
74+
def selector: Selector = new TestSelector(testFile.testIdent)
75+
val (status, throwable) = makeStatus(result)
76+
def duration: Long = -1
77+
})
78+
}
7779
result
7880
}
7981
}

0 commit comments

Comments
 (0)