Merge pull request #3997 from eed3si9n/wip/test-status-thread-safety

Fix race condition in non-forked, parallel tests.
This commit is contained in:
eugene yokota 2018-03-07 16:18:55 -05:00 committed by GitHub
commit 92c95ce290
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 7 deletions

View File

@ -214,6 +214,11 @@ lazy val testingProj = (project in file("testing"))
sourceManaged in (Compile, generateContrabands) := baseDirectory.value / "src" / "main" / "contraband-scala",
contrabandFormatsForType in generateContrabands in Compile := ContrabandConfig.getFormats,
mimaSettings,
mimaBinaryIssueFilters ++= Seq(
// private[sbt]
ProblemFilters.exclude[IncompatibleMethTypeProblem]("sbt.TestStatus.write"),
ProblemFilters.exclude[IncompatibleResultTypeProblem]("sbt.TestStatus.read"),
),
)
.configure(addSbtIO, addSbtCompilerClasspath, addSbtUtilLogging)

View File

@ -63,7 +63,8 @@ private[sbt] object Server {
val maxSocketLength = new UnixDomainSocketLibrary.SockaddrUn().sunPath.length - 1
val path = socketfile.getAbsolutePath
if (path.length > maxSocketLength)
sys.error("socket file absolute path too long; " +
sys.error(
"socket file absolute path too long; " +
"either switch to another connection type " +
"or define a short \"SBT_GLOBAL_SERVER_DIR\" value. " +
s"Current path: ${path}")

View File

@ -8,14 +8,16 @@
package sbt
import java.io.File
import sbt.io.IO
import scala.collection.mutable.Map
import sbt.io.IO
import sbt.protocol.testing.TestResult
import java.util.concurrent.ConcurrentHashMap
import scala.collection.concurrent
// Assumes exclusive ownership of the file.
private[sbt] class TestStatusReporter(f: File) extends TestsListener {
private lazy val succeeded = TestStatus.read(f)
private lazy val succeeded: concurrent.Map[String, Long] = TestStatus.read(f)
def doInit = ()
def startGroup(name: String): Unit = { succeeded remove name; () }
@ -32,13 +34,16 @@ private[sbt] class TestStatusReporter(f: File) extends TestsListener {
private[sbt] object TestStatus {
import java.util.Properties
def read(f: File): Map[String, Long] = {
def read(f: File): concurrent.Map[String, Long] = {
import scala.collection.JavaConverters._
val properties = new Properties
IO.load(properties, f)
properties.asScala map { case (k, v) => (k, v.toLong) }
val result = new ConcurrentHashMap[String, Long]()
properties.asScala.iterator.foreach { case (k, v) => result.put(k, v.toLong) }
result.asScala
}
def write(map: Map[String, Long], label: String, f: File): Unit = {
def write(map: collection.Map[String, Long], label: String, f: File): Unit = {
val properties = new Properties
for ((test, lastSuccessTime) <- map)
properties.setProperty(test, lastSuccessTime.toString)