summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2009-01-08 09:36:09 +0000
committerPhilipp Haller <hallerp@gmail.com>2009-01-08 09:36:09 +0000
commit0313e1c018d89fc4e4474f42308e81cfc60fdfb6 (patch)
tree37e33ed25e2baf713b3ac3c9e5b83718a3ea86ba /src
parent166563559ba72f3e2e0309396261030c14effe4d (diff)
downloadscala-0313e1c018d89fc4e4474f42308e81cfc60fdfb6.tar.gz
scala-0313e1c018d89fc4e4474f42308e81cfc60fdfb6.tar.bz2
scala-0313e1c018d89fc4e4474f42308e81cfc60fdfb6.zip
Fix timeout problem in partest
Diffstat (limited to 'src')
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala70
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala6
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala247
3 files changed, 160 insertions, 163 deletions
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index a8eb044629..d61e0af51b 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -155,10 +155,6 @@ class ReflectiveCompiler(val fileManager: ConsoleFileManager) extends SimpleComp
}
class CompileManager(val fileManager: FileManager) {
-
- import scala.actors.Actor._
- import scala.actors.{Actor, Exit, TIMEOUT}
-
var compiler: SimpleCompiler = new /*ReflectiveCompiler*/ DirectCompiler(fileManager)
var numSeparateCompilers = 1
@@ -167,71 +163,37 @@ class CompileManager(val fileManager: FileManager) {
compiler = new /*ReflectiveCompiler*/ DirectCompiler(fileManager)
}
- val delay = fileManager.timeout.toLong
-
- def withTimeout(files: List[File])(thunk: => Boolean): Boolean = {
- createSeparateCompiler()
-
- val parent = self
- self.trapExit = true
- val child = link {
- parent ! (self, thunk)
- }
-
- receiveWithin(delay) {
- case TIMEOUT =>
- println("compilation timed out")
- false
- case Exit(from, reason) if from == child =>
- val From = from
- reason match {
- case 'normal =>
- receive {
- case (From, result: Boolean) => result
- }
- case t: Throwable =>
- NestUI.verbose("while invoking compiler ("+files+"):")
- NestUI.verbose("caught "+t)
- t.printStackTrace
- if (t.getCause != null)
- t.getCause.printStackTrace
- false
- }
- }
- }
-
/* This method returns true iff compilation succeeds.
*/
- def shouldCompile(files: List[File], kind: String, log: File): Boolean =
- withTimeout(files) {
- compiler.compile(None, files, kind, log)
- }
+ def shouldCompile(files: List[File], kind: String, log: File): Boolean = {
+ createSeparateCompiler()
+ compiler.compile(None, files, kind, log)
+ }
/* This method returns true iff compilation succeeds.
*/
- def shouldCompile(out: File, files: List[File], kind: String, log: File): Boolean =
- withTimeout(files) {
- compiler.compile(Some(out), files, kind, log)
- }
+ def shouldCompile(out: File, files: List[File], kind: String, log: File): Boolean = {
+ createSeparateCompiler()
+ compiler.compile(Some(out), files, kind, log)
+ }
/* This method returns true iff compilation fails
* _and_ the compiler does _not_ crash or loop.
*
* If the compiler crashes, this method returns false.
*/
- def shouldFailCompile(files: List[File], kind: String, log: File): Boolean =
- withTimeout(files) {
- !compiler.compile(None, files, kind, log)
- }
+ def shouldFailCompile(files: List[File], kind: String, log: File): Boolean = {
+ createSeparateCompiler()
+ !compiler.compile(None, files, kind, log)
+ }
/* This method returns true iff compilation fails
* _and_ the compiler does _not_ crash or loop.
*
* If the compiler crashes, this method returns false.
*/
- def shouldFailCompile(out: File, files: List[File], kind: String, log: File): Boolean =
- withTimeout(files) {
- !compiler.compile(Some(out), files, kind, log)
- }
-
+ def shouldFailCompile(out: File, files: List[File], kind: String, log: File): Boolean = {
+ createSeparateCompiler()
+ !compiler.compile(Some(out), files, kind, log)
+ }
}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
index 3e08a2ffff..4872a61437 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -90,7 +90,7 @@ class ConsoleRunner extends DirectRunner with RunnerUtils {
runAll = true
var enabled = List[TestSet]()
-
+ var readTimeout = false
for (arg <- args) {
(testSets find { set => arg == "--" + set.loc }) match {
case Some(set) => enabled = set :: enabled
@@ -102,6 +102,10 @@ class ConsoleRunner extends DirectRunner with RunnerUtils {
case "--failed" => fileManager.failed = true
case "--version" => //todo: printVersion
case "--ansi" => NestUI.initialize(NestUI.MANY)
+ case "--timeout" => readTimeout = true
+ case s: String if readTimeout =>
+ fileManager.timeout = s
+ readTimeout = false
case _ =>
if (denotesTestFile(arg) || denotesTestDir(arg)) {
val file = new File(arg)
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
index ef7f81f475..34dbdd7a3a 100644
--- a/src/partest/scala/tools/partest/nest/Worker.scala
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -11,6 +11,7 @@ import java.io.{File, FileInputStream, FileOutputStream, PrintStream,
FileReader, OutputStreamWriter, BufferedReader}
import java.net.URL
+import java.util.{Timer, TimerTask}
import scala.tools.nsc.{ObjectRunner, GenericRunnerCommand}
@@ -19,6 +20,7 @@ import scala.actors.Actor._
case class RunTests(kind: String, files: List[File])
case class Results(succ: Int, fail: Int, logs: List[LogFile], outdirs: List[File])
+case class LogContext(file: LogFile, writers: Option[(StringWriter, PrintWriter)])
class LogFile(parent: File, child: String) extends File(parent, child) {
var toDelete = false
@@ -31,6 +33,7 @@ class Worker(val fileManager: FileManager) extends Actor {
import scala.tools.nsc.util.FakePos
var reporter: ConsoleReporter = _
+ val timer = new Timer
def error(msg: String) {
reporter.error(FakePos("scalac"),
@@ -41,8 +44,10 @@ class Worker(val fileManager: FileManager) extends Actor {
react {
case RunTests(kind, files) =>
NestUI.verbose("received "+files.length+" to test")
- val (succ, fail) = runTests(kind, files)
- sender ! Results(succ, fail, createdLogFiles, createdOutputDirs)
+ val master = sender
+ runTests(kind, files, (succ: Int, fail: Int) => {
+ master ! Results(succ, fail, createdLogFiles, createdOutputDirs)
+ })
}
}
@@ -78,6 +83,12 @@ class Worker(val fileManager: FileManager) extends Actor {
NestUI.normal("]\n", printer)
}
+ def printInfoTimeout(printer: PrintWriter) {
+ NestUI.normal("[", printer)
+ NestUI.failure("TIMOUT", printer)
+ NestUI.normal("]\n", printer)
+ }
+
var log = ""
var createdLogFiles: List[LogFile] = List()
var createdOutputDirs: List[File] = List()
@@ -317,7 +328,7 @@ class Worker(val fileManager: FileManager) extends Actor {
* @param kind The test kind (pos, neg, run, etc.)
* @param files The list of test files
*/
- def runTests(kind: String, files: List[File]): (Int, Int) = {
+ def runTests(kind: String, files: List[File], topcont: (Int, Int) => Unit): Unit = {
val compileMgr = new CompileManager(fileManager)
var errors = 0
var succeeded = true
@@ -327,10 +338,8 @@ class Worker(val fileManager: FileManager) extends Actor {
/** 1. Creates log file and output directory.
* 2. Runs <code>script</code> function, providing log file and
* output directory as arguments.
- * 3. Prints test result.
- * 4. Shows log/diff if enabled.
*/
- def runInContext(file: File, kind: String, script: (File, File) => Unit) {
+ def runInContext(file: File, kind: String, script: (File, File) => Unit): LogContext = {
// when option "--failed" is provided
// execute test only if log file is present
// (which means it failed before)
@@ -360,23 +369,9 @@ class Worker(val fileManager: FileManager) extends Actor {
succeeded = false
}
- if (!succeeded) {
- errors += 1
- NestUI.verbose("incremented errors: "+errors)
- } else {
- // delete log file only if test was successful
- logFile.toDelete = true
- }
-
- printInfoEnd(succeeded, wr)
- wr.flush()
- swr.flush() //TODO: needed?
- NestUI.normal(swr.toString)
- if (!succeeded && fileManager.showDiff && diff != "")
- NestUI.normal(diff)
- else if (!succeeded && fileManager.showLog)
- showLog(logFile)
- }
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
}
def compileFilesIn(dir: File, kind: String, logFile: File, outDir: File) {
@@ -412,7 +407,7 @@ class Worker(val fileManager: FileManager) extends Actor {
}
}
- def runJvmTest(file: File, kind: String) {
+ def runJvmTest(file: File, kind: String): LogContext =
runInContext(file, kind, (logFile: File, outDir: File) => {
if (file.isDirectory) {
compileFilesIn(file, kind, logFile, outDir)
@@ -440,10 +435,9 @@ class Worker(val fileManager: FileManager) extends Actor {
}
}
})
- }
- kind match {
- case "scalacheck" => for (file <- files)
+ def processSingleFile(file: File): LogContext = kind match {
+ case "scalacheck" =>
runInContext(file, kind, (logFile: File, outDir: File) => {
if (file.isDirectory) {
compileFilesIn(file, kind, logFile, outDir)
@@ -480,7 +474,8 @@ class Worker(val fileManager: FileManager) extends Actor {
}
}
})
- case "pos" => for (file <- files)
+
+ case "pos" =>
runInContext(file, kind, (logFile: File, outDir: File) => {
if (file.isDirectory) {
compileFilesIn(file, kind, logFile, outDir)
@@ -489,44 +484,40 @@ class Worker(val fileManager: FileManager) extends Actor {
succeeded = false
}
})
+
case "neg" =>
- for (file <- files) {
- runInContext(file, kind, (logFile: File, outDir: File) => {
- if (file.isDirectory) {
- failCompileFilesIn(file, kind, logFile, outDir)
- } else if (!compileMgr.shouldFailCompile(List(file), kind, logFile)) {
+ runInContext(file, kind, (logFile: File, outDir: File) => {
+ if (file.isDirectory) {
+ failCompileFilesIn(file, kind, logFile, outDir)
+ } else if (!compileMgr.shouldFailCompile(List(file), kind, logFile)) {
+ succeeded = false
+ }
+ if (succeeded) { // compare log file to check file
+ val fileBase = basename(file.getName)
+ val dir = file.getParentFile
+ if (!existsCheckFile(dir, fileBase, kind)) {
+ // diff is contents of logFile
+ diff = file2String(logFile)
+ } else
+ diff = compareOutput(dir, fileBase, kind, logFile)
+
+ if (!diff.equals("")) {
+ NestUI.verbose("output differs from log file\n")
succeeded = false
}
- if (succeeded) { // compare log file to check file
- val fileBase = basename(file.getName)
- val dir = file.getParentFile
- if (!existsCheckFile(dir, fileBase, kind)) {
- // diff is contents of logFile
- diff = file2String(logFile)
- } else
- diff = compareOutput(dir, fileBase, kind, logFile)
+ }
+ })
- if (!diff.equals("")) {
- NestUI.verbose("output differs from log file\n")
- succeeded = false
- }
- }
- })
- }
case "run" =>
- for (file <- files) {
- runJvmTest(file, kind)
- }
+ runJvmTest(file, kind)
+
case "jvm" =>
- for (file <- files) {
- runJvmTest(file, kind)
- }
+ runJvmTest(file, kind)
+
case "jvm5" =>
- for (file <- files) {
- runJvmTest(file, kind)
- }
+ runJvmTest(file, kind)
+
case "res" => {
- for (file <- files) {
// when option "--failed" is provided
// execute test only if log file is present
// (which means it failed before)
@@ -596,6 +587,7 @@ class Worker(val fileManager: FileManager) extends Actor {
logWriter.print(prompt)
val line = resReader.readLine()
if ((line ne null) && line.length() > 0) {
+/*
val parent = self
self.trapExit = true
val child = link {
@@ -617,7 +609,8 @@ class Worker(val fileManager: FileManager) extends Actor {
false
}
}
-
+*/
+ action(line)
loop(action)
}
}
@@ -676,26 +669,12 @@ class Worker(val fileManager: FileManager) extends Actor {
succeeded = false
}
- // delete log file only if test was successful
- if (succeeded)
- logFile.toDelete = true
-
- if (!succeeded) {
- errors += 1
- NestUI.verbose("incremented errors: "+errors)
- }
- printInfoEnd(succeeded, wr)
- wr.flush()
- swr.flush()
- NestUI.normal(swr.toString)
-
- if (!succeeded && fileManager.showDiff) NestUI.normal(diff)
- if (!succeeded && fileManager.showLog) showLog(logFile)
- }
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
}
- }
+
case "shootout" => {
- for (file <- files) {
// when option "--failed" is provided
// execute test only if log file is present
// (which means it failed before)
@@ -756,27 +735,13 @@ class Worker(val fileManager: FileManager) extends Actor {
succeeded = false
}
- // delete log file only if test was successful
- if (succeeded)
- logFile.toDelete = true
-
- if (!succeeded) {
- errors += 1
- NestUI.verbose("incremented errors: "+errors)
- }
- printInfoEnd(succeeded, wr)
- wr.flush()
- swr.flush()
- NestUI.normal(swr.toString)
-
- if (!succeeded && fileManager.showDiff) NestUI.normal(diff)
- if (!succeeded && fileManager.showLog) showLog(logFile)
- }
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
}
- }
+
case "script" => {
val osName = System.getProperty("os.name", "")
- for (file <- files) {
// when option "--failed" is provided
// execute test only if log file is present
// (which means it failed before)
@@ -835,28 +800,94 @@ class Worker(val fileManager: FileManager) extends Actor {
succeeded = false
}
- // delete log file only if test was successful
- if (succeeded)
- logFile.toDelete = true
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ }
+ }
+
+ def reportAll(cont: (Int, Int) => Unit) {
+ NestUI.verbose("finished testing "+kind+" with "+errors+" errors")
+ NestUI.verbose("created "+compileMgr.numSeparateCompilers+" separate compilers")
+ timer.cancel()
+ cont(files.length-errors, errors)
+ }
- if (!succeeded) {
- errors += 1
- NestUI.verbose("incremented errors: "+errors)
- }
+ def reportResult(logs: Option[LogContext]) {
+ // delete log file only if test was successful
+ if (succeeded && !logs.isEmpty)
+ logs.get.file.toDelete = true
+
+ if (!succeeded) {
+ errors += 1
+ NestUI.verbose("incremented errors: "+errors)
+ }
+
+ if (!logs.isEmpty)
+ logs.get.writers match {
+ case Some((swr, wr)) =>
printInfoEnd(succeeded, wr)
wr.flush()
swr.flush()
NestUI.normal(swr.toString)
+ if (!succeeded && fileManager.showDiff && diff != "")
+ NestUI.normal(diff)
+ if (!succeeded && fileManager.showLog)
+ showLog(logs.get.file)
+ case None =>
+ }
+ }
- if (!succeeded && fileManager.showDiff) NestUI.normal(diff)
- if (!succeeded && fileManager.showLog) showLog(logFile)
- }
+ val numFiles = files.size
+ if (numFiles == 0)
+ reportAll(topcont)
+
+ var fileCnt = 1
+ Actor.loopWhile(fileCnt <= numFiles) {
+ val parent = self
+ val ontimeout = new TimerTask {
+ def run() {
+ parent ! 'timeout
}
}
+ timer.schedule(ontimeout, fileManager.timeout.toLong)
+
+ actor {
+ val result = try {
+ processSingleFile(files(fileCnt-1))
+ } catch {
+ case t: Throwable =>
+ NestUI.verbose("while invoking compiler ("+files+"):")
+ NestUI.verbose("caught "+t)
+ t.printStackTrace
+ if (t.getCause != null)
+ t.getCause.printStackTrace
+ null
+ }
+ parent ! result
+ }
+
+ react {
+ case 'timeout =>
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ printInfoStart(files(fileCnt-1), wr)
+ printInfoTimeout(wr)
+ wr.flush()
+ swr.flush()
+ NestUI.normal(swr.toString)
+ succeeded = false
+ reportResult(None)
+ if (fileCnt == numFiles)
+ reportAll(topcont)
+ fileCnt += 1
+ case logs: LogContext =>
+ reportResult(if (logs != null) Some(logs) else None)
+ if (fileCnt == numFiles)
+ reportAll(topcont)
+ fileCnt += 1
+ }
}
- NestUI.verbose("finished testing "+kind+" with "+errors+" errors")
- NestUI.verbose("created "+compileMgr.numSeparateCompilers+" separate compilers")
- (files.length-errors, errors)
}
def showLog(logFile: File) {