mirror of https://github.com/sbt/sbt.git
107 lines
3.3 KiB
Scala
107 lines
3.3 KiB
Scala
|
|
/* sbt -- Simple Build Tool
|
||
|
|
* Copyright 2012 Eugene Vigdorchik
|
||
|
|
*/
|
||
|
|
package sbt
|
||
|
|
|
||
|
|
import org.scalatools.testing._
|
||
|
|
import java.net.ServerSocket
|
||
|
|
import java.io._
|
||
|
|
import Tests._
|
||
|
|
import ForkMain._
|
||
|
|
|
||
|
|
private[sbt] object ForkTests {
|
||
|
|
def apply(frameworks: Seq[TestFramework], tests: List[TestDefinition], config: Execution, classpath: Seq[File], runner: ScalaRun, log: Logger): Task[Output] = {
|
||
|
|
val opts = config.options.toList
|
||
|
|
val listeners = opts flatMap {
|
||
|
|
case Listeners(ls) => ls
|
||
|
|
case _ => List.empty
|
||
|
|
}
|
||
|
|
val testListeners = listeners flatMap {
|
||
|
|
case tl: TestsListener => Some(tl)
|
||
|
|
case _ => None
|
||
|
|
}
|
||
|
|
val filters = opts flatMap {
|
||
|
|
case Filter(f) => Some(f)
|
||
|
|
case _ => None
|
||
|
|
}
|
||
|
|
val argMap = frameworks.map {
|
||
|
|
f => f.implClassName -> opts.flatMap {
|
||
|
|
case Argument(None, args) => args
|
||
|
|
case Argument(Some(`f`), args) => args
|
||
|
|
case _ => List.empty
|
||
|
|
}
|
||
|
|
}.toMap
|
||
|
|
|
||
|
|
std.TaskExtra.toTask {
|
||
|
|
val server = new ServerSocket(0)
|
||
|
|
object Acceptor extends Runnable {
|
||
|
|
val results = collection.mutable.Map.empty[String, TestResult.Value]
|
||
|
|
def output = (overall(results.values), results.toMap)
|
||
|
|
def run = {
|
||
|
|
val socketOpt = try {
|
||
|
|
Some(server.accept())
|
||
|
|
} catch {
|
||
|
|
case e: IOException => None
|
||
|
|
}
|
||
|
|
for (socket <- socketOpt) {
|
||
|
|
val os = new ObjectOutputStream(socket.getOutputStream)
|
||
|
|
val is = new ObjectInputStream(socket.getInputStream)
|
||
|
|
|
||
|
|
val testsFiltered = tests.filter(test => filters.forall(_(test.name))).map{
|
||
|
|
t => new ForkTestDefinition(t.name, t.fingerprint)
|
||
|
|
}.toArray
|
||
|
|
os.writeObject(testsFiltered)
|
||
|
|
|
||
|
|
os.writeInt(frameworks.size)
|
||
|
|
for ((clazz, args) <- argMap) {
|
||
|
|
os.writeObject(clazz)
|
||
|
|
os.writeObject(args.toArray)
|
||
|
|
}
|
||
|
|
|
||
|
|
@annotation.tailrec def react: Unit = is.readObject match {
|
||
|
|
case `TestsDone` => os.writeObject(TestsDone);
|
||
|
|
case Array(`ErrorTag`, s: String) => log.error(s); react
|
||
|
|
case Array(`WarnTag`, s: String) => log.warn(s); react
|
||
|
|
case Array(`InfoTag`, s: String) => log.info(s); react
|
||
|
|
case Array(`DebugTag`, s: String) => log.debug(s); react
|
||
|
|
case t: Throwable => log.trace(t); react
|
||
|
|
case tEvents: Array[Event] =>
|
||
|
|
for (first <- tEvents.headOption) listeners.foreach(_ startGroup first.testName)
|
||
|
|
val event = TestEvent(tEvents)
|
||
|
|
listeners.foreach(_ testEvent event)
|
||
|
|
for (first <- tEvents.headOption) {
|
||
|
|
val result = event.result getOrElse TestResult.Passed
|
||
|
|
results += first.testName -> result
|
||
|
|
listeners.foreach(_ endGroup (first.testName, result))
|
||
|
|
}
|
||
|
|
react
|
||
|
|
}
|
||
|
|
react
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
() => {
|
||
|
|
try {
|
||
|
|
testListeners.foreach(_.doInit())
|
||
|
|
val t = new Thread(Acceptor)
|
||
|
|
t.start()
|
||
|
|
|
||
|
|
val fullCp = classpath ++: Seq(IO.classLocationFile[ForkMain], IO.classLocationFile[Framework])
|
||
|
|
for (msg <- runner.run(classOf[ForkMain].getCanonicalName, fullCp, Seq(server.getLocalPort.toString), log)) {
|
||
|
|
log.error(msg)
|
||
|
|
server.close()
|
||
|
|
}
|
||
|
|
|
||
|
|
t.join()
|
||
|
|
val result = Acceptor.output
|
||
|
|
testListeners.foreach(_.doComplete(result._1))
|
||
|
|
result
|
||
|
|
} finally {
|
||
|
|
if (!server.isClosed) server.close()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|