summaryrefslogtreecommitdiff
path: root/src/partest
diff options
context:
space:
mode:
Diffstat (limited to 'src/partest')
-rw-r--r--src/partest/README76
-rw-r--r--src/partest/scala/tools/partest/Actions.scala205
-rw-r--r--src/partest/scala/tools/partest/Alarms.scala86
-rw-r--r--src/partest/scala/tools/partest/BuildContributors.scala102
-rw-r--r--src/partest/scala/tools/partest/Categories.scala70
-rw-r--r--src/partest/scala/tools/partest/Compilable.scala106
-rw-r--r--src/partest/scala/tools/partest/Config.scala129
-rw-r--r--src/partest/scala/tools/partest/Dispatcher.scala162
-rw-r--r--src/partest/scala/tools/partest/Entities.scala74
-rw-r--r--src/partest/scala/tools/partest/Housekeeping.scala187
-rw-r--r--src/partest/scala/tools/partest/Partest.scala81
-rw-r--r--src/partest/scala/tools/partest/PartestDefaults.scala30
-rw-r--r--src/partest/scala/tools/partest/PartestSpec.scala104
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala287
-rw-r--r--src/partest/scala/tools/partest/Results.scala121
-rw-r--r--src/partest/scala/tools/partest/Runner.scala36
-rw-r--r--src/partest/scala/tools/partest/Statistics.scala46
-rw-r--r--src/partest/scala/tools/partest/Universe.scala96
-rw-r--r--src/partest/scala/tools/partest/ant/JavaTask.scala57
-rw-r--r--src/partest/scala/tools/partest/antlib.xml3
-rw-r--r--src/partest/scala/tools/partest/category/AllCategories.scala20
-rw-r--r--src/partest/scala/tools/partest/category/Analysis.scala64
-rw-r--r--src/partest/scala/tools/partest/category/Compiler.scala140
-rw-r--r--src/partest/scala/tools/partest/category/Runner.scala108
-rw-r--r--src/partest/scala/tools/partest/io/ANSIWriter.scala58
-rw-r--r--src/partest/scala/tools/partest/io/JUnitReport.scala38
-rw-r--r--src/partest/scala/tools/partest/io/Logging.scala137
-rw-r--r--src/partest/scala/tools/partest/nest/AntRunner.scala30
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala197
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleFileManager.scala190
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala209
-rw-r--r--src/partest/scala/tools/partest/nest/Diff.java (renamed from src/partest/scala/tools/partest/io/Diff.java)2
-rw-r--r--src/partest/scala/tools/partest/nest/DiffPrint.java (renamed from src/partest/scala/tools/partest/io/DiffPrint.java)2
-rw-r--r--src/partest/scala/tools/partest/nest/DirectRunner.scala78
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala110
-rw-r--r--src/partest/scala/tools/partest/nest/NestRunner.scala16
-rw-r--r--src/partest/scala/tools/partest/nest/NestUI.scala118
-rw-r--r--src/partest/scala/tools/partest/nest/PathSettings.scala41
-rw-r--r--src/partest/scala/tools/partest/nest/ReflectiveRunner.scala88
-rw-r--r--src/partest/scala/tools/partest/nest/RunnerUtils.scala29
-rw-r--r--src/partest/scala/tools/partest/nest/StreamAppender.scala94
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala49
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala1071
-rw-r--r--src/partest/scala/tools/partest/package.scala59
-rw-r--r--src/partest/scala/tools/partest/util/package.scala61
-rw-r--r--src/partest/scala/tools/partest/utils/PrintMgr.scala52
-rw-r--r--src/partest/scala/tools/partest/utils/Properties.scala (renamed from src/partest/scala/tools/partest/Properties.scala)4
47 files changed, 2751 insertions, 2372 deletions
diff --git a/src/partest/README b/src/partest/README
index c7673fe2f8..81876fc810 100644
--- a/src/partest/README
+++ b/src/partest/README
@@ -1,50 +1,32 @@
-If you're looking for something to read, I suggest running ../test/partest
-with no arguments, which at this moment prints this:
+How partest choses the compiler / library:
-Usage: partest [<options>] [<test> <test> ...]
- <test>: a path to a test designator, typically a .scala file or a directory.
- Examples: files/pos/test1.scala, files/res/bug785
+ * ''-Dpartest.build=build/four-pack'' -> will search for libraries in
+ ''lib'' directory of given path
+ * ''--pack'' -> will set ''partest.build=build/pack'', and run all tests.
+ add ''--[kind]'' to run a selected set of tests.
+ * auto detection:
+ - partest.build property -> ''bin'' / ''lib'' directories
+ - distribution (''dists/latest'')
+ - supersabbus pack (''build/pack'')
+ - sabbus quick (''build/quick'')
+ - installed dist (test files in ''misc/scala-test/files'')
- Test categories:
- --all run all tests (default, unless no options given)
- --pos Compile files that are expected to build
- --neg Compile files that are expected to fail
- --run Test JVM backend
- --jvm Test JVM backend
- --res Run resident compiler scenarii
- --buildmanager Run Build Manager scenarii
- --scalacheck Run Scalacheck tests
- --script Run script files
- --shootout Run shootout tests
- --scalap Run scalap tests
+How partest choses test files: the test files must be accessible from
+the directory on which partest is run. So the test files must be either
+at:
+ * ./test/files
+ * ./files (cwd is "test")
+ * ./misc/scala-test/files (installed scala distribution)
- Test "smart" categories:
- --grep run all tests with a source file containing <expr>
- --failed run all tests which failed on the last run
-
- Specifying paths and additional flags, ~ means repository root:
- --rootdir path from ~ to partest (default: test)
- --builddir path from ~ to test build (default: build/pack)
- --srcdir path from --rootdir to sources (default: files)
- --javaopts flags to java on all runs (overrides JAVA_OPTS)
- --scalacopts flags to scalac on all tests (overrides SCALAC_OPTS)
- --pack alias for --builddir build/pack
- --quick alias for --builddir build/quick
-
- Options influencing output:
- --trace show the individual steps taken by each test
- --show-diff show diff between log and check file
- --show-log show log on failures
- --dry-run do not run tests, only show their traces.
- --terse be less verbose (almost silent except for failures)
- --verbose be more verbose (additive with --trace)
- --debug maximum debugging output
- --ansi print output in color
-
- Other options:
- --timeout Timeout in seconds
- --cleanup delete all stale files and dirs before run
- --nocleanup do not delete any logfiles or object dirs
- --stats collect and print statistics about the tests
- --validate examine test filesystem for inconsistencies
- --version print version
+Other arguments:
+ * --pos next files test a compilation success
+ * --neg next files test a compilation failure
+ * --run next files test the interpreter and all backends
+ * --jvm next files test the JVM backend
+ * --res next files test the resident compiler
+ * --buildmanager next files test the build manager
+ * --shootout next files are shootout tests
+ * --script next files test the script runner
+ * ''-Dpartest.scalac_opts=...'' -> add compiler options
+ * ''--verbose'' -> print verbose messages
+ * ''-Dpartest.debug=true'' -> print debug messages
diff --git a/src/partest/scala/tools/partest/Actions.scala b/src/partest/scala/tools/partest/Actions.scala
deleted file mode 100644
index 5cbe64ce23..0000000000
--- a/src/partest/scala/tools/partest/Actions.scala
+++ /dev/null
@@ -1,205 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import util._
-import nsc.io._
-
-trait Actions {
- partest: Universe =>
-
- class TestSequence(val actions: List[TestStep]) extends AbsTestSequence {
- }
-
- implicit def createSequence(xs: List[TestStep]) = new TestSequence(xs)
-
- trait ExecSupport {
- self: TestEntity =>
-
- def execEnv: Map[String, String] = {
- val map = assembleEnvironment()
- val cwd = execCwd.toList map ("CWD" -> _.path)
-
- map ++ cwd
- }
- def execCwd = if (commandFile.isFile) Some(sourcesDir) else None
-
- def runExec(args: List[String]): Boolean = {
- val cmd = fromArgs(args)
-
- if (isVerbose) {
- trace("runExec: " + execEnv.mkString("ENV(", "\n", "\n)"))
- execCwd foreach (x => trace("CWD(" + x + ")"))
- }
-
- trace("runExec: " + cmd)
- isDryRun || execAndLog(cmd)
- }
-
- /** Exec a process to run a command. Assumes 0 exit value is success.
- * Of necessity, also treats no available exit value as success.
- */
- protected def execAndLog(cmd: String): Boolean = {
- var proc: Process = null
-
- val result = interruptMeIn(cmd, testTimeout) {
- loggingResult {
- proc = Process.exec(toArgs(cmd), execEnv, execCwd.orNull, true)
- proc.slurp()
- }
- proc != null && (proc.waitFor() == 0)
- }
- result getOrElse {
- warning("Process never terminated: '%s'" format cmd)
- if (proc != null)
- proc.destroy()
-
- false
- }
- }
- }
-
- trait ScriptableTest {
- self: TestEntity =>
-
- /** Translates a line from a .cmds file into a teststep.
- */
- def customTestStep(line: String): TestStep = {
- trace("customTestStep: " + line)
- val (cmd, rest) = line span (x => !Character.isWhitespace(x))
- def qualify(name: String) = sourcesDir / name path
- val args = toArgs(rest) map qualify
- def fail: TestStep = (_: TestEntity) => error("Parse error: did not understand '%s'" format line)
-
- val f: TestEntity => Boolean = cmd match {
- case "scalac" => _ scalac args
- case "javac" => _ javac args
- case "scala" => _ runScala args
- case _ => fail
- }
- f
- }
- }
-
- trait CompilableTest extends CompileExecSupport {
- self: TestEntity =>
-
- def sourceFiles = location.walk collect { case f: File if isJavaOrScala(f) => f } toList
- def allSources = sourceFiles map (_.path)
- def scalaSources = sourceFiles filter isScala map (_.path)
- def javaSources = sourceFiles filter isJava map (_.path)
-
- /** If there are mixed java and scala files, the standard compilation
- * sequence is:
- *
- * scalac with all files
- * javac with only java files
- * scalac with only scala files
- *
- * This should be expanded to encompass other strategies so we know how
- * well they're working or not working - notably, it would be very useful
- * to know exactly when and how two-pass compilation fails.
- */
- def compile() = {
- trace("compile: " + sourceFiles)
-
- def compileJava() = javac(javaSources)
- def compileScala() = scalac(scalaSources)
- def compileAll() = scalac(allSources)
- def compileMixed() = compileAll() && compileJava() && compileScala()
-
- if (scalaSources.nonEmpty && javaSources.nonEmpty) compileMixed()
- else compileScala()
- }
- }
-
- trait DiffableTest {
- self: TestEntity =>
-
- def checkFile: File = withExtension("check").toFile
- def checkFileRequired =
- returning(checkFile.isFile)(res => if (!res) warnAndLog("A checkFile at '%s' is mandatory.\n" format checkFile.path))
-
- lazy val sourceFileNames = sourceFiles map (_.name)
-
- /** Given the difficulty of verifying that any selective approach works
- * everywhere, the algorithm now is to look for the name of any known
- * source file for this test, and if seen, remove all the non-whitespace
- * preceding it. (Paths with whitespace don't work anyway.) This should
- * wipe out all slashes, backslashes, C:\, cygwin/windows differences,
- * and whatever else makes a simple diff not simple.
- *
- * The log and check file are both transformed, which I don't think is
- * correct -- only the log should be -- but doing it this way until I
- * can clarify martin's comments in #3283.
- */
- def normalizePaths(s: String) =
- sourceFileNames.foldLeft(s)((res, name) => res.replaceAll("""\S+\Q%s\E""" format name, name))
-
- /** The default cleanup normalizes paths relative to sourcesDir,
- * absorbs line terminator differences by going to lines and back,
- * and trims leading or trailing whitespace.
- */
- def diffCleanup(f: File) = safeLines(f) map normalizePaths mkString "\n" trim
-
- /** diffFiles requires actual Files as arguments but the output we want
- * is the post-processed versions of log/check, so we resort to tempfiles.
- */
- lazy val diffOutput = {
- if (!checkFile.exists) "" else {
- val input = diffCleanup(checkFile)
- val output = diffCleanup(logFile)
- def asFile(s: String) = returning(File.makeTemp("partest-diff"))(_ writeAll s)
-
- if (input == output) ""
- else diffFiles(asFile(input), asFile(output))
- }
- }
- private def checkTraceName = tracePath(checkFile)
- private def logTraceName = tracePath(logFile)
- private def isDiffConfirmed = checkFile.exists && (diffOutput == "")
-
- private def sendTraceMsg() {
- def result =
- if (isDryRun) ""
- else if (isDiffConfirmed) " [passed]"
- else if (checkFile.exists) " [failed]"
- else " [unchecked]"
-
- trace("diff %s %s%s".format(checkTraceName, logTraceName, result))
- }
-
- /** If optional is true, a missing check file is considered
- * a successful diff. Necessary since many categories use
- * checkfiles in an ad hoc manner.
- */
- def runDiff() = {
- sendTraceMsg()
-
- def updateCheck = (
- isUpdateCheck && {
- val formatStr = "** diff %s %s: " + (
- if (checkFile.exists) "failed, updating '%s' and marking as passed."
- else if (diffOutput == "") "not creating checkFile at '%s' as there is no output."
- else "was unchecked, creating '%s' for future tests."
- ) + "\n"
-
- normal(formatStr.format(checkTraceName, logTraceName, checkFile.path))
- if (diffOutput != "") normal(diffOutput)
-
- checkFile.writeAll(diffCleanup(logFile), "\n")
- true
- }
- )
-
- isDryRun || isDiffConfirmed || (updateCheck || !checkFile.exists)
- }
- }
-}
diff --git a/src/partest/scala/tools/partest/Alarms.scala b/src/partest/scala/tools/partest/Alarms.scala
deleted file mode 100644
index f38d8d6268..0000000000
--- a/src/partest/scala/tools/partest/Alarms.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools
-package partest
-
-import java.util.{ Timer, TimerTask }
-
-trait Alarms {
- self: Universe =>
-
- def interruptMeIn[T](debugMsg: String, seconds: Int)(body: => T): Option[T] = {
- val thisThread = currentThread
- val alarm = new SimpleAlarm(seconds * 1000) set thisThread.interrupt()
- debug("interruptMeIn(%d) '%s'".format(seconds, debugMsg))
-
- try { Some(body) }
- catch { case _: InterruptedException => debug("Received interrupted exception.") ; None }
- finally { debug("Cancelling interruptMeIn '%s'" format debugMsg) ; alarm.cancel() ; Thread.interrupted() }
- }
-
- case class AlarmerAction(secs: Int, action: () => Unit) extends Runnable {
- override def run() = action()
- }
-
- /** Set any number of alarms up with tuples of the form:
- * seconds to alarm -> Function0[Unit] to execute
- */
- class Alarmer(alarms: AlarmerAction*) {
- import java.util.concurrent._
-
- val exec = Executors.newSingleThreadScheduledExecutor()
- alarms foreach (x => exec.schedule(x, x.secs, TimeUnit.SECONDS))
- exec.shutdown()
-
- def cancelAll() = exec.shutdownNow()
- }
-
- class SimpleAlarm(timeout: Long) {
- private val alarm = new Timer
-
- /** Start a timer, running the given body if it goes off.
- */
- def set(body: => Unit) = returning(new TimerTask { def run() = body })(alarm.schedule(_, timeout))
-
- /** Cancel the timer.
- */
- def cancel() = alarm.cancel()
- }
-
- trait TestAlarms {
- test: TestEntity =>
-
- private def warning1 = AlarmerAction(testWarning, () => warning(
- """|I've been waiting %s seconds for this to complete:
- | %s
- |It may be stuck, or if not, it should be broken into smaller tests.
- |""".stripMargin.format(testWarning, test))
- )
- private def warning2 = AlarmerAction(testWarning * 2, () => warning(
- """|Now I've been waiting %s seconds for this to complete:
- | %s
- |If partest seems hung it would be a good place to look.
- |""".stripMargin.format(testWarning * 2, test))
- )
-
- def startAlarms(onTimeout: => Unit) =
- if (isNoAlarms) new Alarmer() // for alarm debugging
- else new Alarmer(Seq(warning1, warning2, AlarmerAction(testTimeout, () => onTimeout)): _*)
- }
-
- // Thread.setDefaultUncaughtExceptionHandler(new UncaughtException)
- // class UncaughtException extends Thread.UncaughtExceptionHandler {
- // def uncaughtException(t: Thread, e: Throwable) {
- // Console.println("Uncaught in %s: %s".format(t, e))
- // }
- // }
- //
- // lazy val logger = File("/tmp/partest.log").bufferedWriter()
- // def flog(msg: String) = logger synchronized {
- // logger write (msg + "\n")
- // logger.flush()
- // }
-}
diff --git a/src/partest/scala/tools/partest/BuildContributors.scala b/src/partest/scala/tools/partest/BuildContributors.scala
deleted file mode 100644
index 64c7e07bc3..0000000000
--- a/src/partest/scala/tools/partest/BuildContributors.scala
+++ /dev/null
@@ -1,102 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import nsc.util.ClassPath
-
-trait BuildContributors {
- universe: Universe =>
-
- /** A trait mixed into types which contribute a portion of the values.
- * The basic mechanism is the TestBuild, TestCategory, and TestEntity
- * can each contribute to each value. They are assembled at the last
- * moment by the ContributorAssembler (presently the TestEntity.)
- */
- trait BuildContributor {
- def javaFlags: List[String]
- def scalacFlags: List[String]
- def classpathPaths: List[Path]
- def buildProperties: List[(String, Any)]
- def buildEnvironment: Map[String, String]
- }
-
- trait ContributorAssembler {
- def contributors: List[BuildContributor]
- def assemble[T](what: BuildContributor => List[T]): List[T] = contributors flatMap what
-
- /** !!! This will need work if we want to achieve real composability,
- * but it can wait for the demand.
- */
- def assembleScalacArgs(args: List[String]) = assemble(_.scalacFlags) ++ args
- def assembleJavaArgs(args: List[String]) = assemble(_.javaFlags) ++ args
- def assembleProperties() = assemble(_.buildProperties)
- def assembleClasspaths(paths: List[Path]) = assemble(_.classpathPaths) ++ paths
- def assembleEnvironment() = assemble(_.buildEnvironment.toList).toMap
-
- def createClasspathString() = ClassPath fromPaths (assembleClasspaths(Nil) : _*)
- def createPropertyString() = assembleProperties() map { case (k, v) => "-D%s=%s".format(k, v.toString) }
- }
-
- trait BuildContribution extends BuildContributor {
- self: TestBuild =>
-
- /** The base classpath and system properties.
- * !!! TODO - this should adjust itself depending on the build
- * being tested, because pack and quick at least need different jars.
- */
- def classpathPaths = List[Path](library, compiler, partest, fjbg) ++ forkJoinPath
- def buildProperties = List(
- "scala.home" -> testBuildDir,
- "partest.lib" -> library, // used in jvm/inner
- "java.awt.headless" -> true,
- "user.language" -> "en",
- "user.country" -> "US",
- "partest.debug" -> isDebug,
- "partest.verbose" -> isVerbose
- // Disabled because there are no natives tests.
- // "java.library.path" -> srcLibDir
- )
- def javaFlags: List[String] = toArgs(javaOpts)
- def scalacFlags: List[String] = toArgs(scalacOpts)
-
- /** We put the build being tested's /bin directory in the front of the
- * path so the scripts and such written to execute "scala" will use this
- * build and not whatever happens to be on their path.
- */
- private def modifiedPath = ClassPath.join(scalaBin.path, Properties.envOrElse("PATH", ""))
- def buildEnvironment = Map("PATH" -> modifiedPath)
- }
-
- trait CategoryContribution extends BuildContributor {
- self: DirBasedCategory =>
-
- /** Category-wide classpath additions placed in <category>/lib. */
- private def libContents = root / "lib" ifDirectory (_.list.toList)
-
- def classpathPaths = libContents getOrElse Nil
- def buildProperties = Nil
- def javaFlags = Nil
- def scalacFlags = Nil
- def buildEnvironment = Map()
- }
-
- trait TestContribution extends BuildContributor with ContributorAssembler {
- self: TestEntity =>
-
- def jarsInTestDir = location.walk collect { case f: File if f hasExtension "jar" => f } toList
-
- def contributors = List(build, category, self)
- def javaFlags = safeArgs(javaOptsFile)
- def scalacFlags = safeArgs(scalaOptsFile)
- def classpathPaths = jarsInTestDir :+ outDir
- def buildProperties = List(
- "partest.output" -> outDir.toAbsolute, // used in jvm/inner
- "partest.cwd" -> outDir.parent.toAbsolute // used in shootout tests
- )
- def buildEnvironment = Map("JAVA_OPTS" -> fromArgs(assembleJavaArgs(Nil)))
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/Categories.scala b/src/partest/scala/tools/partest/Categories.scala
deleted file mode 100644
index 172cca74b4..0000000000
--- a/src/partest/scala/tools/partest/Categories.scala
+++ /dev/null
@@ -1,70 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import nsc.Settings
-import nsc.io._
-import nsc.util.{ ClassPath }
-
-trait Categories {
- self: Universe =>
-
- trait TestCategory extends AbsTestCategory {
- def kind: String
- def startMessage: String = "Executing test group"
- def testSequence: TestSequence
-
- class TestSettings(entity: TestEntity, error: String => Unit) extends Settings(error) {
- def this(entity: TestEntity) = this(entity, Console println _)
-
- deprecation.value = false
- encoding.value = "ISO-8859-1"
- classpath.value = entity.testClasspath
- outdir.value = entity.outDir.path
- }
-
- def createSettings(entity: TestEntity): TestSettings = new TestSettings(entity)
- def createTest(location: Path): TestEntity =
- if (location.isFile) TestFile(this, location.toFile)
- else if (location.isDirectory) TestDirectory(this, location.toDirectory)
- else error("Failed to create test at '%s'" format location)
-
- /** Category test identification.
- */
- def denotesTestFile(p: Path) = p.isFile && (p hasExtension "scala")
- def denotesTestDir(p: Path) = p.isDirectory && !ignorePath(p)
- def denotesTest(p: Path) = denotesTestDir(p) || denotesTestFile(p)
-
- /** This should verify that all necessary files are present.
- * By default it delegates to denotesTest.
- */
- def denotesValidTest(p: Path) = denotesTest(p)
- }
-
- abstract class DirBasedCategory(val kind: String) extends TestCategory with CategoryContribution {
- lazy val root = Directory(src / kind).normalize
- def enumerate = root.list filter denotesTest map createTest toList
-
- /** Standard actions. These can be overridden either on the
- * Category level or by individual tests.
- */
- def compile: TestStep = (_: TestEntity).compile()
- def checkFileRequired: TestStep = (_: TestEntity).checkFileRequired
- def diff: TestStep = (_: TestEntity).diff()
- def run: TestStep = (_: TestEntity).run()
- def exec: TestStep = (_: TestEntity).exec()
-
- /** Combinators.
- */
- def not(f: TestStep): TestStep = !f(_: TestEntity)
-
- override def toString = kind
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/Compilable.scala b/src/partest/scala/tools/partest/Compilable.scala
deleted file mode 100644
index ddaa277842..0000000000
--- a/src/partest/scala/tools/partest/Compilable.scala
+++ /dev/null
@@ -1,106 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.tools.nsc.io._
-import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError }
-import scala.tools.nsc.util.{ ClassPath }
-import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
-
-trait PartestCompilation {
- self: Universe =>
-
- trait CompileExecSupport extends ExecSupport {
- self: TestEntity =>
-
- def javacpArg = "-classpath " + testClasspath
- def scalacpArg = "-usejavacp"
-
- /** Not used, requires tools.jar.
- */
- // def javacInternal(args: List[String]) = {
- // import com.sun.tools.javac.Main
- // Main.compile(args.toArray, logWriter)
- // }
-
- def javac(args: List[String]): Boolean = {
- val allArgString = fromArgs(javacpArg :: javacOpts :: args)
-
- // javac -d outdir -classpath <basepath> <files>
- val cmd = "%s -d %s %s".format(javacCmd, outDir, allArgString)
- def traceMsg =
- if (isVerbose) cmd
- else "%s -d %s %s".format(tracePath(Path(javacCmd)), tracePath(outDir), fromArgs(args))
-
- trace(traceMsg)
-
- isDryRun || execAndLog(cmd)
- }
-
- def scalac(args: List[String]): Boolean = {
- val allArgs = assembleScalacArgs(args)
- val (global, files) = newGlobal(allArgs)
- def nonFileArgs = if (isVerbose) global.settings.recreateArgs else assembleScalacArgs(Nil)
- def traceArgs = fromArgs(nonFileArgs ++ (files map tracePath))
- def traceMsg = "scalac " + traceArgs
-
- trace(traceMsg)
- isDryRun || global.partestCompile(files, true)
- }
-
- /** Actually running the test, post compilation.
- * Normally args will be List("Test", "jvm"), main class and arg to it.
- */
- def runScala(args: List[String]): Boolean = {
- val scalaRunnerClass = "scala.tools.nsc.MainGenericRunner"
-
- // java $JAVA_OPTS <javaopts> -classpath <cp>
- val javaCmdAndOptions = javaCmd +: assembleJavaArgs(List(javacpArg))
- // MainGenericRunner -usejavacp <scalacopts> Test jvm
- val scalaCmdAndOptions = List(scalaRunnerClass, scalacpArg) ++ assembleScalacArgs(args)
- // Assembled
- val cmd = fromArgs(javaCmdAndOptions ++ createPropertyString() ++ scalaCmdAndOptions)
-
- def traceMsg = if (isVerbose) cmd else fromArgs(javaCmd :: args)
- trace("runScala: " + traceMsg)
-
- isDryRun || execAndLog(cmd)
- }
-
- def newReporter(settings: Settings) = new ConsoleReporter(settings, Console.in, logWriter)
-
- class PartestGlobal(settings: Settings, val creporter: ConsoleReporter) extends Global(settings, creporter) {
- def partestCompile(files: List[String], printSummary: Boolean): Boolean = {
- try { new Run compile files }
- catch {
- case FatalError(msg) => creporter.error(null, "fatal error: " + msg)
- case ae: AssertionError => creporter.error(null, ""+ae)
- case te: TypeError => creporter.error(null, ""+te)
- case ex =>
- creporter.error(null, ""+ex)
- throw ex
- }
-
- if (printSummary)
- creporter.printSummary
-
- creporter.flush()
- !creporter.hasErrors
- }
- }
-
- def newGlobal(args: List[String]): (PartestGlobal, List[String]) = {
- val settings = category createSettings self
- val command = new CompilerCommand(args, settings)
- val reporter = newReporter(settings)
-
- if (!command.ok)
- debug("Error parsing arguments: '%s'".format(args mkString ", "))
-
- (new PartestGlobal(command.settings, reporter), command.files)
- }
- }
-}
diff --git a/src/partest/scala/tools/partest/Config.scala b/src/partest/scala/tools/partest/Config.scala
deleted file mode 100644
index 288a3034e9..0000000000
--- a/src/partest/scala/tools/partest/Config.scala
+++ /dev/null
@@ -1,129 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import io._
-import nsc.io._
-import Properties._
-
-trait Config {
- universe: Universe =>
-
- lazy val src = absolutize(srcDir).toDirectory
- lazy val build = new TestBuild()
-
- def javaHomeEnv = envOrElse("JAVA_HOME", null)
- def javaCmd = envOrElse("JAVACMD", "java")
- def javacCmd = Option(javaHomeEnv) map (x => Path(x) / "bin" / "javac" path) getOrElse "javac"
-
- /** Values related to actors. The timeouts are in seconds. On a dry
- * run we only allocate one worker so the output isn't interspersed.
- */
- def workerTimeout = 3600 // 1 hour, probably overly generous
- def numWorkers = if (isDryRun) 1 else propOrElse("partest.actors", "8").toInt
- def expectedErrors = propOrElse("partest.errors", "0").toInt
- def poolSize = (wrapAccessControl(propOrNone("actors.corePoolSize")) getOrElse "16").toInt
-
- def allScalaFiles = src.deepFiles filter (_ hasExtension "scala")
- def allObjDirs = src.deepDirs filter (_ hasExtension "obj")
- def allLogFiles = src.deepFiles filter (_ hasExtension "log")
- def allClassFiles = src.deepFiles filter (_ hasExtension "class")
-
- class TestBuild() extends BuildContribution {
- import nsc.util.ClassPath
-
- /** Scala core libs.
- */
- val library = pathForComponent("library")
- val compiler = pathForComponent("compiler")
- val partest = pathForComponent("partest")
- val scalap = pathForComponent("scalap", "%s.jar")
-
- /** Scala supplementary libs - these are not all needed for all build targets,
- * and some of them are copied inside other jars in later targets. However quick
- * for instance cannot be run without some of these.
- */
- val fjbg = pathForLibrary("fjbg")
- val msil = pathForLibrary("msil")
- val forkjoin = pathForLibrary("forkjoin")
- val scalacheck = pathForLibrary("scalacheck")
-
- /** Other interesting paths.
- */
- val scalaBin = testBuildDir / "bin"
-
- /** A hack for now to get quick running.
- */
- def needsForkJoin = {
- val loader = nsc.util.ScalaClassLoader.fromURLs(List(library.toURL))
- val fjMarker = "scala.concurrent.forkjoin.ForkJoinTask"
- val clazz = loader.tryToLoadClass(fjMarker)
-
- if (clazz.isDefined) debug("Loaded ForkJoinTask OK, don't need jar.")
- else debug("Could not load ForkJoinTask, putting jar on classpath.")
-
- clazz.isEmpty
- }
- lazy val forkJoinPath: List[Path] = if (needsForkJoin) List(forkjoin) else Nil
-
- /** Internal **/
- private def repo = partestDir.parent.normalize
- // XXX - is this needed? Where?
- //
- // private val pluginOptionString = "-Xplugin:"
- // private def updatedPluginPath(options: String): String = {
- // val (pluginArgs, rest) = toArgs(options) partition (_ startsWith pluginOptionString)
- // // join all plugin paths as one classpath
- // val pluginPaths = ClassPath.join(pluginArgs map (_ stripPrefix pluginOptionString): _*)
- // // map all paths to absolute
- // val newPath = ClassPath.map(pluginPaths, x => absolutize(x).path)
- // // recreate option
- // val pluginOption = if (newPath == "") None else Some(pluginOptionString + newPath)
- //
- // fromArgs(rest ::: pluginOption.toList)
- // }
-
- private def pathForComponent(what: String, jarFormat: String = "scala-%s.jar"): Path = {
- def asDir = testBuildDir / "classes" / what
- def asJar = testBuildDir / "lib" / jarFormat.format(what)
-
- if (asDir.isDirectory) asDir
- else if (asJar.isFile) asJar
- else ""
- }
- private def pathForLibrary(what: String) = File(repo / "lib" / (what + ".jar"))
- }
-
- def printConfigBanner() = {
- debug("Java VM started with arguments: '%s'" format fromArgs(Process.javaVmArguments))
- debug("System Properties:\n" + util.allPropertiesString())
-
- normal(configBanner())
- }
-
- /** Treat an access control failure as None. */
- private def wrapAccessControl[T](body: => Option[T]): Option[T] =
- try body catch { case _: java.security.AccessControlException => None }
-
- private def configBanner() = {
- val javaBin = Path(javaHome) / "bin"
- val javaInfoString = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
-
- List(
- "Scala compiler classes in: " + testBuildDir,
- "Scala version is: " + nsc.Properties.versionMsg,
- "Scalac options are: " + universe.scalacOpts,
- "Java binaries in: " + javaBin,
- "Java runtime is: " + javaInfoString,
- "Java runtime options: " + (Process.javaVmArguments mkString " "),
- "Javac options are: " + universe.javacOpts,
- "Java options are: " + universe.javaOpts,
- "Source directory is: " + src,
- "Selected categories: " + (selectedCategories mkString " "),
- ""
- ) mkString "\n"
- }
-}
diff --git a/src/partest/scala/tools/partest/Dispatcher.scala b/src/partest/scala/tools/partest/Dispatcher.scala
deleted file mode 100644
index 2a9d99ab60..0000000000
--- a/src/partest/scala/tools/partest/Dispatcher.scala
+++ /dev/null
@@ -1,162 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import scala.tools.nsc.io._
-import scala.actors.{ Actor, TIMEOUT }
-import scala.actors.Actor._
-import scala.collection.immutable
-import scala.util.control.Exception.ultimately
-
-/** The machinery for concurrent execution of tests. Each Worker
- * is given a bundle of tests, which it runs sequentially and then
- * sends a report back to the dispatcher.
- */
-trait Dispatcher {
- partest: Universe =>
-
- /** The public entry point. The given filter narrows down the list of
- * tests to run.
- */
- def runSelection(categories: List[TestCategory], filt: TestEntity => Boolean = _ => true): CombinedTestResults = {
- // Setting scala.home informs tests where to obtain their jars.
- setProp("scala.home", testBuildDir.path)
-
- val allTests = allCategories flatMap (_.enumerate)
- val selected = allTests filter filt
- val groups = selected groupBy (_.category)
- val count = selected.size
-
- if (count == 0) return CombinedTestResults(0, 0, 0, Nil)
- else if (count == allTests.size) verbose("Running all %d tests." format count)
- else verbose("Running %d/%d tests: %s".format(count, allTests.size, toStringTrunc(selected map (_.label) mkString ", ")))
-
- allCategories collect { case x if groups contains x => runCategory(x, groups(x)) } reduceLeft (_ ++ _)
- }
-
- private def parallelizeTests(tests: List[TestEntity]): immutable.Map[TestEntity, TestResult] = {
- // propagate verbosity
- if (isDebug) scala.actors.Debug.level = 3
-
- // "If elected, I guarantee a slice of tests for every worker!"
- val groups = tests grouped ((tests.size / numWorkers) + 1) toList
-
- // "Workers, line up for assignments!"
- val workers =
- for ((slice, workerNum) <- groups.zipWithIndex) yield {
- returning(new Worker(workerNum)) { worker =>
- worker.start()
- worker ! TestsToRun(slice)
- }
- }
-
- normal("Started %d workers with ~%d tests each.\n".format(groups.size, groups.head.size))
-
- /** Listening for news from the proletariat.
- */
- (workers map { w =>
- receiveWithin(workerTimeout * 1000) {
- case ResultsOfRun(resultMap) => resultMap
- case TIMEOUT =>
- warning("Worker %d timed out." format w.workerNum)
- // mark all the worker's tests as having timed out - should be hard to miss
- // immutable.Map[TestEntity, TestResult]()
- groups(w.workerNum) map (x => (x -> new Timeout(x))) toMap
- }
- }) reduceLeft (_ ++ _)
- }
-
- private def runCategory(category: TestCategory, tests: List[TestEntity]): CombinedTestResults = {
- val kind = category.kind
- normal("%s (%s tests in %s)\n".format(category.startMessage, tests.size, category))
-
- val (milliSeconds, resultMap) = timed2(parallelizeTests(tests))
- val (passed, failed) = resultsToStatistics(resultMap mapValues (_.state))
- val failures = resultMap.values filterNot (_.passed) toList
-
- CombinedTestResults(passed, failed, milliSeconds, failures)
- }
-
- /** A Worker is given a bundle of tests and runs them all sequentially.
- */
- class Worker(val workerNum: Int) extends Actor {
- def act() {
- react { case TestsToRun(tests) =>
- val master = sender
- runTests(tests)(results => master ! ResultsOfRun(results))
- }
- }
-
- /** Runs the tests. Passes the result Map to onCompletion when done.
- */
- private def runTests(tests: List[TestEntity])(onCompletion: immutable.Map[TestEntity, TestResult] => Unit) {
- var results = new immutable.HashMap[TestEntity, TestResult] // maps tests to results
- val numberOfTests = tests.size
- val testIterator = tests.iterator
- def processed = results.size
- def isComplete = testIterator.isEmpty
-
- def atThreshold(num: Double) = {
- require(num >= 0 && num <= 1.0)
- ((processed - 1).toDouble / numberOfTests <= num) && (processed.toDouble / numberOfTests >= num)
- }
-
- def extraMessage = {
- // for now quiet for normal people
- if (isVerbose || isTrace || isDebug) {
- if (isComplete) "(#%d 100%%)" format workerNum
- else if (isVerbose) "(#%d %d/%d)".format(workerNum, processed, numberOfTests)
- else if (isTrace && atThreshold(0.5)) "(#%d 50%%)" format workerNum
- else ""
- }
- else ""
- }
-
- def countAndReport(result: TestResult) {
- val TestResult(test, state) = result
- // refuse to count an entity twice
- if (results contains test)
- return warning("Received duplicate result for %s: was %s, now %s".format(test, results(test), state))
-
- // increment the counter for this result state
- results += (test -> result)
-
- // show on screen
- if (isDryRun) normal("\n") // blank line between dry run traces
- else result show extraMessage
-
- // remove log if successful
- if (result.passed)
- test.deleteLog()
-
- // Respond to master if this Worker is complete
- if (isComplete)
- onCompletion(results)
- }
-
- Actor.loopWhile(testIterator.hasNext) {
- val parent = self
- // pick a test and set some alarms
- val test = testIterator.next
- val alarmer = test startAlarms (parent ! new Timeout(test))
-
- actor {
- ultimately(alarmer.cancelAll()) {
- // Calling isSuccess forces the lazy val "process" inside the test, running it.
- val res = test.isSuccess
- // Cancel the alarms and alert the media.
- parent ! TestResult(test, res)
- }
- }
-
- react {
- case x: TestResult => countAndReport(x)
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/Entities.scala b/src/partest/scala/tools/partest/Entities.scala
deleted file mode 100644
index bea505b594..0000000000
--- a/src/partest/scala/tools/partest/Entities.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-
-trait Entities {
- self: Universe =>
-
- abstract class TestEntity extends AbsTestEntity
- with TestContribution
- with TestHousekeeping
- with TestAlarms
- with EntityLogging
- with CompilableTest
- with ScriptableTest
- with DiffableTest {
- def location: Path
- def category: TestCategory
-
- lazy val label = location.stripExtension
- lazy val testClasspath = returning(createClasspathString())(x => vtrace("testClasspath: " + x))
-
- /** Was this test successful? Calling this for the first time forces
- * lazy val "process" which actually runs the test.
- */
- def isSuccess = process
-
- /** Some standard files, which may or may not be present.
- */
- def scalaOptsFile = withExtension("flags").toFile // opts to scalac
- def javaOptsFile = withExtension("javaopts").toFile // opts to java (but not javac)
- def commandFile = withExtension("cmds").toFile // sequence of commands to execute
- def logFile = withExtension("log").toFile // collected output
-
- /** Some standard directories.
- */
- def outDir = withExtension("obj").toDirectory // output dir, e.g. files/pos/t14.obj
- def categoryDir = location.parent.normalize // category dir, e.g. files/pos/
- def sourcesDir = location ifDirectory (_.normalize) getOrElse categoryDir
-
- /** Standard arguments for run, exec, diff.
- */
- def argumentsToRun = List("Test", "jvm")
- def argumentsToExec = List(location.path)
-
- /** Using a .cmds file for a custom test sequence.
- */
- def commandList = safeLines(commandFile)
- def testSequence =
- if (commandFile.isFile && commandList.nonEmpty) commandList map customTestStep
- else category.testSequence
-
- def run() = runScala(argumentsToRun)
- def exec() = runExec(argumentsToExec)
- def diff() = runDiff() // checkFile, logFile
-
- /** The memoized result of the test run.
- */
- private lazy val process = {
- val outcome = runWrappers(testSequence.actions forall (f => f(this)))
-
- // an empty outcome means we've been interrupted and are shutting down.
- outcome getOrElse false
- }
- }
-
- case class TestDirectory(category: TestCategory, location: Directory) extends TestEntity { }
- case class TestFile(category: TestCategory, location: File) extends TestEntity { }
-}
diff --git a/src/partest/scala/tools/partest/Housekeeping.scala b/src/partest/scala/tools/partest/Housekeeping.scala
deleted file mode 100644
index a624ca8adb..0000000000
--- a/src/partest/scala/tools/partest/Housekeeping.scala
+++ /dev/null
@@ -1,187 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.util.control.Exception.catching
-import util._
-import nsc.io._
-import Process.runtime
-import Properties._
-
-/** An agglomeration of code which is low on thrills. Hopefully
- * it operates so quietly in the background that you never have to
- * look at this file.
- */
-trait Housekeeping {
- self: Universe =>
-
- /** Orderly shutdown on ctrl-C. */
- @volatile private var _shuttingDown = false
- protected def setShuttingDown() = {
- /** Whatever we want to do as shutdown begins goes here. */
- if (!_shuttingDown) {
- warning("Received shutdown signal, partest is cleaning up...\n")
- _shuttingDown = true
- }
- }
- def isShuttingDown = _shuttingDown
-
- /** Execute some code with a shutdown hook in place. This is
- * motivated by the desire not to leave the filesystem full of
- * junk when someone ctrl-Cs a test run.
- */
- def withShutdownHook[T](hook: => Unit)(body: => T): Option[T] =
- /** Java doesn't like it if you keep adding and removing shutdown
- * hooks after shutdown has begun, so we trap the failure.
- */
- catching(classOf[IllegalStateException]) opt {
- val t = new Thread() {
- override def run() = {
- setShuttingDown()
- hook
- }
- }
- runtime addShutdownHook t
-
- try body
- finally runtime removeShutdownHook t
- }
-
- /** Search for a directory, possibly given only a name, by starting
- * at the current dir and walking upward looking for it at each level.
- */
- protected def searchForDir(name: String): Directory = {
- val result = Path(name) ifDirectory (x => x.normalize) orElse {
- val cwd = Directory.Current getOrElse error("user.dir property not set")
- val dirs = cwd :: cwd.parents map (_ / name)
-
- Path onlyDirs dirs map (_.normalize) headOption
- }
-
- result getOrElse error("Fatal: could not find directory '%s'" format name)
- }
-
- /** Paths we ignore for most purposes.
- */
- def ignorePath(x: Path) = {
- (x.name startsWith ".") ||
- (x.isDirectory && ((x.name == "lib") || x.hasExtension("obj", "svn")))
- }
- /** Make a possibly relative path absolute using partestDir as the base.
- */
- def absolutize(path: String) = Path(path) toAbsoluteWithRoot partestDir
-
- /** Go on a deleting binge.
- */
- def cleanupAll() {
- if (isNoCleanup)
- return
-
- val (dirCount, fileCount) = (cleanupObjDirs(), cleanupLogs() + cleanupJunk())
- if (dirCount + fileCount > 0)
- normal("Cleaned up %d directories and %d files.\n".format(dirCount, fileCount))
- }
-
- def cleanupObjDirs() = countTrue(allObjDirs collect { case x if x.exists => x.deleteRecursively() })
- def cleanupJunk() = countTrue(allClassFiles collect { case x if x.exists => x.delete() })
- def cleanupLogs() = countTrue(allLogFiles collect { case x if x.exists => x.delete() })
-
- /** Look through every file in the partest directory and ask around
- * to make sure someone knows him. Complain about strangers.
- */
- def validateAll() {
- def denotesTest(p: Path) = allCategories exists (_ denotesTest p)
- def isMSILcheck(p: Path) = p.name endsWith "-msil.check"
-
- def analyzeCategory(cat: DirBasedCategory) = {
- val allTests = cat.enumerate
- val otherPaths = cat.root walkFilter (x => !ignorePath(x)) filterNot (cat denotesTest _) filterNot isMSILcheck toList
- val count = otherPaths.size
-
- println("Validating %d non-test paths in %s.".format(count, cat.kind))
-
- for (path <- otherPaths) {
- (allTests find (_ acknowledges path)) match {
- case Some(test) => if (isVerbose) println(" OK: '%s' is claimed by '%s'".format(path, test.label))
- case _ => println(">> Unknown path '%s'" format path)
- }
- }
- }
-
- allCategories collect { case x: DirBasedCategory => analyzeCategory(x) }
- }
-
- trait TestHousekeeping {
- self: TestEntity =>
-
- /** Calculating derived files. Given a test like
- * files/run/foo.scala or files/run/foo/
- * This creates paths like foo.check, foo.flags, etc.
- */
- def withExtension(extension: String) = categoryDir / "%s.%s".format(label, extension)
-
- /** True for a path if this test acknowledges it belongs to this test.
- * Overridden by some categories.
- */
- def acknowledges(path: Path): Boolean = {
- val loc = location.normalize
- val knownPaths = List(scalaOptsFile, javaOptsFile, commandFile, logFile, checkFile) ++ jarsInTestDir
- def isContainedSource = location.isDirectory && isJavaOrScala(path) && (path.normalize startsWith loc)
-
- (knownPaths exists (_ isSame path)) || isContainedSource
- }
-
- /** This test "responds to" this String. This could mean anything -- it's a
- * way of specifying ad-hoc collections of tests to exercise only a subset of tests.
- * At present it looks for the given String in all the test sources.
- */
- def respondsToString(str: String) = containsString(str)
- def containsString(str: String) = {
- debug("Checking %s for \"%s\"".format(sourceFiles mkString ", ", str))
- sourceFiles map safeSlurp exists (_ contains str)
- }
-
- def possiblyTimed[T](body: => T): T = {
- if (isStats) timed(recordTestTiming(label, _))(body)
- else body
- }
-
- private def prepareForTestRun() = {
- // make sure we have a clean slate
- deleteLog(force = true)
- if (outDir.exists)
- outDir.deleteRecursively()
-
- // recreate object dir
- outDir createDirectory true
- }
- def deleteOutDir() = outDir.deleteRecursively()
- def deleteShutdownHook() = { debug("Shutdown hook deleting " + outDir) ; deleteOutDir() }
-
- protected def runWrappers[T](body: => T): Option[T] = {
- prepareForTestRun()
-
- withShutdownHook(deleteShutdownHook()) {
- loggingOutAndErr {
- val result = possiblyTimed { body }
- if (!isNoCleanup)
- deleteOutDir()
-
- result
- }
- }
- }
-
- override def toString = location.path
- override def equals(other: Any) = other match {
- case x: TestEntity => location.normalize == x.location.normalize
- case _ => false
- }
- override def hashCode = location.normalize.hashCode
- }
-
- private def countTrue(f: => Iterator[Boolean]) = f filter (_ == true) length
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/Partest.scala b/src/partest/scala/tools/partest/Partest.scala
deleted file mode 100644
index b3fe9a98ef..0000000000
--- a/src/partest/scala/tools/partest/Partest.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import nsc.util._
-import category.AllCategories
-
-/** Global object for a Partest run. It is completely configured by the list
- * of arguments passed to the constructor (although there are a few properties
- * and environment variables which can influence matters.) See PartestSpec.scala
- * for the complete list.
- */
-class Partest(args: List[String]) extends {
- val parsed = PartestSpec(args: _*)
-} with Universe with PartestSpec with cmd.Instance with AllCategories {
-
- if (parsed.propertyArgs.nonEmpty)
- debug("Partest property args: " + fromArgs(parsed.propertyArgs))
-
- debug("Partest created with args: " + fromArgs(args))
-
- def helpMsg = PartestSpec.helpMsg
-
- // The abstract values from Universe.
- lazy val testBuildDir = searchForDir(buildDir)
- lazy val partestDir = searchForDir(rootDir)
- lazy val allCategories = List(Pos, Neg, Run, Jvm, Res, Shootout, Scalap, Scalacheck, BuildManager, Script)
- lazy val selectedCategories = if (isAllImplied) allCategories else specifiedCats
-
- def specifiedTests = parsed.residualArgs map (x => Path(x).normalize)
- def specifiedKinds = testKinds filter (x => isSet(x) || (runSets contains x))
- def specifiedCats = specifiedKinds flatMap (x => allCategories find (_.kind == x))
- def isAllImplied = isAll || (specifiedTests.isEmpty && specifiedKinds.isEmpty)
-
- /** Assembles a filter based on command line options which restrict the test set
- * --grep limits to only matching tests
- * --failed limits to only recently failed tests (log file is present)
- * --<category> limits to only the given tests and categories (but --all overrides)
- * path/to/Test limits to only the given tests and categories
- */
- lazy val filter = {
- def indivFilter(test: TestEntity) = specifiedTests contains test.location.normalize
- def categoryFilter(test: TestEntity) = specifiedCats contains test.category
- def indivOrCat(test: TestEntity) = isAllImplied || indivFilter(test) || categoryFilter(test) // combines previous two
-
- def failedFilter(test: TestEntity) = !isFailed || (test.logFile exists)
- def grepFilter(test: TestEntity) = grepExpr.isEmpty || (test containsString grepExpr.get)
- def combinedFilter(x: TestEntity) = indivOrCat(x) && failedFilter(x) && grepFilter(x) // combines previous three
-
- combinedFilter _
- }
-
- def launchTestSuite() = {
- def onTimeout() = {
- warning("Partest test run timed out after " + timeout + " seconds.\n")
- System.exit(-1)
- }
- val alarm = new Alarmer(AlarmerAction(timeout, () => onTimeout()))
-
- try runSelection(selectedCategories, filter)
- finally alarm.cancelAll()
- }
-}
-
-object Partest {
- def fromBuild(dir: String, args: String*): Partest = apply("--builddir" +: dir +: args: _*)
- def apply(args: String*): Partest = new Partest(args.toList)
-
- // builds without partest jars won't actually work
- def starr() = fromBuild("")
- def locker() = fromBuild("build/locker")
- def quick() = fromBuild("build/quick")
- def pack() = fromBuild("build/pack")
- def strap() = fromBuild("build/strap")
- def dist() = fromBuild("dists/latest")
-}
-
diff --git a/src/partest/scala/tools/partest/PartestDefaults.scala b/src/partest/scala/tools/partest/PartestDefaults.scala
new file mode 100644
index 0000000000..139c54dedd
--- /dev/null
+++ b/src/partest/scala/tools/partest/PartestDefaults.scala
@@ -0,0 +1,30 @@
+package scala.tools
+package partest
+
+import nsc.io.{ File, Path, Process, Directory }
+import util.{ PathResolver }
+import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
+
+object PartestDefaults {
+ import nsc.Properties._
+ private def wrapAccessControl[T](body: => Option[T]): Option[T] =
+ try body catch { case _: java.security.AccessControlException => None }
+
+ def testRootName = propOrNone("partest.root")
+ def srcDirName = propOrElse("partest.srcdir", "files")
+ def testRootDir = testRootName map (x => Directory(x))
+
+ def classPath = PathResolver.Environment.javaUserClassPath // XXX
+
+ def javaCmd = propOrElse("partest.javacmd", "java")
+ def javacCmd = propOrElse("partest.javac_cmd", "javac")
+ def javaOpts = propOrElse("partest.java_opts", "")
+ def scalacOpts = propOrElse("partest.scalac_opts", "-deprecation")
+
+ def testBuild = propOrNone("partest.build")
+ def errorCount = propOrElse("partest.errors", "0").toInt
+ def numActors = propOrElse("partest.actors", "8").toInt
+ def poolSize = wrapAccessControl(propOrNone("actors.corePoolSize"))
+
+ def timeout = "1200000"
+}
diff --git a/src/partest/scala/tools/partest/PartestSpec.scala b/src/partest/scala/tools/partest/PartestSpec.scala
deleted file mode 100644
index c25119b3af..0000000000
--- a/src/partest/scala/tools/partest/PartestSpec.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import cmd._
-
-/** This takes advantage of bits of scala goodness to fully define a command
- * line program with a minimum of duplicated code. When the specification object
- * is created, the vals are evaluated in order and each of them side effects
- * a private accumulator. What emerges is a full list of the valid unary
- * and binary arguments, as well as autogenerated help.
- */
-trait PartestSpec extends Spec with Meta.StdOpts with Interpolation {
- def referenceSpec = PartestSpec
- def programInfo = Spec.Info("partest", "", "scala.tools.partest.Runner")
- private val kind = new Spec.Accumulator[String]()
- protected def testKinds = kind.get
-
- private implicit val tokenizeString = FromString.ArgumentsFromString // String => List[String]
-
- help("""
- |# Pro Tip! Instant bash completion: `partest --bash` (note backticks)
- |Usage: partest [<options>] [<test> <test> ...]
- | <test>: a path to a test designator, typically a .scala file or a directory.
- | Examples: files/pos/test1.scala, files/res/bug785
- |
- | Test categories:""".stripMargin)
-
- val isAll = ("all" / "run all tests (default, unless no options given)" --?)
- (kind("pos") / "Compile files that are expected to build" --?)
- (kind("neg") / "Compile files that are expected to fail" --?)
- (kind("run") / "Test JVM backend" --?)
- (kind("jvm") / "Test JVM backend" --?)
- (kind("res") / "Run resident compiler scenarii" --?)
- (kind("buildmanager") / "Run Build Manager scenarii" --?)
- (kind("scalacheck") / "Run Scalacheck tests" --?)
- (kind("script") / "Run script files" --?)
- (kind("shootout") / "Run shootout tests" --?)
- (kind("scalap") / "Run scalap tests" --?)
-
- heading ("""Test "smart" categories:""")
- val grepExpr = "grep" / "run all tests with a source file containing <expr>" --|
- val isFailed = "failed" / "run all tests which failed on the last run" --?
-
- heading ("Specifying paths and additional flags, ~ means repository root:")
-
- val rootDir = "rootdir" / "path from ~ to partest" defaultTo "test"
- val buildDir = "builddir" / "path from ~ to test build" defaultTo "build/pack"
- val srcDir = "srcdir" / "path from --rootdir to sources" defaultTo "files"
- val javaOpts = "javaopts" / "flags to java on all runs" defaultToEnv "JAVA_OPTS"
- val javacOpts = "javacopts" / "flags to javac on all runs" defaultToEnv "JAVAC_OPTS"
- val scalacOpts = "scalacopts" / "flags to scalac on all tests" defaultToEnv "SCALAC_OPTS"
-
- "pack" / "" expandTo ("--builddir", "build/pack")
- "quick" / "" expandTo ("--builddir", "build/quick")
-
- heading ("Options influencing output:")
- val isTrace = "trace" / "show the individual steps taken by each test" --?
- val isShowDiff = "show-diff" / "show diff between log and check file" --?
- val isShowLog = "show-log" / "show log on failures" --?
- val isDryRun = "dry-run" / "do not run tests, only show their traces." --?
- val isTerse = "terse" / "be less verbose (almost silent except for failures)" --?
- val isVerbose = "verbose" / "be more verbose (additive with --trace)" --?
- val isDebug = "debug" / "maximum debugging output" --?
- val isAnsi = "ansi" / "print output in color" --?
-
- heading ("Other options:")
- val timeout = "timeout" / "Overall timeout in seconds" defaultTo 7200
- val testWarning = "test-warning" / "Test warning in seconds" defaultTo 90
- val testTimeout = "test-timeout" / "Test timeout in seconds" defaultTo 900
- val isCleanup = "cleanup" / "delete all stale files and dirs before run" --?
- val isNoCleanup = "nocleanup" / "do not delete any logfiles or object dirs" --?
- val isStats = "stats" / "collect and print statistics about the tests" --?
- val isValidate = "validate" / "examine test filesystem for inconsistencies" --?
- val isUpdateCheck = "update-check" / "overwrite checkFile if diff fails" --?
-
- "version" / "print version" --> runAndExit(println(Properties.versionMsg))
-
- // no help for anything below this line - secret options
- // mostly intended for property configuration.
- val runSets = ("runsets" --^) getOrElse Nil
- val isNoAlarms = "noalarms" --?
- val isInsideAnt = "is-in-ant" --?
-}
-
-object PartestSpec extends PartestSpec with Property {
- lazy val propMapper = new PropertyMapper(PartestSpec) {
- override def isPassThrough(key: String) = key == "partest.options"
- }
-
- type ThisCommandLine = PartestCommandLine
- class PartestCommandLine(args: List[String]) extends SpecCommandLine(args) {
- override def errorFn(msg: String) = printAndExit("Error: " + msg)
-
- def propertyArgs = PartestSpec.propertyArgs
- }
-
- override def creator(args: List[String]): PartestCommandLine = new PartestCommandLine(args)
-}
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
new file mode 100644
index 0000000000..230a6f73ec
--- /dev/null
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -0,0 +1,287 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.tools
+package partest
+
+import scala.actors.Actor._
+import scala.util.Properties.setProp
+import scala.tools.nsc.io.{ Directory, Path => SPath }
+import nsc.Settings
+import nsc.util.ClassPath
+import util.PathResolver
+import scala.tools.ant.sabbus.CompilationPathProperty
+
+import java.io.File
+import java.net.URLClassLoader
+import java.lang.reflect.Method
+
+import org.apache.tools.ant.Task
+import org.apache.tools.ant.types.{Path, Reference, FileSet}
+
+class PartestTask extends Task with CompilationPathProperty {
+
+ def addConfiguredPosTests(input: FileSet) {
+ posFiles = Some(input)
+ }
+
+ def addConfiguredNegTests(input: FileSet) {
+ negFiles = Some(input)
+ }
+
+ def addConfiguredRunTests(input: FileSet) {
+ runFiles = Some(input)
+ }
+
+ def addConfiguredJvmTests(input: FileSet) {
+ jvmFiles = Some(input)
+ }
+
+ def addConfiguredResidentTests(input: FileSet) {
+ residentFiles = Some(input)
+ }
+
+ def addConfiguredBuildManagerTests(input: FileSet) {
+ buildManagerFiles = Some(input)
+ }
+
+ def addConfiguredScalacheckTests(input: FileSet) {
+ scalacheckFiles = Some(input)
+ }
+
+ def addConfiguredScriptTests(input: FileSet) {
+ scriptFiles = Some(input)
+ }
+
+ def addConfiguredShootoutTests(input: FileSet) {
+ shootoutFiles = Some(input)
+ }
+
+ def addConfiguredScalapTests(input: FileSet) {
+ scalapFiles = Some(input)
+ }
+
+ def setSrcDir(input: String) {
+ srcDir = Some(input)
+ }
+
+ def setClasspath(input: Path) {
+ if (classpath.isEmpty)
+ classpath = Some(input)
+ else
+ classpath.get.append(input)
+ }
+
+ def createClasspath(): Path = {
+ if (classpath.isEmpty) classpath = Some(new Path(getProject()))
+ classpath.get.createPath()
+ }
+
+ def setClasspathref(input: Reference) {
+ createClasspath().setRefid(input)
+ }
+
+ def setShowLog(input: Boolean) {
+ showLog = input
+ }
+
+ def setShowDiff(input: Boolean) {
+ showDiff = input
+ }
+
+ def setErrorOnFailed(input: Boolean) {
+ errorOnFailed = input
+ }
+
+ def setJavaCmd(input: File) {
+ javacmd = Some(input)
+ }
+
+ def setJavacCmd(input: File) {
+ javaccmd = Some(input)
+ }
+
+ def setScalacOpts(opts: String) {
+ scalacOpts = Some(opts)
+ }
+
+ def setTimeout(delay: String) {
+ timeout = Some(delay)
+ }
+
+ def setDebug(input: Boolean) {
+ debug = input
+ }
+
+ def setJUnitReportDir(input: File) {
+ jUnitReportDir = Some(input)
+ }
+
+ private var classpath: Option[Path] = None
+ private var srcDir: Option[String] = None
+ private var javacmd: Option[File] = None
+ private var javaccmd: Option[File] = None
+ private var showDiff: Boolean = false
+ private var showLog: Boolean = false
+ private var runFailed: Boolean = false
+ private var posFiles: Option[FileSet] = None
+ private var negFiles: Option[FileSet] = None
+ private var runFiles: Option[FileSet] = None
+ private var jvmFiles: Option[FileSet] = None
+ private var residentFiles: Option[FileSet] = None
+ private var buildManagerFiles: Option[FileSet] = None
+ private var scalacheckFiles: Option[FileSet] = None
+ private var scriptFiles: Option[FileSet] = None
+ private var shootoutFiles: Option[FileSet] = None
+ private var scalapFiles: Option[FileSet] = None
+ private var errorOnFailed: Boolean = false
+ private var scalacOpts: Option[String] = None
+ private var timeout: Option[String] = None
+ private var jUnitReportDir: Option[File] = None
+ private var debug = false
+
+ def fileSetToDir(fs: FileSet) = Directory(fs getDir getProject)
+ def fileSetToArray(fs: FileSet): Array[SPath] = {
+ val root = fileSetToDir(fs)
+ (fs getDirectoryScanner getProject).getIncludedFiles map (root / _)
+ }
+
+ private def getFiles(fileSet: Option[FileSet]): Array[File] = fileSet match {
+ case None => Array()
+ case Some(fs) => fileSetToArray(fs) filterNot (_ hasExtension "log") map (_.jfile)
+ }
+
+ private def getFilesAndDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
+ case None => Array()
+ case Some(fs) =>
+ def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
+
+ val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
+ val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
+ val dirResult = dirTests.toList.toArray map (_.jfile)
+
+ dirResult ++ fileTests
+ }
+
+ private def getPosFiles = getFilesAndDirs(posFiles)
+ private def getNegFiles = getFilesAndDirs(negFiles)
+ private def getRunFiles = getFiles(runFiles)
+ private def getJvmFiles = getFilesAndDirs(jvmFiles)
+ private def getResidentFiles = getFiles(residentFiles)
+ private def getBuildManagerFiles = getFilesAndDirs(buildManagerFiles)
+ private def getScalacheckFiles = getFiles(scalacheckFiles)
+ private def getScriptFiles = getFiles(scriptFiles)
+ private def getShootoutFiles = getFiles(shootoutFiles)
+ private def getScalapFiles = getFiles(scalapFiles)
+
+ override def execute() {
+ if (isPartestDebug)
+ setProp("partest.debug", "true")
+
+ srcDir foreach (x => setProp("partest.srcdir", x))
+
+ val classpath = this.compilationPath getOrElse error("Mandatory attribute 'compilationPath' is not set.")
+
+ val scalaLibrary = {
+ (classpath.list map { fs => new File(fs) }) find { f =>
+ f.getName match {
+ case "scala-library.jar" => true
+ case "library" if (f.getParentFile.getName == "classes") => true
+ case _ => false
+ }
+ }
+ } getOrElse error("Provided classpath does not contain a Scala library.")
+
+ val antRunner = new scala.tools.partest.nest.AntRunner
+ val antFileManager = antRunner.fileManager
+
+ antFileManager.showDiff = showDiff
+ antFileManager.showLog = showLog
+ antFileManager.failed = runFailed
+ antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*)
+ antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath
+
+ javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath)
+ javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath)
+ scalacOpts foreach (antFileManager.SCALAC_OPTS = _)
+ timeout foreach (antFileManager.timeout = _)
+
+ type TFSet = (Array[File], String, String)
+ val testFileSets = List(
+ (getPosFiles, "pos", "Compiling files that are expected to build"),
+ (getNegFiles, "neg", "Compiling files that are expected to fail"),
+ (getRunFiles, "run", "Compiling and running files"),
+ (getJvmFiles, "jvm", "Compiling and running files"),
+ (getResidentFiles, "res", "Running resident compiler scenarii"),
+ (getBuildManagerFiles, "buildmanager", "Running Build Manager scenarii"),
+ (getScalacheckFiles, "scalacheck", "Running scalacheck tests"),
+ (getScriptFiles, "script", "Running script files"),
+ (getShootoutFiles, "shootout", "Running shootout tests"),
+ (getScalapFiles, "scalap", "Running scalap tests")
+ )
+
+ def runSet(set: TFSet): (Int, Int, Iterable[String]) = {
+ val (files, name, msg) = set
+ if (files.isEmpty) (0, 0, List())
+ else {
+ log(msg)
+ val results: Iterable[(String, Int)] = antRunner.reflectiveRunTestsForFiles(files, name)
+ val (succs, fails) = resultsToStatistics(results)
+
+ val failed: Iterable[String] = results collect {
+ case (path, 1) => path + " [FAILED]"
+ case (path, 2) => path + " [TIMOUT]"
+ }
+
+ // create JUnit Report xml files if directory was specified
+ jUnitReportDir foreach { d =>
+ d.mkdir
+
+ val report = testReport(name, results, succs, fails)
+ scala.xml.XML.save(d.getAbsolutePath+"/"+name+".xml", report)
+ }
+
+ (succs, fails, failed)
+ }
+ }
+
+ val _results = testFileSets map runSet
+ val allSuccesses = _results map (_._1) sum
+ val allFailures = _results map (_._2) sum
+ val allFailedPaths = _results flatMap (_._3)
+
+ def f = if (errorOnFailed && allFailures > 0) error(_) else log(_: String)
+ def s = if (allFailures > 1) "s" else ""
+ val msg =
+ if (allFailures > 0)
+ "Test suite finished with %d case%s failing:\n".format(allFailures, s)+
+ allFailedPaths.mkString("\n")
+ else if (allSuccesses == 0) "There were no tests to run."
+ else "Test suite finished with no failures."
+
+ f(msg)
+ }
+ def oneResult(res: (String, Int)) =
+ <testcase name={res._1}>{
+ res._2 match {
+ case 0 => scala.xml.NodeSeq.Empty
+ case 1 => <failure message="Test failed"/>
+ case 2 => <failure message="Test timed out"/>
+ }
+ }</testcase>
+
+ def testReport(kind: String, results: Iterable[(String, Int)], succs: Int, fails: Int) =
+ <testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
+ <properties/>
+ {
+ results.map(oneResult(_))
+ }
+ </testsuite>
+}
diff --git a/src/partest/scala/tools/partest/Results.scala b/src/partest/scala/tools/partest/Results.scala
deleted file mode 100644
index 5d0e300136..0000000000
--- a/src/partest/scala/tools/partest/Results.scala
+++ /dev/null
@@ -1,121 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import scala.collection.immutable
-
-trait Results {
- self: Universe =>
-
- /** A collection of tests for a Worker.
- */
- case class TestsToRun(entities: List[TestEntity])
-
- /** The response from a Worker who has been given TestsToRun.
- */
- case class ResultsOfRun(results: immutable.Map[TestEntity, TestResult])
-
- /** The result of a single test. (0: OK, 1: FAILED, 2: TIMEOUT)
- */
- sealed abstract class TestResult(val state: Int, val description: String) {
- def entity: TestEntity
-
- def passed = state == 0
- def colorize(s: String): String
- def show(msg: String) =
- if (!isShuttingDown)
- showResult(colorize(description), msg)
-
- private def outputPrefix = if (isInsideAnt) "" else markNormal("partest: ")
- private def name = src relativize entity.location // e.g. "neg/test.scala"
- private def showResult(status: String, extraMsg: String) =
- normal(outputPrefix + "[...]/%-40s [%s] %s\n".format(name, status, extraMsg))
-
- override def equals(other: Any) = other match {
- case x: TestResult => entity == x.entity
- case _ => false
- }
- override def hashCode = entity.hashCode
- override def toString = "%s [%s]".format(entity, description)
- }
-
- class Success(val entity: TestEntity) extends TestResult(0, " OK ") {
- def colorize(s: String) = markSuccess(s)
- override def show(msg: String) = if (!isTerse) super.show(msg)
- }
- class Failure(val entity: TestEntity) extends TestResult(1, " FAILED ") {
- def colorize(s: String) = markFailure(s)
-
- override def show(msg: String) = {
- super.show(msg)
-
- if (isShowDiff || isTrace)
- normal(entity.diffOutput)
-
- if (isShowLog || isTrace)
- normal(toStringTrunc(entity.failureMessage(), 1600))
- }
- override def toString = List(super.toString, toStringTrunc(entity.failureMessage(), 400)) mkString "\n"
- }
- class Timeout(val entity: TestEntity) extends TestResult(2, "TIME OUT") {
- def colorize(s: String) = markFailure(s)
- }
-
- object TestResult {
- def apply(entity: TestEntity, success: Boolean) =
- if (success) new Success(entity)
- else new Failure(entity)
-
- def apply(entity: TestEntity, state: Int) = state match {
- case 0 => new Success(entity)
- case 1 => new Failure(entity)
- case 2 => new Timeout(entity)
- }
- def unapply(x: Any) = x match {
- case x: TestResult => Some((x.entity, x.state))
- case _ => None
- }
- }
-
- /** The combined results of any number of tests.
- */
- case class CombinedTestResults(
- passed: Int,
- failed: Int,
- elapsedMilliseconds: Long,
- failures: List[TestResult]
- ) {
- // housekeeping
- val elapsedSecs = elapsedMilliseconds / 1000
- val elapsedMins = elapsedSecs / 60
- val elapsedHrs = elapsedMins / 60
- val dispMins = elapsedMins - elapsedHrs * 60
- val dispSecs = elapsedSecs - elapsedMins * 60
-
- def total = passed + failed
- def hasFailures = failed > 0
- def exitCode = if (expectedErrors == failed) 0 else 1
-
- def ++(x: CombinedTestResults) = CombinedTestResults(
- passed + x.passed,
- failed + x.failed,
- elapsedMilliseconds + x.elapsedMilliseconds,
- failures ::: x.failures
- )
-
- def elapsedString = "%02d:%02d:%02d".format(elapsedHrs, dispMins, dispSecs)
- def failuresString = {
- if (failures.isEmpty) ""
- else "Summary of failures:" :: failures mkString ("\n", "\n", "")
- }
-
- override def toString =
- if (total == 0) "There were no tests to run."
- else if (isDryRun) "%d tests would be run." format total
- else if (hasFailures) "%d of %d tests failed (elapsed time: %s)".format(failed, total, elapsedString) + failuresString
- else "All %d tests were successful (elapsed time: %s)".format(total, elapsedString)
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/Runner.scala b/src/partest/scala/tools/partest/Runner.scala
deleted file mode 100644
index 1a28e60896..0000000000
--- a/src/partest/scala/tools/partest/Runner.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import nsc.io._
-
-object Runner {
- def main(args: Array[String]) {
- val runner = Partest(args: _*)
- import runner._
-
- if (args.isEmpty) return println(helpMsg)
- if (isValidate) return validateAll()
-
- printConfigBanner()
-
- if (isCleanup)
- cleanupAll()
-
- val result = launchTestSuite()
- val exitCode = result.exitCode
- val message = "\n" + result + "\n"
-
- if (exitCode == 0) success(message)
- else failure(message)
-
- if (isStats)
- showTestStatistics()
-
- System exit exitCode
- }
-}
diff --git a/src/partest/scala/tools/partest/Statistics.scala b/src/partest/scala/tools/partest/Statistics.scala
deleted file mode 100644
index 2ea3c6e8f0..0000000000
--- a/src/partest/scala/tools/partest/Statistics.scala
+++ /dev/null
@@ -1,46 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-
-import scala.collection.mutable.HashMap
-
-trait Statistics {
- /** Only collected when --stats is given. */
- lazy val testStatistics = new HashMap[String, Long]
-
- /** Given function and block of code, evaluates code block,
- * calls function with milliseconds elapsed, and returns block result.
- */
- def timed[T](f: Long => Unit)(body: => T): T = {
- val start = System.currentTimeMillis
- val result = body
- val end = System.currentTimeMillis
-
- f(end - start)
- result
- }
- /** Times body and returns both values.
- */
- def timed2[T](body: => T): (Long, T) = {
- var milliSeconds = 0L
- val result = timed(x => milliSeconds = x)(body)
-
- (milliSeconds, result)
- }
-
- def resultsToStatistics(results: Iterable[(_, Int)]): (Int, Int) =
- (results partition (_._2 == 0)) match {
- case (winners, losers) => (winners.size, losers.size)
- }
-
- def recordTestTiming(name: String, milliseconds: Long) =
- synchronized { testStatistics(name) = milliseconds }
-
- def showTestStatistics() {
- testStatistics.toList sortBy (-_._2) foreach { case (k, v) => println("%s: %.2f seconds".format(k, (v.toDouble / 1000))) }
- }
-}
diff --git a/src/partest/scala/tools/partest/Universe.scala b/src/partest/scala/tools/partest/Universe.scala
deleted file mode 100644
index 942fc1a8be..0000000000
--- a/src/partest/scala/tools/partest/Universe.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-
-import nsc.io._
-import category.AllCategories
-import io.Logging
-
-/** The high level view of the partest infrastructure.
- */
-abstract class Universe
- extends Entities
- with BuildContributors
- with Logging
- with Dispatcher
- with Statistics
- with Housekeeping
- with Results
- with PartestCompilation
- with PartestSpec
- with Config
- with Alarms
- with Actions
- with Categories {
-
- /** The abstract values from which all else is derived. */
- def partestDir: Directory
- def testBuildDir: Directory
- def allCategories: List[TestCategory]
- def selectedCategories: List[TestCategory]
-
- /** Some plausibly abstract types. */
- type TestBuild <: BuildContributor // e.g. quick, pack
- type TestCategory <: AbsTestCategory // e.g. pos, neg, run
- type TestEntity <: AbsTestEntity // e.g. files/pos/test25.scala
- type TestSequence <: AbsTestSequence // e.g. compile, run, diff
-
- /** Although TestStep isn't much more than Function1 right now,
- * it exists this way so it can become more capable.
- */
- implicit def f1ToTestStep(f: TestEntity => Boolean): TestStep =
- new TestStep { def apply(test: TestEntity) = f(test) }
-
- abstract class TestStep extends (TestEntity => Boolean) {
- def apply(test: TestEntity): Boolean
- }
-
- /** An umbrella category of tests, such as "pos" or "run".
- */
- trait AbsTestCategory extends BuildContributor {
- type TestSettings
-
- def kind: String
- def testSequence: TestSequence
- def denotesTest(location: Path): Boolean
-
- def createTest(location: Path): TestEntity
- def createSettings(entity: TestEntity): TestSettings
- def enumerate: List[TestEntity]
- }
-
- /** A single test. It may involve multiple files, but only a
- * single path is used to designate it.
- */
- trait AbsTestEntity extends BuildContributor {
- def category: TestCategory
- def location: Path
- def onException(x: Throwable): Unit
- def testClasspath: String
-
- /** Most tests will use the sequence defined by the category,
- * but the test can override and define a custom sequence.
- */
- def testSequence: TestSequence
-
- /** True if this test recognizes the given path as a piece of it.
- * For validation purposes.
- */
- def acknowledges(path: Path): Boolean
- }
-
- /** Every TestEntity is partly characterized by a series of actions
- * which are applied to the TestEntity in the given order. The test
- * passes if all those actions return true, fails otherwise.
- */
- trait AbsTestSequence {
- def actions: List[TestStep]
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/ant/JavaTask.scala b/src/partest/scala/tools/partest/ant/JavaTask.scala
deleted file mode 100644
index 6740554dd8..0000000000
--- a/src/partest/scala/tools/partest/ant/JavaTask.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package ant
-
-import org.apache.tools.ant.Task
-import org.apache.tools.ant.taskdefs.Java
-import org.apache.tools.ant.types.Environment
-
-import scala.tools.nsc.io._
-import scala.tools.nsc.util.ClassPath
-import cmd.Spec._
-
-class JavaTask extends Java {
- override def getTaskName() = "partest"
- private val scalaRunnerClass = "scala.tools.nsc.MainGenericRunner"
- private val partestRunnerClass = "scala.tools.partest.Runner"
- def defaultJvmArgs = "-Xms64M -Xmx768M -Xss768K -XX:MaxPermSize=96M"
-
- protected def rootDir = prop("partest.rootdir") getOrElse (baseDir / "test").path
- protected def partestJVMArgs = prop("partest.jvm.args") getOrElse defaultJvmArgs
- protected def runnerArgs = List("-usejavacp", partestRunnerClass, "--javaopts", partestJVMArgs)
-
- private def baseDir = Directory(getProject.getBaseDir)
- private def prop(s: String) = Option(getProject getProperty s)
- private def jvmline(s: String) = returning(createJvmarg())(_ setLine s)
- private def addArg(s: String) = returning(createArg())(_ setValue s)
-
- private def newKeyValue(key: String, value: String) =
- returning(new Environment.Variable)(x => { x setKey key ; x setValue value })
-
- def setDefaults() {
- setFork(true)
- setFailonerror(true)
- getProject.setSystemProperties()
- setClassname(scalaRunnerClass)
- addSysproperty(newKeyValue("partest.is-in-ant", "true"))
- jvmline(partestJVMArgs)
- runnerArgs foreach addArg
-
- // do we want basedir or rootDir to be the cwd?
- // setDir(Path(rootDir).jfile)
- }
-
- override def init() = {
- super.init()
- setDefaults()
- }
-}
-
diff --git a/src/partest/scala/tools/partest/antlib.xml b/src/partest/scala/tools/partest/antlib.xml
index af36f11368..b3b98e853f 100644
--- a/src/partest/scala/tools/partest/antlib.xml
+++ b/src/partest/scala/tools/partest/antlib.xml
@@ -1,3 +1,4 @@
<antlib>
- <taskdef name="partest" classname="scala.tools.partest.ant.JavaTask"/>
+ <taskdef name="partest"
+ classname="scala.tools.partest.PartestTask"/>
</antlib>
diff --git a/src/partest/scala/tools/partest/category/AllCategories.scala b/src/partest/scala/tools/partest/category/AllCategories.scala
deleted file mode 100644
index 953f80324b..0000000000
--- a/src/partest/scala/tools/partest/category/AllCategories.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package category
-
-trait AllCategories extends Compiler with Analysis with Runner {
- self: Universe =>
-
- object Pos extends DirBasedCategory("pos") { lazy val testSequence: TestSequence = List(compile) }
- object Neg extends DirBasedCategory("neg") { lazy val testSequence: TestSequence = List(checkFileRequired, not(compile), diff) }
- object Run extends DirBasedCategory("run") { lazy val testSequence: TestSequence = List(compile, run, diff) }
- object Jvm extends DirBasedCategory("jvm") { lazy val testSequence: TestSequence = List(compile, run, diff) }
-}
diff --git a/src/partest/scala/tools/partest/category/Analysis.scala b/src/partest/scala/tools/partest/category/Analysis.scala
deleted file mode 100644
index 2c6c208ee5..0000000000
--- a/src/partest/scala/tools/partest/category/Analysis.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package category
-
-import java.lang.{ ClassLoader => JavaClassLoader }
-import java.net.URL
-import nsc.util.ScalaClassLoader
-import nsc.io._
-
-class PartestClassLoader(urls: Array[URL], parent: JavaClassLoader) extends ScalaClassLoader.URLClassLoader(urls, parent) {
- def this(urls: Array[URL]) = this(urls, null)
- def bytes(path: String) = findBytesForClassName(path)
- def singleton(path: String) = tryToInitializeClass(path).get getField "MODULE$" get null
-
- /** Calls a method in an object via reflection.
- */
- def apply[T](className: String, methodName: String)(args: Any*): T = {
- def fail = error("Reflection failed on %s.%s".format(className, methodName))
- val clazz = tryToLoadClass(className) getOrElse fail
- val obj = singleton(className)
- val m = clazz.getMethods find (x => x.getName == methodName && x.getParameterTypes.size == args.size) getOrElse fail
-
- m.invoke(obj, args map (_.asInstanceOf[AnyRef]): _*).asInstanceOf[T]
- }
-}
-
-trait Analysis {
- self: Universe =>
-
- object Scalap extends DirBasedCategory("scalap") {
- val testSequence: TestSequence = List(checkFileRequired, compile, run, diff)
- override def denotesTest(p: Path) = p.isDirectory && (p.toDirectory.files exists (_.name == "result.test"))
- override def createTest(location: Path) = new ScalapTest(location)
-
- class ScalapTest(val location: Path) extends TestEntity {
- val category = Scalap
- val scalapMain = "scala.tools.scalap.Main$"
- val scalapMethod = "decompileScala"
-
- override def classpathPaths = super.classpathPaths :+ build.scalap
- override def checkFile = File(location / "result.test")
-
- private def runnerURLs = build.classpathPaths ::: classpathPaths map (_.toURL)
- private def createClassLoader = new PartestClassLoader(runnerURLs.toArray, this.getClass.getClassLoader)
-
- val isPackageObject = containsString("package object")
- val suffix = if (isPackageObject) ".package" else ""
- val className = location.name.capitalize + suffix
-
- override def run() = loggingResult {
- def loader = createClassLoader
- def bytes = loader.bytes(className)
-
- trace("scalap %s".format(className))
- if (isDryRun) ""
- else loader[String](scalapMain, scalapMethod)(bytes, isPackageObject)
- }
- }
- }
-}
diff --git a/src/partest/scala/tools/partest/category/Compiler.scala b/src/partest/scala/tools/partest/category/Compiler.scala
deleted file mode 100644
index 49775d5031..0000000000
--- a/src/partest/scala/tools/partest/category/Compiler.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package category
-
-import nsc.io._
-import nsc.reporters._
-import nsc.{ Settings, CompilerCommand }
-import scala.tools.nsc.interactive.RefinedBuildManager
-import util.copyPath
-
-trait Compiler {
- self: Universe =>
-
- /** Resident Compiler.
- * $SCALAC -d dir.obj -Xresident -sourcepath . "$@"
- */
- object Res extends DirBasedCategory("res") {
- lazy val testSequence: TestSequence = List(checkFileRequired, compile, diff)
-
- override def denotesTest(p: Path) = p.isDirectory && resFile(p).isFile
- override def createTest(location: Path) = new ResidentTest(location.toDirectory)
-
- override def createSettings(entity: TestEntity): TestSettings =
- returning(super.createSettings(entity)) { settings =>
- settings.resident.value = true
- settings.sourcepath.value = entity.sourcesDir.path
- }
-
- class ResidentTest(val location: Directory) extends TestEntity {
- val category = Res
- override def sourcesDir = categoryDir
-
- override def acknowledges(p: Path) =
- super.acknowledges(p) || (resFile(location) isSame p)
-
- private def residentCompilerCommands = safeLines(resFile(location))
- private def compileResident(global: PartestGlobal, lines: List[String]) = {
- def printPrompt = global inform "nsc> "
- val results =
- lines map { line =>
- printPrompt
- trace("compile " + line)
- isDryRun || global.partestCompile(toArgs(line) map (categoryDir / _ path), false)
- }
-
- printPrompt
-
- /** Note - some res tests are really "neg" style tests, so we can't
- * use the return value of the compile. The diff catches failures.
- */
- true // results forall (_ == true)
- }
-
- override def compile() = compileResident(newGlobal(Nil)._1, residentCompilerCommands)
- }
- private[Res] def resFile(p: Path) = p.toFile addExtension "res"
- }
-
- object BuildManager extends DirBasedCategory("buildmanager") {
- lazy val testSequence: TestSequence = List(checkFileRequired, compile, diff)
- override def denotesTest(p: Path) = p.isDirectory && testFile(p).isFile
- override def createTest(location: Path) = new BuildManagerTest(location.toDirectory)
-
- override def createSettings(entity: TestEntity): TestSettings =
- returning[TestSettings](super.createSettings(entity)) { settings =>
- settings.Ybuildmanagerdebug.value = true
- settings.sourcepath.value = entity.sourcesDir.path
- }
-
- class PartestBuildManager(settings: Settings, val reporter: ConsoleReporter) extends RefinedBuildManager(settings) {
- def errorFn(msg: String) = Console println msg
-
- override protected def newCompiler(newSettings: Settings) =
- new BuilderGlobal(newSettings, reporter)
-
- private def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
- fs flatMap (s => Option(AbstractFile getFile (Path(settings.sourcepath.value) / s path))) toSet
-
- def buildManagerCompile(line: String): Boolean = {
- val prompt = "builder > "
- reporter printMessage (prompt + line)
- val command = new CompilerCommand(toArgs(line), settings)
- val files = filesToSet(settings.sourcepath.value, command.files)
-
- update(files, Set.empty)
- true
- }
- }
-
- private[BuildManager] def testFile(p: Path) = (p / p.name addExtension "test").toFile
-
- class BuildManagerTest(val location: Directory) extends TestEntity {
- val category = BuildManager
-
- override def sourcesDir = outDir
- override def sourceFiles = Path onlyFiles (location walkFilter (_ != changesDir) filter isJavaOrScala toList)
- override def checkFile = File(location / location.name addExtension "check")
-
- override def acknowledges(p: Path) = super.acknowledges(p) || (p isSame testFile(location))
-
- def buildManagerCommands = safeLines(testFile(location))
- def changesDir = Directory(location / (location.name + ".changes"))
-
- override def compile() = {
- val settings = createSettings(this)
- val pbm = new PartestBuildManager(settings, newReporter(settings))
-
- // copy files
- for (source <- sourceFiles) {
- val target = outDir / (location.normalize relativize source)
- copyPath(source, target.toFile)
- }
-
- def runUpdate(line: String) = {
- val Array(srcName, replacement) = line split "=>"
- copyPath(File(changesDir / replacement), File(outDir / srcName))
- }
-
- def sendCommand(line: String): Boolean = {
- val compileRegex = """^>>compile (.*)$""".r
- val updateRegex = """^>>update\s+(.*)""".r
- trace("send: " + (line drop 2))
-
- isDryRun || (line match {
- case compileRegex(xs) => pbm.buildManagerCompile(xs)
- case updateRegex(line) => runUpdate(line)
- })
- }
-
- // send each line to the build manager
- buildManagerCommands forall sendCommand
- }
- }
- }
-}
-
diff --git a/src/partest/scala/tools/partest/category/Runner.scala b/src/partest/scala/tools/partest/category/Runner.scala
deleted file mode 100644
index 10bf5794a9..0000000000
--- a/src/partest/scala/tools/partest/category/Runner.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala Parallel Testing **
-** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.tools
-package partest
-package category
-
-import nsc.io._
-
-trait Runner {
- self: Universe =>
-
- /** Shootout.
- */
- object Shootout extends DirBasedCategory("shootout") {
- lazy val testSequence: TestSequence = List(compile, run, diff)
-
- override def denotesTest(p: Path) = isScala(p) && runner(p).isFile
- override def createTest(location: Path) = new ShootoutTest(location.toFile)
-
- class ShootoutTest(val location: File) extends TestEntity {
- val category = Shootout
- // The files in shootout are very free form, so acknowledge anything close.
- override def acknowledges(p: Path) =
- (p.parent.normalize isSame Shootout.root) && (p.name startsWith label)
-
- private def generated = File(outDir / "test.scala")
- private def runnerFile = runner(location)
- override def sourceFiles = List(generated)
-
- override def compile() = {
- trace("generate %s from %s, %s".format(tracePath(generated), tracePath(location), tracePath(runnerFile)))
- // generate source file (even on dry run, we need the path)
- generated.writeAll(location.slurp(), runnerFile.slurp())
-
- // compile generated file
- super.compile()
- }
- }
-
- private[Shootout] def runner(p: Path) = p addExtension "runner" toFile
- }
-
- object Scalacheck extends DirBasedCategory("scalacheck") {
- lazy val testSequence: TestSequence = List(compile, run)
- override def createTest(location: Path) = new ScalacheckTest(location)
-
- class ScalacheckTest(val location: Path) extends TestEntity {
- val category = Scalacheck
-
- import build.{ scalacheck, forkjoin }
- import org.scalacheck.Properties
- import org.scalacheck.Test.{ checkProperties, defaultParams, Result }
-
- override def classpathPaths = super.classpathPaths ::: List(scalacheck, forkjoin)
- private def arrayURLs = Array(scalacheck, outDir) map (_.toURL)
-
- /** For reasons I'm not entirely clear on, I've written all this
- * to avoid a source dependency on scalacheck.
- */
- class ScalacheckClassLoader extends PartestClassLoader(arrayURLs, this.getClass.getClassLoader) {
- type ScalacheckResult = { def passed: Boolean }
-
- def propCallback(name: String, passed: Int, discarded: Int): Unit = ()
- def testCallback(name: String, result: AnyRef): Unit = ()
-
- val test = singleton("Test$")
- val params = apply[AnyRef]("org.scalacheck.Test$", "defaultParams")()
- val result = apply[Seq[(String, AnyRef)]]("org.scalacheck.Test$", "checkProperties")(test, params, propCallback _, testCallback _)
-
- def allResults() =
- for ((prop, res) <- result) yield {
- ScalacheckTest.this.trace("%s: %s".format(prop, res))
- res.asInstanceOf[ScalacheckResult].passed
- }
-
- def check() = allResults forall (_ == true)
- }
-
- override def run() = {
- trace("scalacheck runs via classloader with: %s".format(arrayURLs mkString ", "))
- isDryRun || (new ScalacheckClassLoader check)
- }
- }
- }
-
- object Script extends DirBasedCategory("script") {
- val testSequence: TestSequence = List(exec, diff)
- override def createTest(location: Path) = new ScriptTest(location)
-
- class ScriptTest(val location: Path) extends TestEntity {
- val category = Script
- val scriptFile = if (location.isDirectory) location / (label + ".scala") else location
- val argsFile = withExtension("args").toFile
- def batFile = scriptFile changeExtension "bat"
- def script = if (Properties.isWin) batFile else scriptFile
-
- override def acknowledges(p: Path) = super.acknowledges(p) || (List(argsFile, batFile) exists (_ isSame p))
- override def execCwd = Some(sourcesDir)
- override def argumentsToExec = script.path :: safeArgs(argsFile)
- }
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/io/ANSIWriter.scala b/src/partest/scala/tools/partest/io/ANSIWriter.scala
deleted file mode 100644
index 0ddcd97a5f..0000000000
--- a/src/partest/scala/tools/partest/io/ANSIWriter.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- * @author Philipp Haller
- */
-
-package scala.tools
-package partest
-package io
-
-import java.io.{ Writer, PrintWriter, OutputStream, OutputStreamWriter }
-
-object ANSIWriter {
- val NONE = 0
- val SOME = 1
- val MANY = 2
-
- def apply(isAnsi: Boolean) = if (isAnsi) MANY else NONE
-}
-import ANSIWriter._
-
-class ANSIWriter(writer: Writer) extends PrintWriter(writer, true) {
- def this(out: OutputStream) = this(new OutputStreamWriter(out))
- def colorful: Int = NONE
-
- protected val manyColors = List(
- Console.BOLD + Console.BLACK,
- Console.BOLD + Console.GREEN,
- Console.BOLD + Console.RED,
- Console.BOLD + Console.YELLOW,
- Console.RESET
- )
- protected val someColors = List(
- Console.BOLD + Console.BLACK,
- Console.RESET,
- Console.BOLD + Console.BLACK,
- Console.BOLD + Console.BLACK,
- Console.RESET
- )
- protected val noColors = List("", "", "", "", "")
-
- lazy val List(_outline, _success, _failure, _warning, _default) = colorful match {
- case NONE => noColors
- case SOME => someColors
- case MANY => manyColors
- case _ => noColors
- }
-
- private def wrprint(msg: String): Unit = synchronized {
- print(msg)
- flush()
- }
-
- def outline(msg: String) = wrprint(_outline + msg + _default)
- def success(msg: String) = wrprint(_success + msg + _default)
- def failure(msg: String) = wrprint(_failure + msg + _default)
- def warning(msg: String) = wrprint(_warning + msg + _default)
- def normal(msg: String) = wrprint(_default + msg)
-}
diff --git a/src/partest/scala/tools/partest/io/JUnitReport.scala b/src/partest/scala/tools/partest/io/JUnitReport.scala
deleted file mode 100644
index 63ae200020..0000000000
--- a/src/partest/scala/tools/partest/io/JUnitReport.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-package io
-
-/** This is disabled for the moment but I can fix it up if anyone
- * is using it.
- */
-class JUnitReport {
- // create JUnit Report xml files if directory was specified
- // def junitReport(dir: Directory) = {
- // dir.mkdir()
- // val report = testReport(set.kind, results, succs, fails)
- // XML.save("%s/%s.xml".format(d.toAbsolute.path, set.kind), report)
- // }
-
- // def oneResult(res: (TestEntity, Int)) =
- // <testcase name={res._1.path}>{
- // res._2 match {
- // case 0 => scala.xml.NodeSeq.Empty
- // case 1 => <failure message="Test failed"/>
- // case 2 => <failure message="Test timed out"/>
- // }
- // }</testcase>
- //
- // def testReport(kind: String, results: Iterable[(TestEntity, Int)], succs: Int, fails: Int) = {
- // <testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
- // <properties/>
- // {
- // results.map(oneResult(_))
- // }
- // </testsuite>
- // }
- //
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/io/Logging.scala b/src/partest/scala/tools/partest/io/Logging.scala
deleted file mode 100644
index 52239ffb2c..0000000000
--- a/src/partest/scala/tools/partest/io/Logging.scala
+++ /dev/null
@@ -1,137 +0,0 @@
-package scala.tools
-package partest
-package io
-
-import java.io.{ StringWriter, PrintWriter, Writer }
-import scala.tools.nsc.io._
-import scala.util.control.ControlThrowable
-
-trait Logging {
- universe: Universe =>
-
- class PartestANSIWriter extends ANSIWriter(Console.out) {
- override def colorful: Int = ANSIWriter(universe.isAnsi)
- private def printIf(cond: Boolean, msg: String) =
- if (cond) { outline("debug: ") ; println(msg) }
-
- val verbose = printIf(isVerbose || isDebug, _: String)
- val debug = printIf(isDebug, _: String)
- }
-
- lazy val NestUI = new PartestANSIWriter()
-
- import NestUI.{ _outline, _success, _failure, _warning, _default }
-
- def markOutline(msg: String) = _outline + msg + _default
- def markSuccess(msg: String) = _success + msg + _default
- def markFailure(msg: String) = _failure + msg + _default
- def markWarning(msg: String) = _warning + msg + _default
- def markNormal(msg: String) = _default + msg
-
- def outline(msg: String) = NestUI outline msg
- def success(msg: String) = NestUI success msg
- def failure(msg: String) = NestUI failure msg
- def warning(msg: String) = NestUI warning msg
- def normal(msg: String) = NestUI normal msg
-
- def verbose(msg: String) = NestUI verbose msg
- def debug(msg: String) = NestUI debug msg
-
- trait EntityLogging {
- self: TestEntity =>
-
- lazy val logWriter = new LogWriter(logFile)
-
- /** Redirect stdout and stderr to logFile, run body, return result.
- */
- def loggingOutAndErr[T](body: => T): T = {
- val log = logFile.printStream(append = true)
-
- try Console.withOut(log) {
- Console.withErr(log) {
- body
- }
- }
- finally log.close()
- }
-
- /** What to print in a failure summary.
- */
- def failureMessage() = if (diffOutput != "") diffOutput else safeSlurp(logFile)
-
- /** For tracing. Outputs a line describing the next action. tracePath
- * is a path wrapper which prints name or full path depending on verbosity.
- */
- def trace(msg: String) = if (isTrace || isDryRun) System.err.println(">> [%s] %s".format(label, msg))
-
- def tracePath(path: Path): String = if (isVerbose) path.path else path.name
- def tracePath(path: String): String = tracePath(Path(path))
-
- /** v == verbose.
- */
- def vtrace(msg: String) = if (isVerbose) trace(msg)
-
- /** Run body, writes result to logFile. Any throwable is
- * caught, stringified, and written to the log.
- */
- def loggingResult(body: => String) =
- try returning(true)(_ => logFile writeAll body)
- catch {
- case x: ControlThrowable => throw x
- case x: InterruptedException => debug(this + " received interrupt, failing.\n") ; false
- case x: Throwable => logException(x)
- }
-
- def throwableToString(x: Throwable): String = {
- val w = new StringWriter
- x.printStackTrace(new PrintWriter(w))
- w.toString
- }
-
- def warnAndLog(str: String) = {
- warning(toStringTrunc(str, 800))
- logWriter append str
- }
-
- def warnAndLogException(msg: String, ex: Throwable) =
- warnAndLog(msg + throwableToString(ex))
-
- def deleteLog(force: Boolean = false) =
- if (universe.isNoCleanup && !force) debug("Not cleaning up " + logFile)
- else logFile.deleteIfExists()
-
- def onException(x: Throwable) { logException(x) }
- def logException(x: Throwable) = {
- val msg = throwableToString(x)
- if (!isTerse)
- normal(msg)
-
- logWriter append msg
- false
- }
- }
-
- /** A writer which doesn't create the file until a write comes in.
- */
- class LazilyCreatedWriter(log: File) extends Writer {
- @volatile private var isCreated = false
- private lazy val underlying = {
- isCreated = true
- log.bufferedWriter()
- }
-
- def flush() = if (isCreated) underlying.flush()
- def close() = if (isCreated) underlying.close()
- def write(chars: Array[Char], off: Int, len: Int) = {
- underlying.write(chars, off, len)
- underlying.flush()
- }
- }
-
- class LogWriter(log: File) extends PrintWriter(new LazilyCreatedWriter(log), true) {
- override def print(s: String) = {
- super.print(s)
- flush()
- }
- }
-} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/nest/AntRunner.scala b/src/partest/scala/tools/partest/nest/AntRunner.scala
new file mode 100644
index 0000000000..cb819720fc
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/AntRunner.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.File
+import scala.tools.nsc.io.{ Directory }
+
+class AntRunner extends DirectRunner {
+
+ val fileManager = new FileManager {
+ var JAVACMD: String = "java"
+ var JAVAC_CMD: String = "javac"
+ var CLASSPATH: String = _
+ var LATEST_LIB: String = _
+ val testRootPath: String = "test"
+ val testRootDir: Directory = Directory(testRootPath)
+ }
+
+ def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String) =
+ runTestsForFiles(kindFiles.toList, kind)
+}
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
new file mode 100644
index 0000000000..22568ad2d0
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -0,0 +1,197 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io }
+import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
+import scala.tools.nsc.util.ClassPath
+import scala.tools.util.PathResolver
+import io.Path
+
+import java.io.{ File, BufferedReader, PrintWriter, FileReader, Writer, FileWriter, StringWriter }
+import File.pathSeparator
+
+class ExtConsoleReporter(override val settings: Settings, reader: BufferedReader, var writer: PrintWriter)
+extends ConsoleReporter(settings, reader, writer) {
+ def this(settings: Settings) = this(settings, Console.in, new PrintWriter(new FileWriter("/dev/null")))
+}
+
+abstract class SimpleCompiler {
+ def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean
+}
+
+class TestSettings(fileMan: FileManager) extends Settings(_ => ()) { }
+
+class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
+ def newGlobal(settings: Settings, reporter: Reporter): Global =
+ new Global(settings, reporter)
+
+ def newGlobal(settings: Settings, logWriter: FileWriter): Global = {
+ val rep = newReporter(settings, logWriter)
+ rep.shortname = true
+ newGlobal(settings, rep)
+ }
+
+ def newSettings(out: Option[String]) = {
+ val settings = new TestSettings(fileManager)
+ settings.usejavacp.value = true
+ settings.deprecation.value = true
+ settings.nowarnings.value = false
+ settings.encoding.value = "ISO-8859-1" // XXX why?
+
+ val classpathElements = settings.classpath.value :: fileManager.LATEST_LIB :: out.toList
+ settings.classpath.value = ClassPath.join(classpathElements: _*)
+ out foreach (settings.outdir.value = _)
+
+ settings
+ }
+
+ def newReporter(sett: Settings, writer: Writer = new StringWriter) =
+ new ExtConsoleReporter(sett, Console.in, new PrintWriter(writer))
+
+ private def updatePluginPath(options: String): String = {
+ val dir = fileManager.testRootDir
+ def absolutize(path: String) = Path(path) match {
+ case x if x.isAbsolute => x.path
+ case x => (fileManager.testRootDir / x).toAbsolute.path
+ }
+
+ val (opt1, opt2) = (options split "\\s").toList partition (_ startsWith "-Xplugin:")
+ val plugins = opt1 map (_ stripPrefix "-Xplugin:") flatMap (_ split pathSeparator) map absolutize
+ val pluginOption = if (opt1.isEmpty) Nil else List("-Xplugin:" + (plugins mkString pathSeparator))
+
+ (opt2 ::: pluginOption) mkString " "
+ }
+
+ def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean = {
+ val testSettings = newSettings(out map (_.getAbsolutePath))
+ val logWriter = new FileWriter(log)
+
+ // check whether there is a ".flags" file
+ val flagsFileName = "%s.flags" format (basename(log.getName) dropRight 4) // 4 is "-run" or similar
+ val argString = (io.File(log).parent / flagsFileName) ifFile (x => updatePluginPath(x.slurp())) getOrElse ""
+ val allOpts = fileManager.SCALAC_OPTS+" "+argString
+ val args = (allOpts split "\\s").toList
+
+ NestUI.verbose("scalac options: "+allOpts)
+
+ val command = new CompilerCommand(args, testSettings)
+ val global = newGlobal(command.settings, logWriter)
+ val testRep: ExtConsoleReporter = global.reporter.asInstanceOf[ExtConsoleReporter]
+
+ val testFileFn: (File, FileManager) => TestFile = kind match {
+ case "pos" => PosTestFile.apply
+ case "neg" => NegTestFile.apply
+ case "run" => RunTestFile.apply
+ case "jvm" => JvmTestFile.apply
+ case "shootout" => ShootoutTestFile.apply
+ case "scalap" => ScalapTestFile.apply
+ case "scalacheck" => ScalaCheckTestFile.apply
+ }
+ val test: TestFile = testFileFn(files.head, fileManager)
+ test.defineSettings(command.settings, out.isEmpty)
+ val toCompile = files map (_.getPath)
+
+ try {
+ NestUI.verbose("compiling "+toCompile)
+ try new global.Run compile toCompile
+ catch {
+ case FatalError(msg) =>
+ testRep.error(null, "fatal error: " + msg)
+ }
+
+ testRep.printSummary
+ testRep.writer.flush
+ testRep.writer.close
+ }
+ catch {
+ case e =>
+ e.printStackTrace()
+ return false
+ }
+ finally logWriter.close()
+
+ !testRep.hasErrors
+ }
+}
+
+// class ReflectiveCompiler(val fileManager: ConsoleFileManager) extends SimpleCompiler {
+// import fileManager.{latestCompFile, latestPartestFile}
+//
+// val sepUrls = Array(latestCompFile.toURI.toURL, latestPartestFile.toURI.toURL)
+// //NestUI.verbose("constructing URLClassLoader from URLs "+latestCompFile+" and "+latestPartestFile)
+//
+// val sepLoader = new java.net.URLClassLoader(sepUrls, null)
+//
+// val sepCompilerClass =
+// sepLoader.loadClass("scala.tools.partest.nest.DirectCompiler")
+// val sepCompiler = sepCompilerClass.newInstance()
+//
+// // needed for reflective invocation
+// val fileClass = Class.forName("java.io.File")
+// val stringClass = Class.forName("java.lang.String")
+// val sepCompileMethod =
+// sepCompilerClass.getMethod("compile", fileClass, stringClass)
+// val sepCompileMethod2 =
+// sepCompilerClass.getMethod("compile", fileClass, stringClass, fileClass)
+//
+// /* This method throws java.lang.reflect.InvocationTargetException
+// * if the compiler crashes.
+// * This exception is handled in the shouldCompile and shouldFailCompile
+// * methods of class CompileManager.
+// */
+// def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean = {
+// val res = sepCompileMethod2.invoke(sepCompiler, out, files, kind, log).asInstanceOf[java.lang.Boolean]
+// res.booleanValue()
+// }
+// }
+
+class CompileManager(val fileManager: FileManager) {
+ var compiler: SimpleCompiler = new /*ReflectiveCompiler*/ DirectCompiler(fileManager)
+
+ var numSeparateCompilers = 1
+ def createSeparateCompiler() = {
+ numSeparateCompilers += 1
+ compiler = new /*ReflectiveCompiler*/ DirectCompiler(fileManager)
+ }
+
+ /* This method returns true iff compilation succeeds.
+ */
+ 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 = {
+ 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 = {
+ 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 = {
+ createSeparateCompiler()
+ !compiler.compile(Some(out), files, kind, log)
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
new file mode 100644
index 0000000000..58d16a3f45
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -0,0 +1,190 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.{ File, FilenameFilter, IOException, StringWriter }
+import java.net.URI
+import scala.util.Properties.{ propOrElse, scalaCmd, scalacCmd }
+import scala.tools.util.PathResolver
+import scala.tools.nsc.{ Settings }
+import scala.tools.nsc.{ io, util }
+import util.{ ClassPath }
+import io.{ Path, Directory }
+import File.pathSeparator
+import ClassPath.{ join }
+import PathResolver.{ Environment, Defaults }
+import RunnerUtils._
+
+
+class ConsoleFileManager extends FileManager {
+ var testBuild: Option[String] = PartestDefaults.testBuild
+ def testBuildFile = testBuild map (testParent / _)
+
+ var testClasses: Option[String] = None
+
+ def this(buildPath: String, rawClasses: Boolean) = {
+ this()
+ if (rawClasses)
+ testClasses = Some(buildPath)
+ else
+ testBuild = Some(buildPath)
+ // re-run because initialization of default
+ // constructor must be updated
+ findLatest()
+ }
+
+ def this(buildPath: String) = {
+ this(buildPath, false)
+ }
+
+ def this(buildPath: String, rawClasses: Boolean, moreOpts: String) = {
+ this(buildPath, rawClasses)
+ SCALAC_OPTS = SCALAC_OPTS+" "+moreOpts
+ }
+
+ lazy val srcDir = PathSettings.srcDir
+ lazy val testRootDir = PathSettings.testRoot
+ lazy val testRootPath = testRootDir.toAbsolute.path
+ def testParent = testRootDir.parent
+
+ var CLASSPATH = PartestDefaults.classPath
+ var JAVACMD = PartestDefaults.javaCmd
+ var JAVAC_CMD = PartestDefaults.javacCmd
+
+
+ NestUI.verbose("CLASSPATH: "+CLASSPATH)
+
+ if (!srcDir.isDirectory) {
+ NestUI.failure("Source directory \"" + srcDir.path + "\" not found")
+ exit(1)
+ }
+
+ CLASSPATH = {
+ val libs = (srcDir / Directory("lib")).files filter (_ hasExtension "jar") map (_.normalize.path)
+
+ // add all jars in libs
+ (CLASSPATH :: libs.toList) mkString pathSeparator
+ }
+
+ def findLatest() {
+ NestUI.verbose("test parent: "+testParent)
+
+ def prefixFileWith(parent: File, relPath: String) = (io.File(parent) / relPath).normalize
+ def prefixFile(relPath: String) = (testParent / relPath).normalize
+
+ if (!testClasses.isEmpty) {
+ testClassesDir = Path(testClasses.get).normalize.toDirectory
+ NestUI.verbose("Running with classes in "+testClassesDir)
+
+ latestFile = testClassesDir.parent / "bin"
+ latestLibFile = testClassesDir / "library"
+ latestCompFile = testClassesDir / "compiler"
+ latestPartestFile = testClassesDir / "partest"
+ latestFjbgFile = testParent / "lib" / "fjbg.jar"
+ }
+ else if (testBuild.isDefined) {
+ val dir = Path(testBuild.get)
+ NestUI.verbose("Running on "+dir)
+ latestFile = dir / "bin"
+ latestLibFile = dir / "lib/scala-library.jar"
+ latestCompFile = dir / "lib/scala-compiler.jar"
+ latestPartestFile = dir / "lib/scala-partest.jar"
+ }
+ else {
+ def setupQuick() {
+ NestUI.verbose("Running build/quick")
+ latestFile = prefixFile("build/quick/bin")
+ latestLibFile = prefixFile("build/quick/classes/library")
+ latestCompFile = prefixFile("build/quick/classes/compiler")
+ latestPartestFile = prefixFile("build/quick/classes/partest")
+ }
+
+ def setupInst() {
+ NestUI.verbose("Running dist (installed)")
+ val p = testParent.getParentFile
+ latestFile = prefixFileWith(p, "bin")
+ latestLibFile = prefixFileWith(p, "lib/scala-library.jar")
+ latestCompFile = prefixFileWith(p, "lib/scala-compiler.jar")
+ latestPartestFile = prefixFileWith(p, "lib/scala-partest.jar")
+ }
+
+ def setupDist() {
+ NestUI.verbose("Running dists/latest")
+ latestFile = prefixFile("dists/latest/bin")
+ latestLibFile = prefixFile("dists/latest/lib/scala-library.jar")
+ latestCompFile = prefixFile("dists/latest/lib/scala-compiler.jar")
+ latestPartestFile = prefixFile("dists/latest/lib/scala-partest.jar")
+ }
+
+ def setupPack() {
+ NestUI.verbose("Running build/pack")
+ latestFile = prefixFile("build/pack/bin")
+ latestLibFile = prefixFile("build/pack/lib/scala-library.jar")
+ latestCompFile = prefixFile("build/pack/lib/scala-compiler.jar")
+ latestPartestFile = prefixFile("build/pack/lib/scala-partest.jar")
+ }
+
+ val dists = testParent / "dists"
+ val build = testParent / "build"
+ // in case of an installed dist, testRootDir is one level deeper
+ val bin = testParent.parent / "bin"
+
+ def mostRecentOf(base: String, names: String*) =
+ names map (x => prefixFile(base + "/" + x).lastModified) reduceLeft (_ max _)
+
+ // detect most recent build
+ val quickTime = mostRecentOf("build/quick/classes", "compiler/compiler.properties", "library/library.properties")
+ val packTime = mostRecentOf("build/pack/lib", "scala-compiler.jar", "scala-library.jar")
+ val distTime = mostRecentOf("dists/latest/lib", "scala-compiler.jar", "scala-library.jar")
+ val instTime = mostRecentOf("lib", "scala-compiler.jar", "scala-library.jar")
+
+ val pairs = Map(
+ (quickTime, () => setupQuick()),
+ (packTime, () => setupPack()),
+ (distTime, () => setupDist()),
+ (instTime, () => setupInst())
+ )
+
+ // run setup based on most recent time
+ pairs(pairs.keys max)()
+
+ latestFjbgFile = prefixFile("lib/fjbg.jar")
+ }
+
+ LATEST_LIB = latestLibFile.getAbsolutePath
+ }
+
+ var LATEST_LIB: String = ""
+
+ var latestFile: File = _
+ var latestLibFile: File = _
+ var latestCompFile: File = _
+ var latestPartestFile: File = _
+ var latestFjbgFile: File = _
+ var testClassesDir: Directory = _
+ // initialize above fields
+ findLatest()
+
+ var testFiles: List[io.Path] = Nil
+
+ def getFiles(kind: String, cond: Path => Boolean): List[File] = {
+ def ignoreDir(p: Path) = List("svn", "obj") exists (p hasExtension _)
+
+ val dir = Directory(srcDir / kind)
+
+ if (dir.isDirectory) NestUI.verbose("look in %s for tests" format dir)
+ else NestUI.failure("Directory '%s' not found" format dir)
+
+ val files =
+ if (testFiles.nonEmpty) testFiles filter (_.parent isSame dir)
+ else dir.list filterNot ignoreDir filter cond toList
+
+ ( if (failed) files filter (x => logFileExists(x, kind)) else files ) map (_.jfile)
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
new file mode 100644
index 0000000000..eae79f23af
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -0,0 +1,209 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.{File, PrintStream, FileOutputStream, BufferedReader,
+ InputStreamReader, StringWriter, PrintWriter}
+import utils.Properties._
+import RunnerUtils._
+import scala.tools.nsc.Properties.{ versionMsg, setProp }
+import scala.tools.nsc.util.CommandLineParser
+import scala.tools.nsc.io
+import scala.tools.nsc.interpreter.returning
+import io.{ Path, Process }
+
+class ConsoleRunner extends DirectRunner {
+ import PathSettings.{ srcDir, testRoot }
+
+ case class TestSet(kind: String, filter: Path => Boolean, msg: String)
+
+ val testSets = {
+ val pathFilter: Path => Boolean = _ hasExtension "scala"
+
+ List(
+ TestSet("pos", pathFilter, "Testing compiler (on files whose compilation should succeed)"),
+ TestSet("neg", pathFilter, "Testing compiler (on files whose compilation should fail)"),
+ TestSet("run", pathFilter, "Testing JVM backend"),
+ TestSet("jvm", pathFilter, "Testing JVM backend"),
+ TestSet("res", x => x.isFile && (x hasExtension "res"), "Testing resident compiler"),
+ TestSet("buildmanager", _.isDirectory, "Testing Build Manager"),
+ TestSet("shootout", pathFilter, "Testing shootout tests"),
+ TestSet("script", pathFilter, "Testing script tests"),
+ TestSet("scalacheck", pathFilter, "Testing ScalaCheck tests"),
+ TestSet("scalap", _.isDirectory, "Run scalap decompiler tests")
+ )
+ }
+
+ var fileManager: ConsoleFileManager = _
+
+ private var testFiles: List[File] = List()
+ private val errors = PartestDefaults.errorCount
+ private val testSetKinds = testSets map (_.kind)
+ private val testSetArgs = testSets map ("--" + _.kind)
+ private val testSetArgMap = testSetArgs zip testSets toMap
+
+ def denotesTestSet(arg: String) = testSetArgs contains arg
+ def denotesTestFile(arg: String) = (arg endsWith ".scala") || (arg endsWith ".res")
+ def denotesTestDir(arg: String) = Path(arg).isDirectory
+ def denotesTestPath(arg: String) = denotesTestDir(arg) || denotesTestFile(arg)
+
+ private def printVersion { NestUI outline (versionMsg + "\n") }
+
+ private val unaryArgs = List(
+ "--pack", "--all", "--verbose", "--show-diff", "--show-log",
+ "--failed", "--version", "--ansi", "--debug"
+ ) ::: testSetArgs
+
+ private val binaryArgs = List(
+ "--grep", "--srcpath", "--buildpath", "--classpath"
+ )
+
+ def main(argstr: String) {
+ val parsed = CommandLineParser(argstr) withUnaryArgs unaryArgs withBinaryArgs binaryArgs
+ val args = parsed.residualArgs
+
+ /** Early return on no args, version, or invalid args */
+ if (argstr == "") return NestUI.usage()
+ if (parsed isSet "--version") return printVersion
+ if (args exists (x => !denotesTestPath(x))) {
+ val invalid = (args filterNot denotesTestPath).head
+ NestUI.failure("Invalid argument '%s'\n" format invalid)
+ return NestUI.usage()
+ }
+
+ parsed get "--srcpath" foreach (x => setProp("partest.srcdir", x))
+
+ fileManager =
+ if (parsed isSet "--buildpath") new ConsoleFileManager(parsed("--buildpath"))
+ else if (parsed isSet "--classpath") new ConsoleFileManager(parsed("--classpath"), true)
+ else if (parsed isSet "--pack") new ConsoleFileManager("build/pack")
+ else new ConsoleFileManager // auto detection, see ConsoleFileManager.findLatest
+
+ def argNarrowsTests(x: String) = denotesTestSet(x) || denotesTestFile(x) || denotesTestDir(x)
+
+ NestUI._verbose = parsed isSet "--verbose"
+ fileManager.showDiff = parsed isSet "--show-diff"
+ fileManager.showLog = parsed isSet "--show-log"
+ fileManager.failed = parsed isSet "--failed"
+
+ if (parsed isSet "--ansi") NestUI initialize NestUI.MANY
+ if (parsed isSet "--timeout") fileManager.timeout = parsed("--timeout")
+ if (parsed isSet "--debug") setProp("partest.debug", "true")
+
+ def addTestFile(file: File) = {
+ if (!file.exists)
+ NestUI.failure("Test file '%s' not found, skipping.\n" format file)
+ else {
+ NestUI.verbose("adding test file " + file)
+ testFiles +:= file
+ }
+ }
+
+ // If --grep is given we suck in every file it matches.
+ parsed get "--grep" foreach { expr =>
+ val allFiles = srcDir.deepList() filter (_ hasExtension "scala") map (_.toFile) toList
+ val files = allFiles filter (_.slurp() contains expr)
+
+ if (files.isEmpty) NestUI.failure("--grep string '%s' matched no files." format expr)
+ else NestUI.verbose("--grep string '%s' matched %d file(s)".format(expr, files.size))
+
+ files foreach (x => addTestFile(x.jfile))
+ }
+ args foreach (x => addTestFile(new File(x)))
+
+ // If no file arguments were given, we assume --all
+ val enabledTestSets: List[TestSet] = {
+ val enabledArgs = testSetArgs filter parsed.isSet
+
+ if (args.isEmpty && !(parsed isSet "--grep") && (enabledArgs.isEmpty || (parsed isSet "--all"))) testSets
+ else enabledArgs map testSetArgMap
+ }
+
+ val dir =
+ if (fileManager.testClasses.isDefined) fileManager.testClassesDir
+ else fileManager.testBuildFile getOrElse {
+ fileManager.latestCompFile.getParentFile.getParentFile.getCanonicalFile
+ }
+
+ val vmBin = javaHome + File.separator + "bin"
+ val vmName = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
+ val vmOpts = fileManager.JAVA_OPTS
+
+ NestUI.verbose("enabled test sets: " + (enabledTestSets map (_.kind) mkString " "))
+
+ List(
+ "Scala compiler classes in: " + dir,
+ "Scala version is: " + versionMsg,
+ "Scalac options are: " + fileManager.SCALAC_OPTS,
+ "Java binaries in: " + vmBin,
+ "Java runtime is: " + vmName,
+ "Java options are: " + vmOpts,
+ "Source directory is: " + srcDir,
+ ""
+ ) foreach (x => NestUI outline (x + "\n"))
+
+ val start = System.currentTimeMillis
+ val (successes, failures) = testCheckAll(enabledTestSets)
+ val end = System.currentTimeMillis
+
+ val total = successes + failures
+
+ val elapsedSecs = (end - start)/1000
+ val elapsedMins = elapsedSecs/60
+ val elapsedHrs = elapsedMins/60
+ val dispMins = elapsedMins - elapsedHrs * 60
+ val dispSecs = elapsedSecs - elapsedMins * 60
+
+ val dispElapsed = {
+ def form(num: Long) = if (num < 10) "0"+num else ""+num
+ form(elapsedHrs)+":"+form(dispMins)+":"+form(dispSecs)
+ }
+
+ println
+ if (failures == 0)
+ NestUI.success("All of "+total+" tests were successful (elapsed time: "+dispElapsed+")\n")
+ else
+ NestUI.failure(failures+" of "+total+" tests failed (elapsed time: "+dispElapsed+")\n")
+
+ System exit ( if (failures == errors) 0 else 1 )
+ }
+
+ def runTests(testSet: TestSet): (Int, Int) = {
+ val TestSet(kind, filter, msg) = testSet
+
+ fileManager.getFiles(kind, filter) match {
+ case Nil => NestUI.verbose("test dir empty\n") ; (0, 0)
+ case files =>
+ NestUI.verbose("test files: "+files)
+ NestUI.outline("\n"+msg+"\n")
+ resultsToStatistics(runTestsForFiles(files, kind))
+ }
+ }
+
+ /**
+ * @return (success count, failure count)
+ */
+ def testCheckAll(enabledSets: List[TestSet]): (Int, Int) = {
+ def kindOf(f: File) = (srcDir relativize Path(f).normalize).segments.head
+
+ val (valid, invalid) = testFiles partition (x => testSetKinds contains kindOf(x))
+ invalid foreach (x => NestUI.failure("Invalid test file '%s', skipping.\n" format x))
+
+ val runTestsFileLists =
+ for ((kind, files) <- valid groupBy kindOf toList) yield {
+ NestUI.outline("\nTesting individual files\n")
+ resultsToStatistics(runTestsForFiles(files, kind))
+ }
+
+ NestUI.verbose("Run sets: "+enabledSets)
+ val results = runTestsFileLists ::: (enabledSets map runTests)
+
+ (results map (_._1) sum, results map (_._2) sum)
+ }
+}
diff --git a/src/partest/scala/tools/partest/io/Diff.java b/src/partest/scala/tools/partest/nest/Diff.java
index c7a3d42f30..abd09d0293 100644
--- a/src/partest/scala/tools/partest/io/Diff.java
+++ b/src/partest/scala/tools/partest/nest/Diff.java
@@ -1,6 +1,6 @@
// $Id$
-package scala.tools.partest.io;
+package scala.tools.partest.nest;
import java.util.Hashtable;
diff --git a/src/partest/scala/tools/partest/io/DiffPrint.java b/src/partest/scala/tools/partest/nest/DiffPrint.java
index 2b2ad93ec7..494bc06e4a 100644
--- a/src/partest/scala/tools/partest/io/DiffPrint.java
+++ b/src/partest/scala/tools/partest/nest/DiffPrint.java
@@ -1,6 +1,6 @@
// $Id$
-package scala.tools.partest.io;
+package scala.tools.partest.nest;
import java.io.*;
import java.util.Vector;
diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala
new file mode 100644
index 0000000000..f774320f4e
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -0,0 +1,78 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.{File, PrintStream, FileOutputStream, BufferedReader,
+ InputStreamReader, StringWriter, PrintWriter}
+import java.util.StringTokenizer
+import scala.util.Properties.{ setProp }
+import scala.tools.nsc.io.Directory
+
+import scala.actors.Actor._
+import scala.actors.TIMEOUT
+
+trait DirectRunner {
+
+ def fileManager: FileManager
+
+ import PartestDefaults.numActors
+
+ if (isPartestDebug)
+ scala.actors.Debug.level = 3
+
+ if (PartestDefaults.poolSize.isEmpty) {
+ scala.actors.Debug.info("actors.corePoolSize not defined")
+ setProp("actors.corePoolSize", "16")
+ }
+
+ def runTestsForFiles(kindFiles: List[File], kind: String): scala.collection.immutable.Map[String, Int] = {
+ val len = kindFiles.length
+ val (testsEach, lastFrag) = (len/numActors, len%numActors)
+ val last = numActors-1
+ val workers = for (i <- List.range(0, numActors)) yield {
+ val toTest = kindFiles.slice(i*testsEach, (i+1)*testsEach)
+ val worker = new Worker(fileManager)
+ worker.start()
+ if (i == last)
+ worker ! RunTests(kind, (kindFiles splitAt (last*testsEach))._2)
+ else
+ worker ! RunTests(kind, toTest)
+ worker
+ }
+
+ var logsToDelete: List[File] = List()
+ var outdirsToDelete: List[File] = List()
+ var results = new scala.collection.immutable.HashMap[String, Int]
+ workers foreach { w =>
+ receiveWithin(3600 * 1000) {
+ case Results(res, logs, outdirs) =>
+ logsToDelete :::= logs filter (_.toDelete)
+ outdirsToDelete :::= outdirs
+ results ++= res
+ case TIMEOUT =>
+ // add at least one failure
+ NestUI.verbose("worker timed out; adding failed test")
+ results += ("worker timed out; adding failed test" -> 2)
+ }
+ }
+
+ if (isPartestDebug)
+ fileManager.showTestTimings()
+
+ if (!isPartestDebug) {
+ for (x <- logsToDelete ::: outdirsToDelete) {
+ NestUI.verbose("deleting "+x)
+ Directory(x).deleteRecursively()
+ }
+ }
+
+ results
+ }
+
+}
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
new file mode 100644
index 0000000000..bdbb34b3c4
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -0,0 +1,110 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.{File, FilenameFilter, IOException, StringWriter,
+ FileInputStream, FileOutputStream, BufferedReader,
+ FileReader, PrintWriter, FileWriter}
+import java.net.URI
+import scala.tools.nsc.io.{ Path, Directory }
+import scala.collection.mutable.HashMap
+
+trait FileManager {
+ /**
+ * Compares two files using a Java implementation of the GNU diff
+ * available at http://www.bmsi.com/java/#diff.
+ *
+ * @param f1 the first file to be compared
+ * @param f2 the second file to be compared
+ * @return the text difference between the compared files
+ */
+ def compareFiles(f1: File, f2: File): String = {
+ val diffWriter = new StringWriter
+ val args = Array(f1.getCanonicalPath(), f2.getCanonicalPath())
+
+ DiffPrint.doDiff(args, diffWriter)
+ val res = diffWriter.toString
+ if (res startsWith "No") "" else res
+ }
+
+ def testRootDir: Directory
+ def testRootPath: String
+
+ var JAVACMD: String
+ var JAVAC_CMD: String
+
+ var CLASSPATH: String
+ var LATEST_LIB: String
+
+ var showDiff = false
+ var showLog = false
+ var failed = false
+
+ var SCALAC_OPTS = PartestDefaults.scalacOpts
+ var JAVA_OPTS = PartestDefaults.javaOpts
+ var timeout = PartestDefaults.timeout
+
+ /** Only when --debug is given. */
+ lazy val testTimings = new HashMap[String, Long]
+ def recordTestTiming(name: String, milliseconds: Long) =
+ synchronized { testTimings(name) = milliseconds }
+ def showTestTimings() {
+ testTimings.toList sortBy (-_._2) foreach { case (k, v) => println("%s: %s".format(k, v)) }
+ }
+
+ def getLogFile(dir: File, fileBase: String, kind: String): LogFile =
+ new LogFile(dir, fileBase + "-" + kind + ".log")
+
+ def getLogFile(file: File, kind: String): LogFile = {
+ val dir = file.getParentFile
+ val fileBase = basename(file.getName)
+ getLogFile(dir, fileBase, kind)
+ }
+
+ def logFileExists(file: File, kind: String) =
+ getLogFile(file, kind).canRead
+
+ def overwriteFileWith(dest: File, file: File) =
+ dest.isFile && copyFile(file, dest)
+
+
+ def copyFile(from: File, dest: File): Boolean = {
+ def copyFile0(from: File, to: File): Boolean =
+ try {
+ val appender = StreamAppender(from, to)
+ appender.run()
+ appender.closeAll()
+ true
+ } catch {
+ case _: IOException => false
+ }
+
+ if (from.isDirectory) {
+ assert(dest.isDirectory, "cannot copy directory to file")
+ val subDir:Directory = Path(dest) / Directory(from.getName)
+ subDir.createDirectory()
+ from.listFiles.toList.forall(copyFile(_, subDir))
+ } else
+ copyFile0(from, if (dest.isDirectory) new File(dest, from.getName) else dest)
+ }
+
+ def mapFile(file: File, suffix: String, dir: File, replace: String => String) {
+ val tmpFile = File.createTempFile("tmp", suffix, dir) // prefix required by API
+
+ val appender = StreamAppender(file, tmpFile)
+ appender.runAndMap(replace)
+ appender.closeAll()
+
+ val appender2 = StreamAppender(tmpFile, file)
+ appender2.run()
+ appender2.closeAll()
+
+ tmpFile.delete()
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/NestRunner.scala b/src/partest/scala/tools/partest/nest/NestRunner.scala
new file mode 100644
index 0000000000..158521875e
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/NestRunner.scala
@@ -0,0 +1,16 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+object NestRunner {
+ def main(args: Array[String]) {
+ val argstr = args.mkString(" ")
+ (new ReflectiveRunner).main(argstr)
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala
new file mode 100644
index 0000000000..efff4e8375
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/NestUI.scala
@@ -0,0 +1,118 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.PrintWriter
+
+object NestUI {
+
+ val NONE = 0
+ val SOME = 1
+ val MANY = 2
+
+ private var _outline = ""
+ private var _success = ""
+ private var _failure = ""
+ private var _warning = ""
+ private var _default = ""
+
+ def initialize(number: Int) = number match {
+ case MANY =>
+ _outline = Console.BOLD + Console.BLACK
+ _success = Console.BOLD + Console.GREEN
+ _failure = Console.BOLD + Console.RED
+ _warning = Console.BOLD + Console.YELLOW
+ _default = Console.RESET
+ case SOME =>
+ _outline = Console.BOLD + Console.BLACK
+ _success = Console.RESET
+ _failure = Console.BOLD + Console.BLACK
+ _warning = Console.BOLD + Console.BLACK
+ _default = Console.RESET
+ case _ =>
+ }
+
+ def outline(msg: String) = print(_outline + msg + _default)
+ def outline(msg: String, wr: PrintWriter) = synchronized {
+ wr.print(_outline + msg + _default)
+ }
+
+ def success(msg: String) = print(_success + msg + _default)
+ def success(msg: String, wr: PrintWriter) = synchronized {
+ wr.print(_success + msg + _default)
+ }
+
+ def failure(msg: String) = print(_failure + msg + _default)
+ def failure(msg: String, wr: PrintWriter) = synchronized {
+ wr.print(_failure + msg + _default)
+ }
+
+ def warning(msg: String) = print(_warning + msg + _default)
+ def warning(msg: String, wr: PrintWriter) = synchronized {
+ wr.print(_warning + msg + _default)
+ }
+
+ def normal(msg: String) = print(_default + msg)
+ def normal(msg: String, wr: PrintWriter) = synchronized {
+ wr.print(_default + msg)
+ }
+
+ def usage() {
+ println("Usage: NestRunner [<options>] [<testfile> ..] [<resfile>]")
+ println(" <testfile>: list of files ending in '.scala'")
+ println(" <resfile>: a file not ending in '.scala'")
+ println(" <options>:")
+ println
+ println(" Test categories:")
+ println(" --all run all tests")
+ println(" --pos run compilation tests (success)")
+ println(" --neg run compilation tests (failure)")
+ println(" --run run interpreter and backend tests")
+ println(" --jvm run JVM backend tests")
+ println(" --res run resident compiler tests")
+ println(" --buildmanager run Build Manager tests")
+ println(" --scalacheck run ScalaCheck tests")
+ println(" --script run script runner tests")
+ println(" --shootout run shootout tests")
+ println(" --grep <expr> run all tests whose source file contains <expr>")
+ println
+ println(" Other options:")
+ println(" --pack pick compiler/library in build/pack, and run all tests")
+ println(" --show-log show log")
+ println(" --show-diff show diff between log and check file")
+ println(" --failed run only those tests that failed during the last run")
+ println(" --verbose show progress information")
+ println(" --buildpath set (relative) path to build jars")
+ println(" ex.: --buildpath build/pack")
+ println(" --classpath set (absolute) path to build classes")
+ println(" --srcpath set (relative) path to test source files")
+ println(" ex.: --srcpath pending")
+ println(" --debug enable debugging output")
+ println
+ println(utils.Properties.versionString)
+ println("maintained by Philipp Haller (EPFL)")
+ exit(1)
+ }
+
+ var _verbose = false
+ var _debug = false
+
+ def verbose(msg: String) {
+ if (_verbose) {
+ outline("debug: ")
+ println(msg)
+ }
+ }
+ def debug(msg: String) {
+ if (isPartestDebug) {
+ outline("debug: ")
+ println(msg)
+ }
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/PathSettings.scala b/src/partest/scala/tools/partest/nest/PathSettings.scala
new file mode 100644
index 0000000000..41bba5782e
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/PathSettings.scala
@@ -0,0 +1,41 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ */
+
+package scala.tools.partest
+package nest
+
+import scala.tools.nsc.Properties.{ setProp, propOrEmpty, propOrNone, propOrElse }
+import scala.tools.nsc.util.ClassPath
+import scala.tools.nsc.io
+import io.{ Path, File, Directory }
+import RunnerUtils._
+import java.net.URLClassLoader
+
+object PathSettings {
+ import PartestDefaults.{ testRootDir, srcDirName }
+
+ private def cwd = Directory.Current getOrElse error("user.dir property not set")
+ private def isPartestDir(d: Directory) = (d.name == "test") && (d / srcDirName isDirectory)
+
+ // Directory <root>/test
+ lazy val testRoot: Directory = testRootDir getOrElse {
+ val candidates: List[Directory] = (cwd :: cwd.parents) flatMap (d => List(d, Directory(d / "test")))
+
+ candidates find isPartestDir getOrElse error("Directory 'test' not found.")
+ }
+
+ // Directory <root>/test/files
+ lazy val srcDir = Directory(testRoot / srcDirName normalize)
+
+ // Directory <root>/test/files/lib
+ lazy val srcLibDir = Directory(srcDir / "lib")
+
+ lazy val scalaCheck = srcLibDir.files find (_.name startsWith "scalacheck") getOrElse {
+ error("No scalacheck jar found in '%s'" format srcLibDir)
+ }
+}
+
+class PathSettings() {
+ // def classpathAsURLs: List[URL]
+}
diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
new file mode 100644
index 0000000000..b3f199a3d6
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala
@@ -0,0 +1,88 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import scala.tools.nsc.Properties.{ setProp, propOrEmpty }
+import scala.tools.nsc.util.ClassPath
+import scala.tools.nsc.io
+import io.Path
+import RunnerUtils._
+import java.net.URLClassLoader
+
+/* This class is used to load an instance of DirectRunner using
+ * a custom class loader.
+ * The purpose is to "auto-detect" a good classpath for the
+ * rest of the classes (Worker, CompileManager etc.), so that
+ * the main NestRunner can be started merely by putting its
+ * class on the classpath (ideally).
+ */
+class ReflectiveRunner {
+ // TODO: we might also use fileManager.CLASSPATH
+ // to use the same classes as used by `scala` that
+ // was used to start the runner.
+ val sepRunnerClassName = "scala.tools.partest.nest.ConsoleRunner"
+
+ def main(args: String) {
+ val argList = (args.split("\\s")).toList
+
+ if (isPartestDebug)
+ showAllJVMInfo
+
+ // find out which build to test
+ val buildPath = searchPath("--buildpath", argList)
+ val classPath = searchPath("--classpath", argList)
+ val fileManager =
+ if (!buildPath.isEmpty)
+ new ConsoleFileManager(buildPath.get)
+ else if (!classPath.isEmpty)
+ new ConsoleFileManager(classPath.get, true)
+ else if (argList contains "--pack")
+ new ConsoleFileManager("build/pack")
+ else // auto detection
+ new ConsoleFileManager
+
+ import fileManager.
+ { latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile }
+ val files =
+ Array(latestCompFile, latestLibFile, latestPartestFile, latestFjbgFile) map (x => io.File(x))
+
+ val sepUrls = files map (_.toURL)
+ val sepLoader = new URLClassLoader(sepUrls, null)
+
+ if (isPartestDebug)
+ println("Loading classes from:\n" + sepUrls.mkString("\n"))
+
+ val paths = classPath match {
+ case Some(cp) => Nil
+ case _ => files.toList map (_.path)
+ }
+ val newClasspath = ClassPath.join(paths: _*)
+
+ setProp("java.class.path", newClasspath)
+ setProp("scala.home", "")
+
+ if (isPartestDebug)
+ for (prop <- List("java.class.path", "sun.boot.class.path", "java.ext.dirs"))
+ println(prop + ": " + propOrEmpty(prop))
+
+ try {
+ val sepRunnerClass = sepLoader loadClass sepRunnerClassName
+ val sepRunner = sepRunnerClass.newInstance()
+ val sepMainMethod = sepRunnerClass.getMethod("main", Array(classOf[String]): _*)
+ val cargs: Array[AnyRef] = Array(args)
+ sepMainMethod.invoke(sepRunner, cargs: _*)
+ }
+ catch {
+ case cnfe: ClassNotFoundException =>
+ cnfe.printStackTrace()
+ NestUI.failure(sepRunnerClassName +" could not be loaded from:\n")
+ sepUrls foreach (x => NestUI.failure(x + "\n"))
+ }
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/RunnerUtils.scala b/src/partest/scala/tools/partest/nest/RunnerUtils.scala
new file mode 100644
index 0000000000..24445bb545
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/RunnerUtils.scala
@@ -0,0 +1,29 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+object RunnerUtils {
+ def splitArgs(str: String) = str split "\\s" filterNot (_ == "") toList
+
+ def searchPath(option: String, as: List[String]): Option[String] = as match {
+ case `option` :: r :: _ => Some(r)
+ case _ :: rest => searchPath(option, rest)
+ case Nil => None
+ }
+
+ def searchAndRemovePath(option: String, as: List[String]) = (as indexOf option) match {
+ case -1 => (None, as)
+ case idx => (Some(as(idx + 1)), (as take idx) ::: (as drop (idx + 2)))
+ }
+
+ def searchAndRemoveOption(option: String, as: List[String]) = (as indexOf option) match {
+ case -1 => (false, as)
+ case idx => (true, (as take idx) ::: (as drop (idx + 1)))
+ }
+}
diff --git a/src/partest/scala/tools/partest/nest/StreamAppender.scala b/src/partest/scala/tools/partest/nest/StreamAppender.scala
new file mode 100644
index 0000000000..8cebcf1685
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/StreamAppender.scala
@@ -0,0 +1,94 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io._
+
+object StreamAppender {
+ def wrapIn(in: InputStream): BufferedReader = new BufferedReader(new InputStreamReader(in))
+ def wrapIn(reader: Reader): BufferedReader = new BufferedReader(reader)
+ def wrapIn(str: String): BufferedReader = new BufferedReader(new StringReader(str))
+
+ def wrapOut(out: OutputStream): PrintWriter = new PrintWriter(new OutputStreamWriter(out), true)
+ def wrapOut(writer: Writer): PrintWriter = new PrintWriter(writer, true)
+ def wrapOut(): PrintWriter = wrapOut(new StringWriter)
+
+ def apply(reader: BufferedReader, writer: Writer): StreamAppender =
+ new StreamAppender(reader, wrapOut(writer))
+
+ def apply(reader: Reader, writer: Writer): StreamAppender =
+ apply(wrapIn(reader), writer)
+
+ def apply(in: InputStream, writer: Writer): StreamAppender =
+ apply(wrapIn(in), writer)
+
+ def apply(str: String, writer: Writer): StreamAppender =
+ apply(wrapIn(str), writer)
+
+ def apply(in: File, out: File): StreamAppender =
+ apply(new FileReader(in), new FileWriter(out))
+
+ def appendToString(in1: InputStream, in2: InputStream): String = {
+ val swriter1 = new StringWriter
+ val swriter2 = new StringWriter
+ val app1 = StreamAppender(wrapIn(in1), swriter1)
+ val app2 = StreamAppender(wrapIn(in2), swriter2)
+
+ val async = new Thread(app2)
+ async.start()
+ app1.run()
+ async.join()
+ swriter1.toString + swriter2.toString
+ }
+/*
+ private def inParallel(t1: Runnable, t2: Runnable, t3: Runnable) {
+ val thr1 = new Thread(t1)
+ val thr2 = new Thread(t2)
+ thr1.start()
+ thr2.start()
+ t3.run()
+ thr1.join()
+ thr2.join()
+ }
+*/
+ private def inParallel(t1: Runnable, t2: Runnable) {
+ val thr = new Thread(t2)
+ thr.start()
+ t1.run()
+ thr.join()
+ }
+
+ def concat(in: InputStream, err: InputStream, out: OutputStream) = new Runnable {
+ override def run() {
+ val outWriter = wrapOut(out)
+ val inApp = StreamAppender(in, outWriter)
+
+ val errStringWriter = new StringWriter
+ val errApp = StreamAppender(wrapIn(err), errStringWriter)
+
+ inParallel(inApp, errApp)
+
+ // append error string to out
+ StreamAppender(errStringWriter.toString, outWriter).run()
+ }
+ }
+}
+
+class StreamAppender(reader: BufferedReader, writer: PrintWriter) extends Runnable {
+ override def run() = runAndMap(identity)
+ private def lines() = Iterator continually reader.readLine() takeWhile (_ != null)
+ def closeAll() = {
+ reader.close()
+ writer.close()
+ }
+
+ def runAndMap(f: String => String) =
+ try lines() map f foreach (writer println _)
+ catch { case e: IOException => e.printStackTrace() }
+}
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
new file mode 100644
index 0000000000..741556fdd5
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/TestFile.scala
@@ -0,0 +1,49 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io.{ File => JFile }
+import scala.tools.nsc.Settings
+import scala.tools.nsc.io._
+
+abstract class TestFile(kind: String) {
+ def file: JFile
+ def fileManager: FileManager
+
+ val dir = file.toAbsolute.parent
+ val fileBase = file.stripExtension
+ lazy val objectDir = dir / "%s-%s.obj".format(fileBase, kind) createDirectory true
+ val flags: Option[String] = dir / "%s.flags".format(fileBase) ifFile { _.slurp().trim }
+
+ def setOutDirTo = objectDir
+
+ def defineSettings(settings: Settings, setOutDir: Boolean) = {
+ settings.classpath append dir.path
+ if (setOutDir)
+ settings.outdir.value = setOutDirTo.path
+
+ flags foreach (settings processArgumentString _)
+ settings.classpath append fileManager.CLASSPATH
+ }
+
+ override def toString(): String = "%s %s".format(kind, file)
+}
+
+case class PosTestFile(file: JFile, fileManager: FileManager) extends TestFile("pos")
+case class NegTestFile(file: JFile, fileManager: FileManager) extends TestFile("neg")
+case class RunTestFile(file: JFile, fileManager: FileManager) extends TestFile("run")
+case class BuildManagerTestFile(file: JFile, fileManager: FileManager) extends TestFile("bm")
+case class ScalaCheckTestFile(file: JFile, fileManager: FileManager) extends TestFile("scalacheck")
+case class JvmTestFile(file: JFile, fileManager: FileManager) extends TestFile("jvm")
+case class ShootoutTestFile(file: JFile, fileManager: FileManager) extends TestFile("shootout") {
+ override def setOutDirTo = file.parent
+}
+case class ScalapTestFile(file: JFile, fileManager: FileManager) extends TestFile("scalap") {
+ override def setOutDirTo = file.parent
+}
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
new file mode 100644
index 0000000000..2f81dfd0f7
--- /dev/null
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -0,0 +1,1071 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2010 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+// $Id$
+
+package scala.tools.partest
+package nest
+
+import java.io._
+import java.net.{ URLClassLoader, URL }
+import java.util.{ Timer, TimerTask }
+
+import scala.util.Properties.{ isWin }
+import scala.tools.nsc.{ ObjectRunner, Settings, CompilerCommand, Global }
+import scala.tools.nsc.io.{ AbstractFile, PlainFile, Path, Directory, File => SFile }
+import scala.tools.nsc.reporters.ConsoleReporter
+import scala.tools.nsc.util.{ ClassPath, FakePos }
+import ClassPath.{ join, split }
+
+import scala.actors.{ Actor, Exit, TIMEOUT }
+import scala.actors.Actor._
+import scala.tools.scalap.scalax.rules.scalasig.{ByteCode, ClassFileParser, ScalaSigAttributeParsers}
+
+import scala.collection.immutable.{ HashMap, Map => ImmMap }
+import scala.collection.Map
+
+import scala.tools.nsc.interactive.{BuildManager, RefinedBuildManager}
+
+case class RunTests(kind: String, files: List[File])
+case class Results(results: ImmMap[String, Int], logs: List[LogFile], outdirs: List[File])
+
+case class LogContext(file: LogFile, writers: Option[(StringWriter, PrintWriter)])
+
+abstract class TestResult {
+ def file: File
+}
+case class Result(override val file: File, context: LogContext) extends TestResult
+case class Timeout(override val file: File) extends TestResult
+
+class LogFile(parent: File, child: String) extends File(parent, child) {
+ var toDelete = false
+}
+
+class Worker(val fileManager: FileManager) extends Actor {
+ import fileManager._
+
+ var reporter: ConsoleReporter = _
+ val timer = new Timer
+
+ def error(msg: String): Unit = reporter.error(
+ FakePos("scalac"),
+ msg + "\n scalac -help gives more information"
+ )
+
+ def act() {
+ react {
+ case RunTests(kind, files) =>
+ // NestUI.verbose("received "+files.length+" to test")
+ val master = sender
+ runTests(kind, files) { results =>
+ master ! Results(results, createdLogFiles, createdOutputDirs)
+ }
+ }
+ }
+
+ def printInfoStart(file: File, printer: PrintWriter) {
+ NestUI.outline("testing: ", printer)
+ val filesdir = file.getAbsoluteFile.getParentFile.getParentFile
+ val testdir = filesdir.getParentFile
+ val totalWidth = 56
+ val name = {
+ // 1. try with [...]/files/run/test.scala
+ val testPathLen = testdir.getAbsolutePath.length
+ val name = file.getAbsolutePath.substring(testPathLen)
+ if (name.length <= totalWidth)
+ name
+ // 2. try with [...]/run/test.scala
+ else {
+ val filesPathLen = filesdir.getAbsolutePath.length
+ file.getAbsolutePath.substring(filesPathLen)
+ }
+ }
+ NestUI.normal("[...]%s%s".format(name, " " * (totalWidth - name.length)), printer)
+ }
+
+ def printInfoEnd(success: Boolean, printer: PrintWriter) {
+ NestUI.normal("[", printer)
+ if (success) NestUI.success(" OK ", printer)
+ else NestUI.failure("FAILED", printer)
+ 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] = Nil
+ var createdOutputDirs: List[File] = Nil
+
+ def createLogFile(file: File, kind: String): LogFile = {
+ val logFile = fileManager.getLogFile(file, kind)
+ createdLogFiles ::= logFile
+ logFile
+ }
+
+ def createOutputDir(dir: File, fileBase: String, kind: String): File = {
+ val outDir = Path(dir) / Directory("%s-%s.obj".format(fileBase, kind))
+ outDir.createDirectory()
+ createdOutputDirs ::= outDir.jfile
+ outDir.jfile
+ }
+
+ /* Note: not yet used/tested. */
+ // def execTestObjectRunner(file: File, outDir: File, logFile: File) {
+ // val consFM = new ConsoleFileManager
+ //
+ // val classpath: List[URL] = {
+ // import consFM.{ latestCompFile, latestLibFile, latestPartestFile }
+ // val units = (
+ // List(outDir, latestCompFile, latestLibFile, latestPartestFile) :::
+ // ((CLASSPATH split File.pathSeparatorChar).toList map (x => new File(x)))
+ // )
+ // units map (_.toURI.toURL)
+ // }
+ //
+ // NestUI.verbose("ObjectRunner classpath: "+classpath)
+ //
+ // try {
+ // // configure input/output files
+ // val logOut = new FileOutputStream(logFile)
+ // val logWriter = new PrintStream(logOut)
+ //
+ // // grab global lock
+ // fileManager.synchronized {
+ // withOutputRedirected(logWriter) {
+ // System.setProperty("java.library.path", logFile.getParentFile.getCanonicalFile.getAbsolutePath)
+ // System.setProperty("partest.output", outDir.getCanonicalFile.getAbsolutePath)
+ // System.setProperty("partest.lib", LATEST_LIB)
+ // System.setProperty("partest.cwd", outDir.getParent)
+ // ObjectRunner.run(classpath, "Test", List("jvm"))
+ // }
+ // }
+ //
+ // /*val out = new FileOutputStream(logFile, true)
+ // Console.withOut(new PrintStream(out)) {
+ // ObjectRunner.run(classpath, "Test", List("jvm"))
+ // }
+ // out.flush
+ // out.close*/
+ // } catch {
+ // case e: Exception =>
+ // NestUI.verbose(e+" ("+file.getPath+")")
+ // e.printStackTrace()
+ // }
+ // }
+
+ def javac(outDir: File, files: List[File], output: File): Boolean = {
+ // compile using command-line javac compiler
+ val javacCmd = if ((fileManager.JAVAC_CMD.indexOf("${env.JAVA_HOME}") != -1) ||
+ fileManager.JAVAC_CMD.equals("/bin/javac") ||
+ fileManager.JAVAC_CMD.equals("\\bin\\javac"))
+ "javac"
+ else
+ fileManager.JAVAC_CMD
+
+ val cmd = javacCmd+
+ " -d "+outDir.getAbsolutePath+
+ " -classpath "+ join(outDir.toString, CLASSPATH) +
+ " "+files.mkString(" ")
+
+ val (success, msg) = try {
+ val exitCode = runCommand(cmd, output)
+ NestUI.verbose("javac returned exit code: "+exitCode)
+ if (exitCode != 0)
+ (false, "Running \"javac\" failed with exit code: "+exitCode+"\n"+cmd+"\n")
+ else
+ (true, "")
+ } catch {
+ case e: Exception =>
+ val swriter = new StringWriter
+ e.printStackTrace(new PrintWriter(swriter))
+ (false, "Running \"javac\" failed:\n"+cmd+"\n"+swriter.toString+"\n")
+ }
+ if (!success) {
+ val writer = new PrintWriter(new FileWriter(output, true), true)
+ writer.print(msg)
+ writer.close()
+ }
+ success
+ }
+
+ /** Runs <code>command</code> redirecting standard out and
+ * error out to <code>output</code> file.
+ */
+ def runCommand(command: String, output: File): Int = {
+ NestUI.verbose("running command:\n"+command)
+ val proc = Runtime.getRuntime.exec(command)
+ val in = proc.getInputStream
+ val err = proc.getErrorStream
+ val writer = new PrintWriter(new FileWriter(output), true)
+ val inApp = StreamAppender(in, writer)
+ val errApp = StreamAppender(err, writer)
+ val async = new Thread(errApp)
+ async.start()
+ inApp.run()
+ async.join()
+ writer.close()
+
+ try proc.exitValue()
+ catch { case _: IllegalThreadStateException => 0 }
+ }
+
+ def execTest(outDir: File, logFile: File, fileBase: String) {
+ // check whether there is a ".javaopts" file
+ val argsFile = new File(logFile.getParentFile, fileBase+".javaopts")
+ val argString = if (argsFile.exists) {
+ NestUI.verbose("Found javaopts file: "+argsFile)
+ val fileReader = new FileReader(argsFile)
+ val reader = new BufferedReader(fileReader)
+ val options = reader.readLine()
+ reader.close()
+ NestUI.verbose("Found javaopts file '%s', using options: '%s'".format(argsFile, options))
+ options
+ } else ""
+
+ def quote(path: String) = "\""+path+"\""
+
+ // Note! As this currently functions, JAVA_OPTS must precede argString
+ // because when an option is repeated to java only the last one wins.
+ // That means until now all the .javaopts files were being ignored because
+ // they all attempt to change options which are also defined in
+ // partest.java_opts, leading to debug output like:
+ //
+ // debug: Found javaopts file 'files/shootout/message.scala-2.javaopts', using options: '-Xss32k'
+ // debug: java -Xss32k -Xss2m -Xms256M -Xmx1024M -classpath [...]
+ val propertyOptions = List(
+ "-Djava.library.path="+logFile.getParentFile.getAbsolutePath,
+ "-Dpartest.output="+outDir.getAbsolutePath,
+ "-Dpartest.lib="+LATEST_LIB,
+ "-Dpartest.cwd="+outDir.getParent,
+ "-Djavacmd="+JAVACMD,
+ "-Duser.language=en -Duser.country=US"
+ ) ::: (
+ if (isPartestDebug) List("-Dpartest.debug=true") else Nil
+ )
+
+ val cmd = (
+ List(
+ JAVACMD,
+ JAVA_OPTS,
+ argString,
+ "-classpath " + join(outDir.toString, CLASSPATH)
+ ) ::: propertyOptions ::: List(
+ "scala.tools.nsc.MainGenericRunner",
+ "-usejavacp",
+ "Test",
+ "jvm"
+ )
+ ) mkString " "
+
+ runCommand(cmd, logFile)
+
+ if (fileManager.showLog) {
+ // produce log as string in `log`
+ val reader = new BufferedReader(new FileReader(logFile))
+ val swriter = new StringWriter
+ val pwriter = new PrintWriter(swriter, true)
+ val appender = new StreamAppender(reader, pwriter)
+ appender.run()
+ log = swriter.toString
+ }
+ }
+
+ def getCheckFile(dir: File, fileBase: String, kind: String) = {
+ def chkFile(s: String) = Directory(dir) / "%s%s.check".format(fileBase, s)
+ val checkFile = if (chkFile("").isFile) chkFile("") else chkFile("-" + kind)
+
+ if (checkFile.canRead) Some(checkFile) else None
+ }
+
+ def existsCheckFile(dir: File, fileBase: String, kind: String) =
+ getCheckFile(dir, fileBase, kind).isDefined
+
+ def compareOutput(dir: File, fileBase: String, kind: String, logFile: File): String =
+ // if check file exists, compare with log file
+ getCheckFile(dir, fileBase, kind) match {
+ case Some(f) => fileManager.compareFiles(logFile, f.jfile)
+ case _ => file2String(logFile)
+ }
+
+ def file2String(logFile: File) = SFile(logFile).slurp()
+ def isJava(f: File) = SFile(f) hasExtension "java"
+ def isScala(f: File) = SFile(f) hasExtension "scala"
+ def isJavaOrScala(f: File) = isJava(f) || isScala(f)
+
+ /** Runs a list of tests.
+ *
+ * @param kind The test kind (pos, neg, run, etc.)
+ * @param files The list of test files
+ */
+ def runTests(kind: String, files: List[File])(topcont: ImmMap[String, Int] => Unit) {
+ val compileMgr = new CompileManager(fileManager)
+ var errors = 0
+ var succeeded = true
+ var diff = ""
+ var log = ""
+
+ def fail(what: Any) {
+ NestUI.verbose("scalac: compilation of "+what+" failed\n")
+ succeeded = false
+ }
+ def diffCheck(latestDiff: String) = {
+ diff = latestDiff
+ if (latestDiff != "") {
+ NestUI.verbose("output differs from log file\n")
+ succeeded = false
+ }
+ }
+
+ /** 1. Creates log file and output directory.
+ * 2. Runs <code>script</code> function, providing log file and
+ * output directory as arguments.
+ */
+ 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)
+ val logFile = createLogFile(file, kind)
+ if (!fileManager.failed || logFile.canRead) {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ succeeded = true
+ diff = ""
+ log = ""
+ printInfoStart(file, wr)
+
+ val fileBase: String = basename(file.getName)
+ NestUI.verbose(this+" running test "+fileBase)
+ val dir = file.getParentFile
+ val outDir = createOutputDir(dir, fileBase, kind)
+ NestUI.verbose("output directory: "+outDir)
+
+ // run test-specific code
+ try {
+ if (isPartestDebug) {
+ val t1 = System.currentTimeMillis
+ script(logFile, outDir)
+ val t2 = System.currentTimeMillis
+ fileManager.recordTestTiming(file.getPath, t2 - t1)
+ }
+ else {
+ script(logFile, outDir)
+ }
+ } catch {
+ case e: Exception =>
+ val writer = new PrintWriter(new FileWriter(logFile), true)
+ e.printStackTrace(writer)
+ writer.close()
+ succeeded = false
+ }
+
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ }
+
+ def compileFilesIn(dir: File, kind: String, logFile: File, outDir: File) {
+ val testFiles = dir.listFiles.toList filter isJavaOrScala
+
+ def isInGroup(f: File, num: Int) = SFile(f).stripExtension endsWith ("_" + num)
+ val groups = (0 to 9).toList map (num => testFiles filter (f => isInGroup(f, num)))
+ val noGroupSuffix = testFiles -- groups.flatten
+
+ def compileGroup(g: List[File]) {
+ val (scalaFiles, javaFiles) = g partition isScala
+
+ if (scalaFiles.nonEmpty) {
+ if (!compileMgr.shouldCompile(outDir, javaFiles ::: scalaFiles, kind, logFile))
+ fail(g)
+ }
+
+ if (succeeded && javaFiles.nonEmpty) {
+ succeeded = javac(outDir, javaFiles, logFile)
+ if (succeeded && scalaFiles.nonEmpty && !compileMgr.shouldCompile(outDir, scalaFiles, kind, logFile))
+ fail(scalaFiles)
+ }
+ }
+
+ if (noGroupSuffix.nonEmpty)
+ compileGroup(noGroupSuffix)
+
+ groups foreach (grp => if (succeeded) compileGroup(grp))
+ }
+
+ def failCompileFilesIn(dir: File, kind: String, logFile: File, outDir: File) {
+ val testFiles = dir.listFiles.toList
+ val sourceFiles = testFiles filter isJavaOrScala
+
+ if (sourceFiles.nonEmpty) {
+ if (!compileMgr.shouldFailCompile(outDir, sourceFiles, kind, logFile))
+ fail(testFiles filter isScala)
+ }
+ }
+
+ def runTestCommon(file: File, kind: String, expectFailure: Boolean)(onSuccess: (File, File) => Unit): LogContext =
+ runInContext(file, kind, (logFile: File, outDir: File) => {
+
+ if (file.isDirectory) {
+ val f = if (expectFailure) failCompileFilesIn _ else compileFilesIn _
+ f(file, kind, logFile, outDir)
+ }
+ else {
+ val f: (List[File], String, File) => Boolean =
+ if (expectFailure) compileMgr.shouldFailCompile _
+ else compileMgr.shouldCompile _
+
+ if (!f(List(file), kind, logFile))
+ fail(file)
+ }
+
+ if (succeeded) // run test
+ onSuccess(logFile, outDir)
+ })
+
+ def runJvmTest(file: File, kind: String): LogContext =
+ runTestCommon(file, kind, expectFailure = false)((logFile, outDir) => {
+ val fileBase = basename(file.getName)
+ val dir = file.getParentFile
+
+ //TODO: detect whether we have to use Runtime.exec
+ // val useRuntime = true
+ //
+ // if (useRuntime)
+ // execTest(outDir, logFile, fileBase)
+ // else
+ // execTestObjectRunner(file, outDir, logFile)
+ // // NestUI.verbose(this+" finished running "+fileBase)
+ execTest(outDir, logFile, fileBase)
+
+ diffCheck(compareOutput(dir, fileBase, kind, logFile))
+ })
+
+ def processSingleFile(file: File): LogContext = kind match {
+ case "scalacheck" =>
+ runTestCommon(file, kind, expectFailure = false)((logFile, outDir) => {
+ val consFM = new ConsoleFileManager
+ import consFM.{ latestCompFile, latestLibFile, latestPartestFile }
+
+ NestUI.verbose("compilation of "+file+" succeeded\n")
+
+ val scalacheckURL = PathSettings.scalaCheck.toURL
+ val outURL = outDir.getCanonicalFile.toURI.toURL
+ val classpath: List[URL] =
+ List(outURL, scalacheckURL, latestCompFile.toURI.toURL, latestLibFile.toURI.toURL, latestPartestFile.toURI.toURL).distinct
+
+ NestUI.debug("scalacheck urls")
+ classpath foreach (x => NestUI.debug(x.toString))
+
+ val logWriter = new PrintStream(new FileOutputStream(logFile))
+
+ withOutputRedirected(logWriter) {
+ ObjectRunner.run(classpath, "Test", Nil)
+ }
+
+ NestUI.verbose(SFile(logFile).slurp())
+ // obviously this must be improved upon
+ succeeded = SFile(logFile).lines() forall (_ contains " OK")
+ })
+
+ case "pos" =>
+ runTestCommon(file, kind, expectFailure = false)((_, _) => ())
+
+ case "neg" =>
+ runTestCommon(file, kind, expectFailure = true)((logFile, outDir) => {
+ // compare log file to check file
+ val fileBase = basename(file.getName)
+ val dir = file.getParentFile
+
+ diffCheck(
+ // diff is contents of logFile
+ if (!existsCheckFile(dir, fileBase, kind)) file2String(logFile)
+ else compareOutput(dir, fileBase, kind, logFile)
+ )
+ })
+
+ case "run" | "jvm" =>
+ runJvmTest(file, kind)
+
+ case "buildmanager" =>
+ val logFile = createLogFile(file, kind)
+ if (!fileManager.failed || logFile.canRead) {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ succeeded = true; diff = ""
+ printInfoStart(file, wr)
+ val (outDir, testFile, changesDir, fileBase) =
+
+ if (!file.isDirectory) {
+ succeeded = false
+ (null, null, null, null)
+ } else {
+ val fileBase: String = basename(file.getName)
+ NestUI.verbose(this+" running test "+fileBase)
+ val outDir = createOutputDir(file, fileBase, kind)
+ if (!outDir.exists) outDir.mkdir()
+ val testFile = new File(file, fileBase + ".test")
+ val changesDir = new File(file, fileBase + ".changes")
+ if (changesDir.isFile || !testFile.isFile) {
+ // if changes exists then it has to be a dir
+ if (!testFile.isFile) NestUI.verbose("invalid build manager test file")
+ if (changesDir.isFile) NestUI.verbose("invalid build manager changes directory")
+ succeeded = false
+ (null, null, null, null)
+ } else {
+ copyTestFiles(file, outDir)
+ NestUI.verbose("outDir: "+outDir)
+ NestUI.verbose("logFile: "+logFile)
+ (outDir, testFile, changesDir, fileBase)
+ }
+ }
+
+ if (succeeded) {
+ // Pre-conditions satisfied
+
+ try {
+ val sourcepath = outDir.getAbsolutePath+File.separator
+
+ // configure input/output files
+ val logWriter = new PrintStream(new FileOutputStream(logFile))
+ val testReader = new BufferedReader(new FileReader(testFile))
+ val logConsoleWriter = new PrintWriter(logWriter)
+
+ // create proper settings for the compiler
+ val settings = new Settings(error)
+ settings.outdir.value = outDir.getCanonicalFile.getAbsolutePath
+ settings.sourcepath.value = sourcepath
+ settings.classpath.value = fileManager.CLASSPATH
+ settings.Ybuildmanagerdebug.value = true
+
+ // simulate Build Manager loop
+ val prompt = "builder > "
+ reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter)
+ val bM: BuildManager =
+ new RefinedBuildManager(settings) {
+ override protected def newCompiler(settings: Settings) =
+ new BuilderGlobal(settings, reporter)
+ }
+
+ val testCompile = (line: String) => {
+ NestUI.verbose("compiling " + line)
+ val args = (line split ' ').toList
+ val command = new CompilerCommand(args, settings)
+ bM.update(filesToSet(settings.sourcepath.value, command.files), Set.empty)
+ !reporter.hasErrors
+ }
+
+ val updateFiles = (line: String) => {
+ NestUI.verbose("updating " + line)
+ val res =
+ ((line split ' ').toList).forall(u => {
+ (u split "=>").toList match {
+ case origFileName::(newFileName::Nil) =>
+ val newFile = new File(changesDir, newFileName)
+ if (newFile.isFile) {
+ val v = overwriteFileWith(new File(outDir, origFileName), newFile)
+ if (!v)
+ NestUI.verbose("'update' operation on " + u + " failed")
+ v
+ } else {
+ NestUI.verbose("File " + newFile + " is invalid")
+ false
+ }
+ case a =>
+ NestUI.verbose("Other =: " + a)
+ false
+ }
+ })
+ if (!res)
+ NestUI.verbose("updating failed")
+ else
+ NestUI.verbose("updating succeeded")
+ res
+ }
+
+ def loop() {
+ val command = testReader.readLine()
+ if ((command ne null) && command.length() > 0) {
+ val commandResult = command match {
+ case s if (s.startsWith(">>update ")) =>
+ updateFiles(s.stripPrefix(">>update "))
+ case s if (s.startsWith(">>compile ")) =>
+ val files = s.stripPrefix(">>compile ")
+ logWriter.println(prompt + files)
+ testCompile(files) // In the end, it can finish with an error
+ case _ =>
+ NestUI.verbose("wrong command in test file: " + command)
+ false
+ }
+
+ if (commandResult) loop()
+
+ } else {
+ NestUI.verbose("finished")
+ succeeded = true
+ }
+ }
+
+ withOutputRedirected(logWriter) {
+ loop()
+ testReader.close()
+ }
+
+ fileManager.mapFile(logFile, "tmp", file, _.replace(sourcepath, ""))
+
+ diffCheck(compareOutput(file, fileBase, kind, logFile))
+ }
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ } else
+ LogContext(logFile, None)
+
+ case "res" => {
+ // when option "--failed" is provided
+ // execute test only if log file is present
+ // (which means it failed before)
+
+ //val (logFileOut, logFileErr) = createLogFiles(file, kind)
+ val logFile = createLogFile(file, kind)
+ if (!fileManager.failed || logFile.canRead) {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ succeeded = true; diff = ""; log = ""
+ printInfoStart(file, wr)
+
+ val fileBase: String = basename(file.getName)
+ NestUI.verbose(this+" running test "+fileBase)
+ val dir = file.getParentFile
+ val outDir = createOutputDir(dir, fileBase, kind)
+ if (!outDir.exists) outDir.mkdir()
+ val resFile = new File(dir, fileBase + ".res")
+ NestUI.verbose("outDir: "+outDir)
+ NestUI.verbose("logFile: "+logFile)
+ //NestUI.verbose("logFileErr: "+logFileErr)
+ NestUI.verbose("resFile: "+resFile)
+
+ // run compiler in resident mode
+ // $SCALAC -d "$os_dstbase".obj -Xresident -sourcepath . "$@"
+
+ try {
+
+ val sourcedir = logFile.getParentFile.getCanonicalFile
+ val sourcepath = sourcedir.getAbsolutePath+File.separator
+ NestUI.verbose("sourcepath: "+sourcepath)
+
+ val argString =
+ "-d "+outDir.getCanonicalFile.getAbsolutePath+
+ " -Xresident"+
+ " -sourcepath "+sourcepath
+ val argList = argString split ' ' toList
+
+ // configure input/output files
+ val logOut = new FileOutputStream(logFile)
+ val logWriter = new PrintStream(logOut)
+ val resReader = new BufferedReader(new FileReader(resFile))
+ val logConsoleWriter = new PrintWriter(new OutputStreamWriter(logOut))
+
+ // create compiler
+ val settings = new Settings(error)
+ settings.sourcepath.value = sourcepath
+ settings.classpath.value = fileManager.CLASSPATH
+ reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter)
+ val command = new CompilerCommand(argList, settings)
+ object compiler extends Global(command.settings, reporter)
+
+ // simulate resident compiler loop
+ val prompt = "\nnsc> "
+
+ val resCompile = (line: String) => {
+ NestUI.verbose("compiling "+line)
+ val cmdArgs = (line split ' ').toList map (fs => new File(dir, fs).getAbsolutePath)
+ NestUI.verbose("cmdArgs: "+cmdArgs)
+ val sett = new Settings(error)
+ sett.sourcepath.value = sourcepath
+ val command = new CompilerCommand(cmdArgs, sett)
+ (new compiler.Run) compile command.files
+ }
+
+ def loop(action: (String) => Unit) {
+ logWriter.print(prompt)
+ val line = resReader.readLine()
+ if ((line ne null) && line.length() > 0) {
+/*
+ val parent = self
+ self.trapExit = true
+ val child = link {
+ action(line)
+ }
+
+ receiveWithin(fileManager.timeout.toLong) {
+ case TIMEOUT =>
+ NestUI.verbose("action timed out")
+ false
+ case Exit(from, reason) if from == child => reason match {
+ case 'normal => // do nothing
+ case t: Throwable =>
+ NestUI.verbose("while invoking compiler:")
+ NestUI.verbose("caught "+t)
+ t.printStackTrace
+ if (t.getCause != null)
+ t.getCause.printStackTrace
+ false
+ }
+ }
+*/
+ action(line)
+ loop(action)
+ }
+ }
+
+ withOutputRedirected(logWriter) {
+ loop(resCompile)
+ resReader.close()
+ }
+
+ def replaceSlashes(s: String): String = {
+ val path = dir.getAbsolutePath+File.separator
+ // find `path` in `line`
+ val index = s.indexOf(path)
+ val line =
+ if (index != -1)
+ s.substring(0, index) + s.substring(index + path.length, s.length)
+ else s
+ line.replace('\\', '/')
+ }
+
+ fileManager.mapFile(logFile, "tmp", dir, replaceSlashes)
+ diffCheck(compareOutput(dir, fileBase, kind, logFile))
+
+ } catch {
+ case e: Exception =>
+ e.printStackTrace()
+ succeeded = false
+ }
+
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ }
+
+ case "shootout" => {
+ // when option "--failed" is provided
+ // execute test only if log file is present
+ // (which means it failed before)
+ val logFile = createLogFile(file, kind)
+ if (!fileManager.failed || logFile.canRead) {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ succeeded = true; diff = ""; log = ""
+ printInfoStart(file, wr)
+
+ val fileBase: String = basename(file.getName)
+ NestUI.verbose(this+" running test "+fileBase)
+ val dir = file.getParentFile
+ val outDir = createOutputDir(dir, fileBase, kind)
+ if (!outDir.exists) outDir.mkdir()
+
+ // 2. define file {outDir}/test.scala that contains code to compile/run
+ val testFile = new File(outDir, "test.scala")
+ NestUI.verbose("outDir: "+outDir)
+ NestUI.verbose("logFile: "+logFile)
+ NestUI.verbose("testFile: "+testFile)
+
+ // 3. cat {test}.scala.runner {test}.scala > testFile
+ val runnerFile = new File(dir, fileBase+".scala.runner")
+ val bodyFile = new File(dir, fileBase+".scala")
+ val appender = StreamAppender.concat(new FileInputStream(runnerFile),
+ new FileInputStream(bodyFile),
+ new FileOutputStream(testFile))
+ appender.run()
+
+ try { // *catch-all*
+ // 4. compile testFile
+ if (!compileMgr.shouldCompile(List(testFile), kind, logFile)) {
+ NestUI.verbose("compilation of "+file+" failed\n")
+ succeeded = false
+ } else {
+ NestUI.verbose("compilation of "+testFile+"succeeded")
+ // -------- run test --------
+
+ //TODO: detect whether we have to use Runtime.exec
+ // val useRuntime = true
+ //
+ // if (useRuntime)
+ // execTest(outDir, logFile, fileBase)
+ // else
+ // execTestObjectRunner(file, outDir, logFile)
+
+ execTest(outDir, logFile, fileBase)
+
+ NestUI.verbose(this+" finished running "+fileBase)
+ } // successful compile
+ } catch { // *catch-all*
+ case e: Exception =>
+ NestUI.verbose("caught "+e)
+ succeeded = false
+ }
+
+ diffCheck(compareOutput(dir, fileBase, kind, logFile))
+
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ }
+
+ case "scalap" => {
+
+ runInContext(file, kind, (logFile: File, outDir: File) => {
+ val sourceDir = file.getParentFile
+ val sourceDirName = sourceDir.getName
+
+ // 1. Find file with result text
+ val results = sourceDir.listFiles(new FilenameFilter {
+ def accept(dir: File, name: String) = name == "result.test"
+ })
+
+ if (results.length != 1) {
+ NestUI.verbose("Result file not found in directory " + sourceDirName + " \n")
+ } else {
+ val resFile = results(0)
+ // 2. Compile source file
+ if (!compileMgr.shouldCompile(outDir, List(file), kind, logFile)) {
+ NestUI.verbose("compilerMgr failed to compile %s to %s".format(file, outDir))
+ succeeded = false
+ } else {
+
+ // 3. Decompile file and compare results
+ val isPackageObject = sourceDir.getName.startsWith("package")
+ val className = sourceDirName.capitalize + (if (!isPackageObject) "" else ".package")
+ val url = outDir.toURI.toURL
+ val loader = new URLClassLoader(Array(url), getClass.getClassLoader)
+ val clazz = loader.loadClass(className)
+
+ val byteCode = ByteCode.forClass(clazz)
+ val result = scala.tools.scalap.Main.decompileScala(byteCode.bytes, isPackageObject)
+
+ try {
+ val fstream = new FileWriter(logFile);
+ val out = new BufferedWriter(fstream);
+ out.write(result)
+ out.close();
+ } catch {
+ case e: IOException => NestUI.verbose(e.getMessage()); succeeded = false
+ }
+
+ diffCheck(fileManager.compareFiles(logFile, resFile))
+ }
+ }
+ })
+ }
+
+ case "script" => {
+ // when option "--failed" is provided
+ // execute test only if log file is present
+ // (which means it failed before)
+ val logFile = createLogFile(file, kind)
+ if (!fileManager.failed || logFile.canRead) {
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ succeeded = true; diff = ""; log = ""
+ printInfoStart(file, wr)
+
+ val fileBase: String = basename(file.getName)
+ NestUI.verbose(this+" running test "+fileBase)
+
+ // check whether there is an args file
+ val argsFile = new File(file.getParentFile, fileBase+".args")
+ NestUI.verbose("argsFile: "+argsFile)
+ val argString = if (argsFile.exists) {
+ val swriter = new StringWriter
+ val app = StreamAppender(new BufferedReader(new FileReader(argsFile)),
+ swriter)
+ app.run()
+ " "+swriter.toString
+ } else ""
+
+ try {
+ val cmdString =
+ if (isWin) {
+ val batchFile = new File(file.getParentFile, fileBase+".bat")
+ NestUI.verbose("batchFile: "+batchFile)
+ batchFile.getAbsolutePath
+ }
+ else file.getAbsolutePath
+ val proc = Runtime.getRuntime.exec(cmdString+argString)
+ val in = proc.getInputStream
+ val err = proc.getErrorStream
+ val writer = new PrintWriter(new FileWriter(logFile), true)
+ val inApp = new StreamAppender(new BufferedReader(new InputStreamReader(in)),
+ writer)
+ val errApp = new StreamAppender(new BufferedReader(new InputStreamReader(err)),
+ writer)
+ val async = new Thread(errApp)
+ async.start()
+ inApp.run()
+ async.join()
+
+ writer.close()
+
+ diffCheck(compareOutput(file.getParentFile, fileBase, kind, logFile))
+ } catch { // *catch-all*
+ case e: Exception =>
+ NestUI.verbose("caught "+e)
+ succeeded = false
+ }
+
+ LogContext(logFile, Some((swr, wr)))
+ } else
+ LogContext(logFile, None)
+ }
+ }
+
+ def reportAll(results: ImmMap[String, Int], cont: ImmMap[String, Int] => Unit) {
+ // NestUI.verbose("finished testing "+kind+" with "+errors+" errors")
+ // NestUI.verbose("created "+compileMgr.numSeparateCompilers+" separate compilers")
+ timer.cancel()
+ cont(results)
+ }
+
+ def reportResult(state: Int, logFile: Option[LogFile], writers: Option[(StringWriter, PrintWriter)]) {
+ val good = (state == 0)
+ if (!good) {
+ errors += 1
+ NestUI.verbose("incremented errors: "+errors)
+ }
+
+ try {
+ // delete log file only if test was successful
+ if (good && !logFile.isEmpty && !isPartestDebug)
+ logFile.get.toDelete = true
+
+ writers match {
+ case Some((swr, wr)) =>
+ if (state == 2)
+ printInfoTimeout(wr)
+ else
+ printInfoEnd(good, wr)
+ wr.flush()
+ swr.flush()
+ NestUI.normal(swr.toString)
+ if (state == 1 && fileManager.showDiff && diff != "")
+ NestUI.normal(diff)
+ if (state == 1 && fileManager.showLog)
+ showLog(logFile.get)
+ case None =>
+ }
+ } catch {
+ case npe: NullPointerException =>
+ }
+ }
+
+ val numFiles = files.size
+ if (numFiles == 0)
+ reportAll(ImmMap(), topcont)
+
+ // maps canonical file names to the test result (0: OK, 1: FAILED, 2: TIMOUT)
+ var status = new HashMap[String, Int]
+
+ var fileCnt = 1
+ Actor.loopWhile(fileCnt <= numFiles) {
+ val parent = self
+
+ actor {
+ val testFile = files(fileCnt-1)
+
+ val ontimeout = new TimerTask {
+ def run() = parent ! Timeout(testFile)
+ }
+ timer.schedule(ontimeout, fileManager.timeout.toLong)
+
+ val context = try {
+ processSingleFile(testFile)
+ } catch {
+ case t: Throwable =>
+ NestUI.verbose("while invoking compiler ("+files+"):")
+ NestUI.verbose("caught "+t)
+ t.printStackTrace
+ if (t.getCause != null)
+ t.getCause.printStackTrace
+ LogContext(null, None)
+ }
+ parent ! Result(testFile, context)
+ }
+
+ react {
+ case res: TestResult =>
+ val path = res.file.getCanonicalPath
+ status.get(path) match {
+ case Some(stat) => // ignore message
+ case None =>
+ res match {
+ case Timeout(_) =>
+ status = status + (path -> 2)
+ val swr = new StringWriter
+ val wr = new PrintWriter(swr)
+ printInfoStart(res.file, wr)
+ succeeded = false
+ reportResult(2, None, Some((swr, wr)))
+ case Result(_, logs) =>
+ status = status + (path -> (if (succeeded) 0 else 1))
+ reportResult(
+ if (succeeded) 0 else 1,
+ if (logs != null) Some(logs.file) else None,
+ if (logs != null) logs.writers else None)
+ }
+ if (fileCnt == numFiles)
+ reportAll(status, topcont)
+ fileCnt += 1
+ }
+ }
+ }
+ }
+
+ private def withOutputRedirected(out: PrintStream)(func: => Unit) {
+ val oldStdOut = System.out
+ val oldStdErr = System.err
+
+ try {
+ System.setOut(out)
+ System.setErr(out)
+ func
+ out.flush()
+ out.close()
+ } finally {
+ System.setOut(oldStdOut)
+ System.setErr(oldStdErr)
+ }
+ }
+
+ private def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
+ fs flatMap (s => Option(AbstractFile getFile (pre + s))) toSet
+
+ private def copyTestFiles(testDir: File, destDir: File) {
+ val invalidExts = List("changes", "svn", "obj")
+ testDir.listFiles.toList filter (
+ f => (isJavaOrScala(f) && f.isFile) ||
+ (f.isDirectory && !(invalidExts.contains(SFile(f).extension)))) foreach
+ { f => fileManager.copyFile(f, destDir) }
+ }
+
+ def showLog(logFile: File) {
+ try {
+ val logReader = new BufferedReader(new FileReader(logFile))
+ val strWriter = new StringWriter
+ val logWriter = new PrintWriter(strWriter, true)
+ val logAppender = new StreamAppender(logReader, logWriter)
+ logAppender.run()
+ logReader.close()
+ val log = strWriter.toString
+ NestUI.normal(log)
+ } catch {
+ case fnfe: java.io.FileNotFoundException =>
+ NestUI.failure("Couldn't open log file \""+logFile+"\".")
+ }
+ }
+}
diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala
index f6d216e379..e9eda6fb75 100644
--- a/src/partest/scala/tools/partest/package.scala
+++ b/src/partest/scala/tools/partest/package.scala
@@ -4,42 +4,37 @@
package scala.tools
-import nsc.io.{ File, Path, Process, Directory }
-import java.nio.charset.CharacterCodingException
+import java.io.{ File => JFile }
+import nsc.io.{ Path, Process, Directory }
+import util.{ PathResolver }
+import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
package object partest {
- /** The CharacterCodingExceptions are thrown at least on windows trying
- * to read a file like script/utf-8.scala
- */
- private[partest] def safeSlurp(f: File) =
- try if (f.exists) f.slurp() else ""
- catch { case _: CharacterCodingException => "" }
-
- private[partest] def safeLines(f: File) = safeSlurp(f) split """\r\n|\r|\n""" toList
- private[partest] def safeArgs(f: File) = toArgs(safeSlurp(f))
- private[partest] def isJava(f: Path) = f.isFile && (f hasExtension "java")
- private[partest] def isScala(f: Path) = f.isFile && (f hasExtension "scala")
- private[partest] def isJavaOrScala(f: Path) = isJava(f) || isScala(f)
-
- private[partest] def toArgs(line: String) = cmd toArgs line
- private[partest] def fromArgs(args: List[String]) = cmd fromArgs args
-
- /** Strings, argument lists, etc. */
-
- private[partest] def fromAnyArgs(args: List[Any]) = args mkString " " // separate to avoid accidents
- private[partest] def toStringTrunc(x: Any, max: Int = 240) = {
- val s = x.toString
- if (s.length < max) s
- else (s take max) + " [...]"
+ import nest.NestUI
+
+ implicit private[partest] def temporaryPath2File(x: Path): JFile = x.jfile
+ implicit private[partest] def temporaryFile2Path(x: JFile): Path = Path(x)
+
+ def basename(name: String): String = Path(name).stripExtension
+ def resultsToStatistics(results: Iterable[(_, Int)]): (Int, Int) = {
+ val (files, failures) = results map (_._2 == 0) partition (_ == true)
+ (files.size, failures.size)
+ }
+
+ def vmArgString = {
+ val str = Process.javaVmArguments mkString " "
+ "Java VM started with arguments: '%s'" format str
+ }
+
+ def allPropertiesString = {
+ import collection.JavaConversions._
+ System.getProperties.toList.sorted map { case (k, v) => "%s -> %s\n".format(k, v) } mkString
}
- private[partest] def setProp(k: String, v: String) = scala.util.Properties.setProp(k, v)
- /** Pretty self explanatory. */
- def printAndExit(msg: String): Unit = {
- println(msg)
- exit(1)
+ def showAllJVMInfo {
+ NestUI.verbose(vmArgString)
+ NestUI.verbose(allPropertiesString)
}
- /** Apply a function and return the passed value */
- def returning[T](x: T)(f: T => Unit): T = { f(x) ; x }
+ def isPartestDebug = propOrEmpty("partest.debug") == "true"
} \ No newline at end of file
diff --git a/src/partest/scala/tools/partest/util/package.scala b/src/partest/scala/tools/partest/util/package.scala
deleted file mode 100644
index bc5470ba5d..0000000000
--- a/src/partest/scala/tools/partest/util/package.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2010 LAMP/EPFL
- */
-
-package scala.tools
-package partest
-
-import java.util.{ Timer, TimerTask }
-import java.io.StringWriter
-import nsc.io._
-
-/** Misc code still looking for a good home.
- */
-package object util {
-
- def allPropertiesString() = javaHashtableToString(System.getProperties)
-
- private def javaHashtableToString(table: java.util.Hashtable[_,_]) = {
- import collection.JavaConversions._
- (table.toList map { case (k, v) => "%s -> %s\n".format(k, v) }).sorted mkString
- }
-
- def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] =
- fs flatMap (x => Option(AbstractFile getFile (Path(pre) / x).path)) toSet
-
- /** Copies one Path to another Path, trying to be sensible when one or the
- * other is a Directory. Returns true if it believes it succeeded.
- */
- def copyPath(from: Path, to: Path): Boolean = {
- if (!to.parent.isDirectory)
- to.parent.createDirectory(force = true)
-
- def copyDir = {
- val sub = to / from.name createDirectory true
- from.toDirectory.list forall (x => copyPath(x, sub))
- }
- (from.isDirectory, to.isDirectory) match {
- case (true, true) => copyDir
- case (true, false) => false
- case (false, true) => from.toFile copyTo (to / from.name)
- case (false, false) => from.toFile copyTo to
- }
- }
-
- /**
- * Compares two files using a Java implementation of the GNU diff
- * available at http://www.bmsi.com/java/#diff.
- *
- * @param f1 the first file to be compared
- * @param f2 the second file to be compared
- * @return the text difference between the compared files
- */
- def diffFiles(f1: File, f2: File): String = {
- val diffWriter = new StringWriter
- val args = Array(f1.toAbsolute.path, f2.toAbsolute.path)
-
- io.DiffPrint.doDiff(args, diffWriter)
- val result = diffWriter.toString
- if (result == "No differences") "" else result
- }
-}
diff --git a/src/partest/scala/tools/partest/utils/PrintMgr.scala b/src/partest/scala/tools/partest/utils/PrintMgr.scala
new file mode 100644
index 0000000000..10533130f1
--- /dev/null
+++ b/src/partest/scala/tools/partest/utils/PrintMgr.scala
@@ -0,0 +1,52 @@
+/* __ *\
+** ________ ___ / / ___ Scala Parallel Testing **
+** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.tools.partest
+package utils
+
+/**
+ * @author Thomas Hofer
+ */
+object PrintMgr {
+
+ val NONE = 0
+ val SOME = 1
+ val MANY = 2
+
+ var outline = ""
+ var success = ""
+ var failure = ""
+ var warning = ""
+ var default = ""
+
+ def initialization(number: Int) = number match {
+ case MANY =>
+ outline = Console.BOLD + Console.BLACK
+ success = Console.BOLD + Console.GREEN
+ failure = Console.BOLD + Console.RED
+ warning = Console.BOLD + Console.YELLOW
+ default = Console.RESET
+ case SOME =>
+ outline = Console.BOLD + Console.BLACK
+ success = Console.RESET
+ failure = Console.BOLD + Console.BLACK
+ warning = Console.BOLD + Console.BLACK
+ default = Console.RESET
+ case _ =>
+ }
+
+ def printOutline(msg: String) = print(outline + msg + default)
+
+ def printSuccess(msg: String) = print(success + msg + default)
+
+ def printFailure(msg: String) = print(failure + msg + default)
+
+ def printWarning(msg: String) = print(warning + msg + default)
+}
diff --git a/src/partest/scala/tools/partest/Properties.scala b/src/partest/scala/tools/partest/utils/Properties.scala
index 4eeb0359ec..237ddea14e 100644
--- a/src/partest/scala/tools/partest/Properties.scala
+++ b/src/partest/scala/tools/partest/utils/Properties.scala
@@ -8,8 +8,8 @@
// $Id$
-package scala.tools
-package partest
+package scala.tools.partest
+package utils
/** Loads partest.properties from the jar. */
object Properties extends scala.util.PropertiesTrait {