diff options
author | Som Snytt <som.snytt@gmail.com> | 2013-04-19 15:49:03 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-04-30 08:18:22 -0700 |
commit | 0c6bcc9cc24eeeb13f88ab91e858e5d246e0947d (patch) | |
tree | 95710f12c67433bb3f5be16621718252b6986a35 /src | |
parent | bf4466982854ffa8be57068752ea31daf7776eee (diff) | |
download | scala-0c6bcc9cc24eeeb13f88ab91e858e5d246e0947d.tar.gz scala-0c6bcc9cc24eeeb13f88ab91e858e5d246e0947d.tar.bz2 scala-0c6bcc9cc24eeeb13f88ab91e858e5d246e0947d.zip |
Partest has an optionable wait period.
Partest --timeout "30 seconds" to time out the test run.
It will not hang on timeout ("I hang with Par-Test" t-shirts
not-withstanding).
It's beyond the scope of this commit to investigate argument
parsing:
`partest --timeout "\"30 seconds"\" --pos`
Diffstat (limited to 'src')
5 files changed, 43 insertions, 13 deletions
diff --git a/src/partest/scala/tools/partest/PartestDefaults.scala b/src/partest/scala/tools/partest/PartestDefaults.scala index 16f1a6933f..8478edeb4d 100644 --- a/src/partest/scala/tools/partest/PartestDefaults.scala +++ b/src/partest/scala/tools/partest/PartestDefaults.scala @@ -1,6 +1,7 @@ package scala.tools package partest +import scala.concurrent.duration.Duration import scala.tools.nsc.Properties.{ propOrElse, propOrNone, propOrEmpty } import java.lang.Runtime.{ getRuntime => runtime } @@ -21,6 +22,7 @@ object PartestDefaults { def testBuild = propOrNone("partest.build") def errorCount = propOrElse("partest.errors", "0").toInt def numThreads = propOrNone("partest.threads") map (_.toInt) getOrElse runtime.availableProcessors + def waitTime = propOrNone("partest.timeout") map (Duration.apply) getOrElse Duration("4 hours") - def timeout = "1200000" + //def timeout = "1200000" // per-test timeout } diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index ddd42f5601..e5ace20062 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -86,7 +86,7 @@ class ConsoleRunner extends DirectRunner { ) ::: standardArgs private val binaryArgs = List( - "--grep", "--srcpath", "--buildpath", "--classpath" + "--grep", "--srcpath", "--buildpath", "--classpath", "--timeout" ) def main(argstr: String) { @@ -109,6 +109,7 @@ class ConsoleRunner extends DirectRunner { } parsed get "--srcpath" foreach (x => setProp("partest.srcdir", x)) + parsed get "--timeout" foreach (x => setProp("partest.timeout", x)) fileManager = if (parsed isSet "--buildpath") new ConsoleFileManager(parsed("--buildpath")) diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index 25371b7d54..230ada4803 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -85,7 +85,6 @@ trait FileManager extends FileUtil { var SCALAC_OPTS = PartestDefaults.scalacOpts.split(' ').toSeq var JAVA_OPTS = PartestDefaults.javaOpts - var timeout = PartestDefaults.timeout /** Only when --debug is given. */ lazy val testTimings = new mutable.HashMap[String, Long] diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index e823c6b09f..363adc0a07 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -8,8 +8,10 @@ package nest import java.io.{ Console => _, _ } import java.net.URL import java.nio.charset.{ Charset, CharsetDecoder, CharsetEncoder, CharacterCodingException, CodingErrorAction => Action } -import java.util.concurrent.{ Executors, TimeUnit } +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit.NANOSECONDS import scala.collection.mutable.ListBuffer +import scala.concurrent.duration.Duration import scala.io.Codec import scala.sys.process.Process import scala.tools.nsc.Properties.{ envOrElse, isWin, jdkHome, javaHome, propOrElse, propOrEmpty, setProp } @@ -19,6 +21,7 @@ import scala.tools.nsc.reporters.ConsoleReporter import scala.tools.nsc.util.{ Exceptional, ScalaClassLoader, stackTraceString } import scala.tools.scalap.Main.decompileScala import scala.tools.scalap.scalax.rules.scalasig.ByteCode +import scala.util.{ Try, Success, Failure } import ClassPath.{ join, split } import PartestDefaults.{ javaCmd, javacCmd } @@ -682,7 +685,7 @@ case class TestRunParams(val scalaCheckParentClassLoader: ScalaClassLoader) trait DirectRunner { def fileManager: FileManager - import PartestDefaults.numThreads + import PartestDefaults.{ numThreads, waitTime } Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler { @@ -708,17 +711,34 @@ trait DirectRunner { val futures = kindFiles map (f => pool submit callable(manager runTest f)) pool.shutdown() - try if (!pool.awaitTermination(4, TimeUnit.HOURS)) - NestUI warning "Thread pool timeout elapsed before all tests were complete!" - catch { case t: InterruptedException => - NestUI warning "Thread pool was interrupted" - t.printStackTrace() + Try (pool.awaitTermination(waitTime) { + throw TimeoutException(waitTime) + }) match { + case Success(_) => futures map (_.get) + case Failure(e) => + e match { + case TimeoutException(d) => + NestUI warning "Thread pool timeout elapsed before all tests were complete!" + case ie: InterruptedException => + NestUI warning "Thread pool was interrupted" + ie.printStackTrace() + } + pool.shutdownNow() // little point in continuing + // try to get as many completions as possible, in case someone cares + val results = for (f <- futures) yield { + try { + Some(f.get(0, NANOSECONDS)) + } catch { + case _: Throwable => None + } + } + results.flatten } - - futures map (_.get) } } +case class TimeoutException(duration: Duration) extends RuntimeException + class LogContext(val file: File, val writers: Option[(StringWriter, PrintWriter)]) object LogContext { diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index 0b169c767a..4a516d620b 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -4,8 +4,9 @@ package scala.tools +import java.util.concurrent.{ Callable, ExecutorService } +import scala.concurrent.duration.Duration import scala.sys.process.javaVmArguments -import java.util.concurrent.Callable import scala.tools.partest.nest.NestUI import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional } @@ -99,6 +100,13 @@ package object partest { ) } + implicit class ExecutorOps(val executor: ExecutorService) { + def awaitTermination[A](wait: Duration)(failing: => A = ()): Option[A] = ( + if (executor awaitTermination (wait.length, wait.unit)) None + else Some(failing) + ) + } + implicit def temporaryPath2File(x: Path): File = x.jfile implicit def stringPathToJavaFile(path: String): File = new File(path) |