Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

SI-6289 Partest in technicolor and showing javac errors

Paulptest includes color and simplified test scarfing.

Scalap tests are moved to the conventional name and location.

Testicolor missed out on Josh Suereth's tweak to sort the files in
a compilation round.  Restore sortiness to test sources.

Testicolor is due to one of Paul's branches on a timeline
that apparently did not include the destruction of planet
Earth and its colonies by the Xindi.

Thanks also to Szabolcs Berecz for his merge effort.  Merging
is thankless work, but not as thankless as merging in a
timeline that actually does terminate in the destruction of
your home world and Enterprise.

Archer had a supremely difficult choice: rescue humanity or
live out his retirement with T'Pol waiting on him hand and
foot? I'm sure I don't know how I'd choose.
  • Loading branch information...
commit c6ce61796f66770ca1b4d63fc0a569f064436433 1 parent 7bb981a
@som-snytt som-snytt authored adriaanm committed
Showing with 1,480 additions and 1,597 deletions.
  1. +25 −60 build.xml
  2. +2 −3 src/partest/scala/tools/partest/DirectTest.scala
  3. +1 −3 src/partest/scala/tools/partest/IcodeTest.scala
  4. +3 −6 src/partest/scala/tools/partest/PartestDefaults.scala
  5. +60 −281 src/partest/scala/tools/partest/PartestTask.scala
  6. +67 −0 src/partest/scala/tools/partest/TestKinds.scala
  7. +54 −0 src/partest/scala/tools/partest/TestState.scala
  8. +11 −14 src/partest/scala/tools/partest/nest/AntRunner.scala
  9. +0 −182 src/partest/scala/tools/partest/nest/CompileManager.scala
  10. +16 −17 src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
  11. +153 −168 src/partest/scala/tools/partest/nest/ConsoleRunner.scala
  12. +105 −0 src/partest/scala/tools/partest/nest/DirectCompiler.scala
  13. +21 −31 src/partest/scala/tools/partest/nest/DirectRunner.scala
  14. +40 −7 src/partest/scala/tools/partest/nest/FileManager.scala
  15. +95 −16 src/partest/scala/tools/partest/nest/NestUI.scala
  16. +584 −0 src/partest/scala/tools/partest/nest/Runner.scala
  17. +10 −679 src/partest/scala/tools/partest/nest/RunnerManager.scala
  18. +12 −17 src/partest/scala/tools/partest/nest/SBTRunner.scala
  19. +53 −0 src/partest/scala/tools/partest/nest/StreamCapture.scala
  20. +0 −80 src/partest/scala/tools/partest/nest/TestFile.scala
  21. +125 −26 src/partest/scala/tools/partest/package.scala
  22. +24 −0 test/build-partest.xml
  23. +1 −1  test/files/neg/choices.check
  24. +1 −1  test/files/neg/choices.flags
  25. +3 −3 test/files/run/reify_this.scala
  26. 0  test/files/scalap/{abstractClass/result.test → abstractClass.check}
  27. 0  test/files/scalap/{abstractClass/A.scala → abstractClass.scala}
  28. 0  test/files/scalap/{abstractMethod/result.test → abstractMethod.check}
  29. 0  test/files/scalap/{abstractMethod/A.scala → abstractMethod.scala}
  30. 0  test/files/scalap/{caseClass/result.test → caseClass.check}
  31. 0  test/files/scalap/{caseClass/A.scala → caseClass.scala}
  32. 0  test/files/scalap/{caseObject/result.test → caseObject.check}
  33. 0  test/files/scalap/{caseObject/A.scala → caseObject.scala}
  34. 0  test/files/scalap/{cbnParam/result.test → cbnParam.check}
  35. 0  test/files/scalap/{cbnParam/A.scala → cbnParam.scala}
  36. 0  test/files/scalap/{classPrivate/result.test → classPrivate.check}
  37. 0  test/files/scalap/{classPrivate/A.scala → classPrivate.scala}
  38. 0  test/files/scalap/{classWithExistential/result.test → classWithExistential.check}
  39. 0  test/files/scalap/{classWithExistential/A.scala → classWithExistential.scala}
  40. 0  test/files/scalap/{classWithSelfAnnotation/result.test → classWithSelfAnnotation.check}
  41. 0  test/files/scalap/{classWithSelfAnnotation/A.scala → classWithSelfAnnotation.scala}
  42. 0  test/files/scalap/{covariantParam/result.test → covariantParam.check}
  43. 0  test/files/scalap/{covariantParam/A.scala → covariantParam.scala}
  44. 0  test/files/scalap/{defaultParameter/result.test → defaultParameter.check}
  45. 0  test/files/scalap/{defaultParameter/A.scala → defaultParameter.scala}
  46. 0  test/files/scalap/{implicitParam/result.test → implicitParam.check}
  47. 0  test/files/scalap/{implicitParam/A.scala → implicitParam.scala}
  48. 0  test/files/scalap/{packageObject/result.test → packageObject.check}
  49. 0  test/files/scalap/{packageObject/A.scala → packageObject.scala}
  50. 0  test/files/scalap/{paramClauses/result.test → paramClauses.check}
  51. 0  test/files/scalap/{paramClauses/A.scala → paramClauses.scala}
  52. 0  test/files/scalap/{paramNames/result.test → paramNames.check}
  53. 0  test/files/scalap/{paramNames/A.scala → paramNames.scala}
  54. 0  test/files/scalap/{sequenceParam/result.test → sequenceParam.check}
  55. 0  test/files/scalap/{sequenceParam/A.scala → sequenceParam.scala}
  56. 0  test/files/scalap/{simpleClass/result.test → simpleClass.check}
  57. 0  test/files/scalap/{simpleClass/A.scala → simpleClass.scala}
  58. 0  test/files/scalap/{traitObject/result.test → traitObject.check}
  59. 0  test/files/scalap/{traitObject/A.scala → traitObject.scala}
  60. 0  test/files/scalap/{typeAnnotations/result.test → typeAnnotations.check}
  61. 0  test/files/scalap/{typeAnnotations/A.scala → typeAnnotations.scala}
  62. 0  test/files/scalap/{valAndVar/result.test → valAndVar.check}
  63. 0  test/files/scalap/{valAndVar/A.scala → valAndVar.scala}
  64. 0  test/files/scalap/{wildcardType/result.test → wildcardType.check}
  65. 0  test/files/scalap/{wildcardType/A.scala → wildcardType.scala}
  66. +14 −2 test/partest
View
85 build.xml 100644 → 100755
@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="sabbus" default="build" xmlns:artifact="urn:maven-artifact-ant">
+ <include file="test/build-partest.xml" as="partest"/>
+
<description>
SuperSabbus for Scala core, builds the scala library and compiler. It can also package it as a simple distribution, tests it for stable bootstrapping and against the Scala test suite.
</description>
@@ -135,7 +137,7 @@ TODO:
<property name="dists.dir" value="${basedir}/dists"/>
<property name="copyright.string" value="Copyright 2002-2013, LAMP/EPFL"/>
- <property name="partest.version.number" value="0.9.2"/>
+ <property name="partest.version.number" value="0.9.3"/>
<!-- These are NOT the flags used to run SuperSabbus, but the ones written
into the script runners created with scala.tools.ant.ScalaTool -->
@@ -530,7 +532,7 @@ TODO:
<path id="quick.partest.build.path">
<path refid="quick.scalap.build.path"/>
<path refid="partest.extras.classpath"/>
- <pathelement location="${build-quick.dir}/classes/repl"/>
+ <pathelement location="${build-quick.dir}/classes/repl"/>
<pathelement location="${scalacheck.jar}"/>
</path>
@@ -650,11 +652,15 @@ TODO:
<path refid="partest.extras.classpath"/>
</path>
+ <!-- obsolete? -->
+ <!-- TODO - segregate swing tests (there can't be many) -->
+ <!--
<path id="partest.build.path">
<path refid="pack.compiler.path"/>
<fileset dir="${partest.dir}/files/lib" includes="*.jar" />
- <pathelement location="${pack.dir}/lib/scala-swing.jar"/> <!-- TODO - segregate swing tests (there can't be many) -->
+ <pathelement location="${pack.dir}/lib/scala-swing.jar"/>
</path>
+ -->
<path id="test.osgi.compiler.build.path">
<pathelement location="${test.osgi.classes}"/>
@@ -762,8 +768,8 @@ TODO:
<touch file="${build-libs.dir}/@{project}.complete" verbose="no"/>
</then></if>
</sequential>
- </macrodef>
-
+ </macrodef>
+
<target name="asm.done" depends="init"> <simple-javac project="asm" jar="no"/> </target>
<target name="forkjoin.done" depends="init"> <simple-javac project="forkjoin" args="-XDignore.symbol.file"/></target>
@@ -1418,72 +1424,32 @@ TODO:
<stopwatch name="quick.sbt-interface.timer" action="total"/>
</target>
- <property name="partest.srcdir" value="files" /> <!-- TODO: make targets for `pending` and other subdirs -->
+ <!-- See test/build-partest.xml for the macro(s) being used here. -->
- <target name="test.run" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="1200000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
-
- <compilationpath refid="partest.build.path"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
- <jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/>
- </partest>
+ <target name="test.suite" depends="pack.done">
+ <testSuite/>
</target>
- <target name="test.suite" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="2400000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise}">
- <compilationpath refid="partest.build.path"/>
- <postests dir="${partest.dir}/${partest.srcdir}/pos" includes="*.scala"/>
- <negtests dir="${partest.dir}/${partest.srcdir}/neg" includes="*.scala"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/run" includes="*.scala"/>
- <jvmtests dir="${partest.dir}/${partest.srcdir}/jvm" includes="*.scala"/>
- <residenttests dir="${partest.dir}/${partest.srcdir}/res" includes="*.res"/>
- <scalaptests dir="${partest.dir}/${partest.srcdir}/scalap" includes="**/*.scala"/>
- <scalachecktests dir="${partest.dir}/${partest.srcdir}/scalacheck">
- <include name="*.scala"/>
- </scalachecktests>
- <specializedtests dir="${partest.dir}/${partest.srcdir}/specialized">
- <include name="*.scala"/>
- </specializedtests>
- <instrumentedtests dir="${partest.dir}/${partest.srcdir}/instrumented">
- <include name="*.scala"/>
- </instrumentedtests>
- </partest>
+ <target name="test.suite.color" depends="pack.done">
+ <testSuite colors="8"/>
+ </target>
+
+ <target name="test.run" depends="pack.done">
+ <testSuite kinds="run jvm"/>
</target>
<target name="test.continuations.suite" depends="pack.done">
- <partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
- timeout="2400000"
- srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable">
- <compilerarg value="-Xpluginsdir"/>
- <compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
- <compilationpath refid="partest.build.path"/>
- <negtests dir="${partest.dir}/${partest.srcdir}/continuations-neg" includes="*.scala"/>
- <runtests dir="${partest.dir}/${partest.srcdir}/continuations-run" includes="*.scala"/>
- </partest>
+ <testSuite kinds="continuations-neg continuations-run"
+ scalacOpts="${scalac.args.optimise} -Xpluginsdir ${build-quick.dir}/misc/scala-devel/plugins -Xplugin-require:continuations -P:continuations:enable"
+ />
</target>
<target name="test.scaladoc" depends="pack.done">
- <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.build.path"/>
- <runtests dir="${partest.dir}/scaladoc/run" includes="*.scala" />
- <scalachecktests dir="${partest.dir}/scaladoc/scalacheck" includes="*.scala" />
- </partest>
+ <testSuite kinds="run scalacheck" srcdir="scaladoc"/>
</target>
<target name="test.interactive" depends="pack.done">
- <partest erroronfailed="yes" scalacopts="${scalac.args.optimise}" showlog="yes">
- <compilationpath refid="partest.build.path"/>
- <presentationtests dir="${partest.dir}/${partest.srcdir}/presentation">
- <include name="*/*.scala"/>
- </presentationtests>
- </partest>
+ <testSuite kinds="presentation"/>
</target>
<!-- for use in PR validation, where stability is rarely broken, so we're going to use starr for locker,
@@ -1491,7 +1457,6 @@ TODO:
<target name="test.core" depends="test.osgi, test.sbt, test.bc, test.interactive, test.continuations.suite, test.scaladoc, test.suite"/>
<target name="test.done" depends="test.core, test.stability"/>
-
<!-- ===========================================================================
BINARY COMPATIBILITY TESTING
============================================================================ -->
View
5 src/partest/scala/tools/partest/DirectTest.scala
@@ -6,7 +6,6 @@
package scala.tools.partest
import scala.tools.nsc._
-import io.Directory
import util.{BatchSourceFile, CommandLineParser}
import reporters.{Reporter, ConsoleReporter}
@@ -21,8 +20,8 @@ abstract class DirectTest extends App {
def show(): Unit
// the test file or dir, and output directory
- def testPath = io.File(sys.props("partest.test-path"))
- def testOutput = io.Directory(sys.props("partest.output"))
+ def testPath = SFile(sys.props("partest.test-path"))
+ def testOutput = Directory(sys.props("partest.output"))
// override to add additional settings with strings
def extraSettings: String = ""
View
4 src/partest/scala/tools/partest/IcodeTest.scala
@@ -5,9 +5,7 @@
package scala.tools.partest
-import scala.tools.nsc._
-import nest.FileUtil._
-import io.Directory
+import scala.tools.partest.nest.FileUtil.compareContents
/** A trait for testing icode. All you need is this in a
* partest source file:
View
9 src/partest/scala/tools/partest/PartestDefaults.scala
@@ -1,13 +1,10 @@
package scala.tools
package partest
-import nsc.io.{ File, Path, Directory }
-import scala.tools.util.PathResolver
-import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
-import java.lang.Runtime.getRuntime
+import scala.tools.nsc.Properties.{ propOrElse, propOrNone, propOrEmpty }
+import java.lang.Runtime.{ getRuntime => runtime }
object PartestDefaults {
- import nsc.Properties._
def testRootName = propOrNone("partest.root")
def srcDirName = propOrElse("partest.srcdir", "files")
@@ -23,7 +20,7 @@ object PartestDefaults {
def testBuild = propOrNone("partest.build")
def errorCount = propOrElse("partest.errors", "0").toInt
- def numThreads = propOrNone("partest.threads") map (_.toInt) getOrElse getRuntime.availableProcessors
+ def numThreads = propOrNone("partest.threads") map (_.toInt) getOrElse runtime.availableProcessors
def timeout = "1200000"
}
View
341 src/partest/scala/tools/partest/PartestTask.scala
@@ -10,14 +10,10 @@ package scala.tools
package partest
import scala.util.Properties.setProp
-import scala.tools.nsc.io.{ Directory, Path => SPath }
-import nsc.util.ClassPath
-import util.PathResolver
import scala.tools.ant.sabbus.CompilationPathProperty
-import java.io.File
import java.lang.reflect.Method
import org.apache.tools.ant.Task
-import org.apache.tools.ant.types.{Path, Reference, FileSet}
+import org.apache.tools.ant.types.{ Reference, FileSet}
import org.apache.tools.ant.types.Commandline.Argument
/** An Ant task to execute the Scala test suite (NSC).
@@ -26,92 +22,42 @@ import org.apache.tools.ant.types.Commandline.Argument
* - `srcdir`,
* - `classpath`,
* - `classpathref`,
- * - `showlog`,
- * - `showdiff`,
* - `erroronfailed`,
* - `javacmd`,
* - `javaccmd`,
* - `scalacopts`,
- * - `timeout`,
* - `debug`,
* - `junitreportdir`.
*
* It also takes the following parameters as nested elements:
* - `compilationpath`.
- * - `postests`,
- * - `negtests`,
- * - `runtests`,
- * - `jvmtests`,
- * - `residenttests`,
- * - `shootouttests`,
- * - `scalaptests`,
- * - `scalachecktests`,
- * - `specializedtests`,
- * - `instrumentedtests`,
- * - `presentationtests`,
- * - `scripttests`.
*
* @author Philippe Haller
*/
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 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 addConfiguredSpecializedTests(input: FileSet) {
- specializedFiles = Some(input)
- }
-
- def addConfiguredInstrumentedTests(input: FileSet) {
- instrumentedFiles = Some(input)
- }
-
- def addConfiguredPresentationTests(input: FileSet) {
- presentationFiles = Some(input)
- }
-
- def addConfiguredAntTests(input: FileSet) {
- antFiles = Some(input)
- }
-
+ type Path = org.apache.tools.ant.types.Path
+
+ private var kinds: List[String] = Nil
+ private var classpath: Option[Path] = None
+ private var debug = false
+ private var errorOnFailed: Boolean = true
+ private var jUnitReportDir: Option[File] = None
+ private var javaccmd: Option[File] = None
+ private var javacmd: Option[File] = Option(sys.props("java.home")) map (x => new File(x, "bin/java"))
+ private var scalacArgs: Option[Seq[Argument]] = None
+ private var srcDir: Option[String] = None
+ private var colors: Int = 0
def setSrcDir(input: String) {
srcDir = Some(input)
}
+ def setColors(input: String) {
+ try colors = input.toInt catch { case _: NumberFormatException => () }
+ if (colors > 0)
+ sys.props("partest.colors") = colors.toString
+ }
+
def setClasspath(input: Path) {
if (classpath.isEmpty)
classpath = Some(input)
@@ -127,15 +73,6 @@ class PartestTask extends Task with CompilationPathProperty {
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
}
@@ -144,6 +81,10 @@ class PartestTask extends Task with CompilationPathProperty {
javacmd = Some(input)
}
+ def setKinds(input: String) {
+ kinds = words(input)
+ }
+
def setJavacCmd(input: File) {
javaccmd = Some(input)
}
@@ -159,10 +100,6 @@ class PartestTask extends Task with CompilationPathProperty {
a
}
- def setTimeout(delay: String) {
- timeout = Some(delay)
- }
-
def setDebug(input: Boolean) {
debug = input
}
@@ -171,172 +108,35 @@ class PartestTask extends Task with CompilationPathProperty {
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 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 scalacheckFiles: Option[FileSet] = None
- private var scriptFiles: Option[FileSet] = None
- private var shootoutFiles: Option[FileSet] = None
- private var scalapFiles: Option[FileSet] = None
- private var specializedFiles: Option[FileSet] = None
- private var instrumentedFiles: Option[FileSet] = None
- private var presentationFiles: Option[FileSet] = None
- private var antFiles: Option[FileSet] = None
- private var errorOnFailed: Boolean = false
- private var scalacArgs: Option[Seq[Argument]] = 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 ".")
- // println("----> " + fileSet)
-
- val fileTests = getFiles(Some(fs)) filterNot (x => shouldExclude(x.getName))
- val dirResult = getDirs(Some(fs)) filterNot (x => shouldExclude(x.getName))
- // println("dirs: " + dirResult.toList)
- // println("files: " + fileTests.toList)
-
- dirResult ++ fileTests
- }
-
- private def getDirs(fileSet: Option[FileSet]): Array[File] = fileSet match {
- case None => Array()
- case Some(fs) =>
- def shouldExclude(name: String) = (name endsWith ".obj") || (name startsWith ".")
-
- val dirTests: Iterator[SPath] = fileSetToDir(fs).dirs filterNot (x => shouldExclude(x.name))
- val dirResult = dirTests.toList.toArray map (_.jfile)
-
- dirResult
- }
-
-
- private def getPosFiles = getFilesAndDirs(posFiles)
- private def getNegFiles = getFilesAndDirs(negFiles)
- private def getRunFiles = getFilesAndDirs(runFiles)
- private def getJvmFiles = getFilesAndDirs(jvmFiles)
- private def getResidentFiles = getFiles(residentFiles)
- private def getScalacheckFiles = getFilesAndDirs(scalacheckFiles)
- private def getScriptFiles = getFiles(scriptFiles)
- private def getShootoutFiles = getFiles(shootoutFiles)
- private def getScalapFiles = getFiles(scalapFiles)
- private def getSpecializedFiles = getFiles(specializedFiles)
- private def getInstrumentedFiles = getFilesAndDirs(instrumentedFiles)
- private def getPresentationFiles = getDirs(presentationFiles)
- private def getAntFiles = getFiles(antFiles)
-
override def execute() {
- val opts = getProject().getProperties() get "env.PARTEST_OPTS"
- if (opts != null && opts.toString != "")
- opts.toString.split(" ") foreach { propDef =>
- log("setting system property " + propDef)
- val kv = propDef split "="
- val key = kv(0) substring 2
- val value = kv(1)
- setProp(key, value)
- }
-
- if (isPartestDebug || debug) {
- setProp("partest.debug", "true")
- nest.NestUI._verbose = true
+ if (debug || sys.props.contains("partest.debug")) {
+ nest.NestUI.setDebug()
}
srcDir foreach (x => setProp("partest.srcdir", x))
val classpath = this.compilationPath getOrElse sys.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 sys.error("Provided classpath does not contain a Scala library.")
-
- val scalaReflect = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-reflect.jar" => true
- case "reflect" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala reflection library.")
-
- val scalaCompiler = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-compiler.jar" => true
- case "compiler" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala compiler.")
-
- val scalaPartest = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-partest.jar" => true
- case "partest" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala partest.")
-
- val scalaActors = {
- (classpath.list map { fs => new File(fs) }) find { f =>
- f.getName match {
- case "scala-actors.jar" => true
- case "actors" if (f.getParentFile.getName == "classes") => true
- case _ => false
- }
- }
- } getOrElse sys.error("Provided classpath does not contain a Scala actors.")
+ val cpfiles = classpath.list map { fs => new File(fs) } toList
+ def findCp(name: String) = cpfiles find (f =>
+ (f.getName == s"scala-$name.jar")
+ || (f.absolutePathSegments endsWith Seq("classes", name))
+ ) getOrElse sys.error(s"Provided classpath does not contain a Scala $name element.")
+
+ val scalaLibrary = findCp("library")
+ val scalaReflect = findCp("reflect")
+ val scalaCompiler = findCp("compiler")
+ val scalaPartest = findCp("partest")
+ val scalaActors = findCp("actors")
def scalacArgsFlat: Option[Seq[String]] = scalacArgs map (_ flatMap { a =>
val parts = a.getParts
- if(parts eq null) Seq[String]() else parts.toSeq
+ if (parts eq null) Nil else parts.toSeq
})
val antRunner = new scala.tools.partest.nest.AntRunner
val antFileManager = antRunner.fileManager
- // this is a workaround for https://issues.scala-lang.org/browse/SI-5433
- // when that bug is fixed, this paragraph of code can be safely removed
- // we hack into the classloader that will become parent classloader for scalac
- // this way we ensure that reflective macro lookup will pick correct Code.lift
- val loader = getClass.getClassLoader.asInstanceOf[org.apache.tools.ant.AntClassLoader]
- val path = new org.apache.tools.ant.types.Path(getProject())
- val newClassPath = ClassPath.join(nest.PathSettings.srcCodeLib.toString, loader.getClasspath)
- path.setPath(newClassPath)
- loader.setClassPath(path)
-
- antFileManager.showDiff = showDiff
- antFileManager.showLog = showLog
+ // antFileManager.failed = runFailed
antFileManager.CLASSPATH = ClassPath.join(classpath.list: _*)
antFileManager.LATEST_LIB = scalaLibrary.getAbsolutePath
antFileManager.LATEST_REFLECT = scalaReflect.getAbsolutePath
@@ -347,53 +147,35 @@ class PartestTask extends Task with CompilationPathProperty {
javacmd foreach (x => antFileManager.JAVACMD = x.getAbsolutePath)
javaccmd foreach (x => antFileManager.JAVAC_CMD = x.getAbsolutePath)
scalacArgsFlat 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"),
- (getScalacheckFiles, "scalacheck", "Running scalacheck tests"),
- (getScriptFiles, "script", "Running script files"),
- (getShootoutFiles, "shootout", "Running shootout tests"),
- (getScalapFiles, "scalap", "Running scalap tests"),
- (getSpecializedFiles, "specialized", "Running specialized files"),
- (getInstrumentedFiles, "instrumented", "Running instrumented files"),
- (getPresentationFiles, "presentation", "Running presentation compiler test files"),
- (getAntFiles, "ant", "Running ant task tests")
- )
-
- def runSet(set: TFSet): (Int, Int, Iterable[String]) = {
- val (files, name, msg) = set
+
+ def runSet(kind: String, files: Array[File]): (Int, Int, List[String]) = {
if (files.isEmpty) (0, 0, List())
else {
- log(msg)
- val results: Iterable[(String, TestState)] = antRunner.reflectiveRunTestsForFiles(files, name)
- val (succs, fails) = resultsToStatistics(results)
+ log(s"Running ${files.length} tests in '$kind' at $now")
+ // log(s"Tests: ${files.toList}")
+ val results = antRunner.reflectiveRunTestsForFiles(files, kind)
+ val (passed, failed) = results partition (_.isOk)
+ val numPassed = passed.size
+ val numFailed = failed.size
+ def failedMessages = failed map (_.longStatus)
- val failed: Iterable[String] = results collect {
- case (path, TestState.Fail) => path + " [FAILED]"
- case (path, TestState.Timeout) => path + " [TIMOUT]"
- }
+ log(s"Completed '$kind' at $now")
// 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)
+ val report = testReport(kind, results, numPassed, numFailed)
+ scala.xml.XML.save(d.getAbsolutePath+"/"+kind+".xml", report)
}
- (succs, fails, failed)
+ (numPassed, numFailed, failedMessages)
}
}
- val _results = testFileSets map runSet
- val allSuccesses = _results map (_._1) sum
- val allFailures = _results map (_._2) sum
+ val _results = kinds map (k => runSet(k, TestKinds testsFor k map (_.jfile) toArray))
+ val allSuccesses = _results map (_._1) sum
+ val allFailures = _results map (_._2) sum
val allFailedPaths = _results flatMap (_._3)
def f = if (errorOnFailed && allFailures > 0) (sys error _) else log(_: String)
@@ -408,20 +190,17 @@ class PartestTask extends Task with CompilationPathProperty {
f(msg)
}
- private def oneResult(res: (String, TestState)) =
- <testcase name={res._1}>{
- res._2 match {
- case TestState.Ok => scala.xml.NodeSeq.Empty
- case TestState.Fail => <failure message="Test failed"/>
- case TestState.Timeout => <failure message="Test timed out"/>
- }
+ private def oneResult(res: TestState) =
+ <testcase name={res.testIdent}>{
+ if (res.isOk) scala.xml.NodeSeq.Empty
+ else <failure message="Test failed"/>
}</testcase>
- private def testReport(kind: String, results: Iterable[(String, TestState)], succs: Int, fails: Int) =
+ private def testReport(kind: String, results: Iterable[TestState], succs: Int, fails: Int) =
<testsuite name={kind} tests={(succs + fails).toString} failures={fails.toString}>
<properties/>
{
- results.map(oneResult(_))
+ results map oneResult
}
</testsuite>
}
View
67 src/partest/scala/tools/partest/TestKinds.scala
@@ -0,0 +1,67 @@
+package scala.tools
+package partest
+
+import nest.PathSettings.srcDir
+
+object TestKinds {
+ val standardKinds = "pos neg run jvm res buildmanager scalacheck scalap specialized instrumented presentation ant" split "\\s+" toList
+ val standardArgs = standardKinds map ("--" + _)
+
+ def denotesTestFile(p: Path) = p.isFile && p.hasExtension("scala", "res", "xml")
+ def denotesTestDir(p: Path) = kindOf(p) match {
+ case "res" => false
+ case _ => p.isDirectory && p.extension == ""
+ }
+ def denotesTestPath(p: Path) = denotesTestDir(p) || denotesTestFile(p)
+
+ // TODO
+ def isTestForPartest(p: Path) = (
+ (p.name == "intentional-failure.scala")
+ || (p.path contains "test-for-partest")
+ )
+
+ def kindOf(p: Path) = {
+ p.toAbsolute.segments takeRight 2 head
+
+ // (srcDir relativize p.toCanonical).segments match {
+ // case (".." :: "scaladoc" :: xs) => xs.head
+ // case xs => xs.head
+ // }
+ }
+ def logOf(p: Path) = {
+ p.parent / s"${p.stripExtension}-${kindOf(p)}.log"
+ // p.parent / s"${p.stripExtension}.log"
+ }
+
+ // true if a test path matches the --grep expression.
+ private def pathMatchesExpr(path: Path, expr: String) = {
+ // Matches the expression if any source file contains the expr,
+ // or if the checkfile contains it, or if the filename contains
+ // it (the last is case-insensitive.)
+ def matches(p: Path) = (
+ (p.path.toLowerCase contains expr.toLowerCase)
+ || (p.fileContents contains expr)
+ )
+ def candidates = {
+ (path changeExtension "check") +: {
+ if (path.isFile) List(path)
+ else path.toDirectory.deepList() filter (_.isJavaOrScala) toList
+ }
+ }
+
+ (candidates exists matches)
+ }
+
+ def groupedTests(paths: List[Path]): List[(String, List[Path])] =
+ (paths.distinct groupBy kindOf).toList sortBy (standardKinds indexOf _._1)
+
+ /** Includes tests for testing partest. */
+ private def allTestsForKind(kind: String): List[Path] =
+ (srcDir / kind toDirectory).list.toList filter denotesTestPath
+
+ def testsForPartest: List[Path] = standardKinds flatMap allTestsForKind filter isTestForPartest
+ def testsFor(kind: String): List[Path] = allTestsForKind(kind) filterNot isTestForPartest
+ def grepFor(expr: String): List[Path] = standardTests filter (t => pathMatchesExpr(t, expr))
+ def standardTests: List[Path] = standardKinds flatMap testsFor
+ def failedTests: List[Path] = standardTests filter (p => logOf(p).isFile)
+}
View
54 src/partest/scala/tools/partest/TestState.scala
@@ -0,0 +1,54 @@
+package scala.tools.partest
+
+import scala.tools.nsc.FatalError
+import scala.tools.nsc.util.stackTraceString
+
+sealed abstract class TestState {
+ def testFile: File
+ def what: String
+ def reason: String
+ def transcript: List[String]
+
+ def isOk = false
+ def isSkipped = false
+ def testIdent = testFile.testIdent
+ def transcriptString = transcript.mkString("\n")
+
+ def identAndReason = testIdent + reasonString
+ def status = s"$what - $identAndReason"
+ def longStatus = status + transcriptString
+ def reasonString = if (reason == "") "" else s" [$reason]"
+
+ override def toString = status
+}
+
+object TestState {
+ case class Uninitialized(testFile: File) extends TestState {
+ def what = "uninitialized"
+ def reason = what
+ def transcript = Nil
+ }
+ case class Pass(testFile: File) extends TestState {
+ final override def isOk = true
+ def what = "pass"
+ def transcript: List[String] = Nil
+ def reason = ""
+ }
+ case class Skip(testFile: File, reason: String) extends TestState {
+ override def isOk = true
+ final override def isSkipped = true
+ def transcript: List[String] = Nil
+ def what = "skip"
+ }
+ case class Fail(testFile: File, reason: String, transcript: List[String]) extends TestState {
+ def what = "fail"
+ }
+ case class Crash(testFile: File, caught: Throwable, transcript: List[String]) extends TestState {
+ def what = "crash"
+ def reason = s"caught $caught_s - ${caught.getMessage}"
+
+ private def caught_s = (caught.getClass.getName split '.').last
+ private def stack_s = stackTraceString(caught)
+ override def transcriptString = nljoin(super.transcriptString, caught_s)
+ }
+}
View
25 src/partest/scala/tools/partest/nest/AntRunner.scala
@@ -10,24 +10,21 @@
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 = _
- var LATEST_REFLECT: String = _
- var LATEST_COMP: String = _
- var LATEST_PARTEST: String = _
- var LATEST_ACTORS: String = _
- val testRootPath: String = "test"
- val testRootDir: Directory = Directory(testRootPath)
+ var JAVACMD: String = "java"
+ var JAVAC_CMD: String = "javac"
+ var CLASSPATH: String = _
+ var LATEST_LIB: String = _
+ var LATEST_REFLECT: String = _
+ var LATEST_COMP: String = _
+ var LATEST_PARTEST: String = _
+ var LATEST_ACTORS: String = _
+ val testRootPath: String = "test"
+ val testRootDir: Directory = Directory(testRootPath)
}
- def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String) =
+ def reflectiveRunTestsForFiles(kindFiles: Array[File], kind: String): List[TestState] =
runTestsForFiles(kindFiles.toList, kind)
}
View
182 src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -1,182 +0,0 @@
-/* NEST (New Scala Test)
- * Copyright 2007-2013 LAMP/EPFL
- * @author Philipp Haller
- */
-
-// $Id$
-
-package scala.tools.partest
-package nest
-
-import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError, io }
-import scala.reflect.io.{ Directory, File => SFile, FileOperationException }
-import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
-import scala.tools.nsc.util.{ ClassPath, FakePos }
-import scala.tools.nsc.Properties.{ setProp, propOrEmpty }
-import scala.tools.util.PathResolver
-import io.Path
-import java.io.{ File, BufferedReader, PrintWriter, FileReader, Writer, FileWriter, StringWriter }
-import File.pathSeparator
-
-sealed abstract class CompilationOutcome {
- def merge(other: CompilationOutcome): CompilationOutcome
- def isPositive = this eq CompileSuccess
- def isNegative = this eq CompileFailed
-}
-case object CompileSuccess extends CompilationOutcome {
- def merge(other: CompilationOutcome) = other
-}
-case object CompileFailed extends CompilationOutcome {
- def merge(other: CompilationOutcome) = if (other eq CompileSuccess) this else other
-}
-case object CompilerCrashed extends CompilationOutcome {
- def merge(other: CompilationOutcome) = this
-}
-
-class ExtConsoleReporter(settings: Settings, val writer: PrintWriter) extends ConsoleReporter(settings, Console.in, writer) {
- shortname = true
-}
-
-class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
- def this(cp: String) = this(cp, _ => ())
-
- nowarnings.value = false
- encoding.value = "UTF-8"
- classpath.value = cp
-}
-
-abstract class SimpleCompiler {
- def compile(out: Option[File], files: List[File], kind: String, log: File): CompilationOutcome
-}
-
-class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
- def newGlobal(settings: Settings, reporter: Reporter): Global =
- Global(settings, reporter)
-
- def newGlobal(settings: Settings, logWriter: FileWriter): Global =
- newGlobal(settings, new ExtConsoleReporter(settings, new PrintWriter(logWriter)))
-
- def newSettings(): TestSettings = new TestSettings(fileManager.LATEST_LIB)
- def newSettings(outdir: String): TestSettings = {
- val cp = ClassPath.join(fileManager.LATEST_LIB, outdir)
- val s = new TestSettings(cp)
- s.outdir.value = outdir
-
- s
- }
-
- implicit class Copier(f: SFile) {
- // But what if f is bigger than CHUNK?!
- def copyTo(dest: Path) {
- dest.toFile writeAll f.slurp
- }
- }
-
- // plugin path can be relative to test root, or cwd is out
- private def updatePluginPath(options: String, out: Option[File], srcdir: Directory): String = {
- val dir = fileManager.testRootDir
- def pathOrCwd(p: String) =
- if (p == "." && out.isDefined) {
- val plugxml = "scalac-plugin.xml"
- val pout = Path(out.get)
- val pd = (srcdir / plugxml).toFile
- if (pd.exists) pd copyTo (pout / plugxml)
- pout
- } else Path(p)
- def absolutize(path: String) = pathOrCwd(path) match {
- case x if x.isAbsolute => x.path
- case x => (dir / 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): CompilationOutcome = {
- val testSettings = out match {
- case Some(f) => newSettings(f.getAbsolutePath)
- case _ => newSettings()
- }
- val logWriter = new FileWriter(log)
-
- // this api has no notion of srcdir, so fake it
- val fstFile = SFile(files(0))
- val srcdir = fstFile.parent
-
- // check whether there is a ".flags" file
- def convertFlags(f: SFile) = updatePluginPath(f.slurp(), out, srcdir)
- val logFile = basename(log.getName)
- val flagsFileName = "%s.flags" format (logFile.substring(0, logFile.lastIndexOf("-")))
- val argString = (SFile(log).parent / flagsFileName) ifFile (convertFlags) getOrElse ""
-
- // slurp local flags (e.g., "A_1.flags")
- def isInGroup(num: Int) = fstFile.stripExtension endsWith ("_" + num)
- val inGroup = (1 to 9) flatMap (group => if (isInGroup(group)) List(group) else List())
- val localFlagsList = if (inGroup.nonEmpty) {
- val localArgString = (srcdir / (fstFile.stripExtension + ".flags")) ifFile (convertFlags) getOrElse ""
- localArgString.split(' ').toList.filter(_.length > 0)
- } else List()
-
- val allOpts = fileManager.SCALAC_OPTS.toList ::: argString.split(' ').toList.filter(_.length > 0) ::: localFlagsList
- val args = allOpts.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
- case "specialized" => SpecializedTestFile.apply
- case "instrumented" => InstrumentedTestFile.apply
- case "presentation" => PresentationTestFile.apply
- case "ant" => AntTestFile.apply
- }
- val test: TestFile = testFileFn(files.head, fileManager)
- if (!test.defineSettings(command.settings, out.isEmpty)) {
- testRep.error(FakePos("partest"), test.flags match {
- case Some(flags) => "bad flags: " + flags
- case _ => "bad settings: " + command.settings
- })
- }
-
- val toCompile = files map (_.getPath)
-
- try {
- NestUI.verbose("compiling "+toCompile)
- NestUI.verbose("with classpath: "+global.classPath.toString)
- NestUI.verbose("and java classpath: "+ propOrEmpty("java.class.path"))
- try {
- if (command.shouldStopWithInfo) logWriter append (command getInfoMessage global)
- else new global.Run compile toCompile
- } catch {
- case FatalError(msg) =>
- testRep.error(null, "fatal error: " + msg)
- return CompilerCrashed
- }
-
- testRep.printSummary()
- testRep.writer.close()
- }
- finally logWriter.close()
-
- if (testRep.hasErrors || command.shouldStopWithInfo) CompileFailed
- else CompileSuccess
- }
-}
-
-class CompileManager(val fileManager: FileManager) {
- private def newCompiler = new DirectCompiler(fileManager)
- def attemptCompile(outdir: Option[File], sources: List[File], kind: String, log: File): CompilationOutcome =
- newCompiler.compile(outdir, sources, kind, log)
-}
View
33 src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -3,20 +3,15 @@
* @author Philipp Haller
*/
-// $Id$
+
package scala.tools.partest
package nest
-import java.io.{ File, FilenameFilter, IOException, StringWriter }
+import java.io.{ FilenameFilter, IOException }
import java.net.URI
import scala.util.Properties.{ propOrElse, scalaCmd, scalacCmd }
-import scala.tools.util.PathResolver
import scala.tools.nsc.{ io, util }
-import util.{ ClassPath }
-import io.{ Path, Directory }
-import File.pathSeparator
-import ClassPath.{ join }
import PathResolver.{ Environment, Defaults }
class ConsoleFileManager extends FileManager {
@@ -55,7 +50,7 @@ class ConsoleFileManager extends FileManager {
var JAVAC_CMD = PartestDefaults.javacCmd
- NestUI.verbose("CLASSPATH: "+CLASSPATH)
+ vlog("CLASSPATH: "+CLASSPATH)
if (!srcDir.isDirectory) {
NestUI.failure("Source directory \"" + srcDir.path + "\" not found")
@@ -70,14 +65,14 @@ class ConsoleFileManager extends FileManager {
}
def findLatest() {
- NestUI.verbose("test parent: "+testParent)
+ vlog("test parent: "+testParent)
- def prefixFileWith(parent: File, relPath: String) = (io.File(parent) / relPath).toCanonical
+ def prefixFileWith(parent: File, relPath: String) = (SFile(parent) / relPath).toCanonical
def prefixFile(relPath: String) = (testParent / relPath).toCanonical
if (!testClasses.isEmpty) {
testClassesDir = Path(testClasses.get).toCanonical.toDirectory
- NestUI.verbose("Running with classes in "+testClassesDir)
+ vlog("Running with classes in "+testClassesDir)
latestLibFile = testClassesDir / "library"
latestActorsFile = testClassesDir / "library" / "actors"
@@ -87,7 +82,7 @@ class ConsoleFileManager extends FileManager {
}
else if (testBuild.isDefined) {
val dir = Path(testBuild.get)
- NestUI.verbose("Running on "+dir)
+ vlog("Running on "+dir)
latestLibFile = dir / "lib/scala-library.jar"
latestActorsFile = dir / "lib/scala-actors.jar"
latestReflectFile = dir / "lib/scala-reflect.jar"
@@ -96,7 +91,7 @@ class ConsoleFileManager extends FileManager {
}
else {
def setupQuick() {
- NestUI.verbose("Running build/quick")
+ vlog("Running build/quick")
latestLibFile = prefixFile("build/quick/classes/library")
latestActorsFile = prefixFile("build/quick/classes/library/actors")
latestReflectFile = prefixFile("build/quick/classes/reflect")
@@ -105,7 +100,7 @@ class ConsoleFileManager extends FileManager {
}
def setupInst() {
- NestUI.verbose("Running dist (installed)")
+ vlog("Running dist (installed)")
val p = testParent.getParentFile
latestLibFile = prefixFileWith(p, "lib/scala-library.jar")
latestActorsFile = prefixFileWith(p, "lib/scala-actors.jar")
@@ -115,7 +110,7 @@ class ConsoleFileManager extends FileManager {
}
def setupDist() {
- NestUI.verbose("Running dists/latest")
+ vlog("Running dists/latest")
latestLibFile = prefixFile("dists/latest/lib/scala-library.jar")
latestActorsFile = prefixFile("dists/latest/lib/scala-actors.jar")
latestReflectFile = prefixFile("dists/latest/lib/scala-reflect.jar")
@@ -124,7 +119,7 @@ class ConsoleFileManager extends FileManager {
}
def setupPack() {
- NestUI.verbose("Running build/pack")
+ vlog("Running build/pack")
latestLibFile = prefixFile("build/pack/lib/scala-library.jar")
latestActorsFile = prefixFile("build/pack/lib/scala-actors.jar")
latestReflectFile = prefixFile("build/pack/lib/scala-reflect.jar")
@@ -170,11 +165,13 @@ class ConsoleFileManager extends FileManager {
var latestReflectFile: File = _
var latestCompFile: File = _
var latestPartestFile: File = _
- def latestScalapFile: File = (latestLibFile.parent / "scalap.jar").jfile
+ //def latestScalapFile: File = (latestLibFile.parent / "scalap.jar").jfile
+ //def latestScalapFile: File = new File(latestLibFile.getParentFile, "scalap.jar")
var testClassesDir: Directory = _
// initialize above fields
findLatest()
+ /*
def getFiles(kind: String, cond: Path => Boolean): List[File] = {
def ignoreDir(p: Path) = List("svn", "obj") exists (p hasExtension _)
@@ -187,4 +184,6 @@ class ConsoleFileManager extends FileManager {
( if (failed) files filter (x => logFileExists(x, kind)) else files ) map (_.jfile)
}
+ */
+ var latestFjbgFile: File = _
}
View
321 src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -3,83 +3,110 @@
* @author Philipp Haller
*/
-// $Id$
-
-package scala.tools.partest
+package scala.tools
+package partest
package nest
-import java.io.{File, PrintStream, FileOutputStream, BufferedReader,
- InputStreamReader, StringWriter, PrintWriter}
import utils.Properties._
import scala.tools.nsc.Properties.{ versionMsg, setProp }
import scala.tools.nsc.util.CommandLineParser
-import scala.tools.nsc.io
-import io.{ Path }
import scala.collection.{ mutable, immutable }
+import PathSettings.srcDir
+import TestKinds._
class ConsoleRunner extends DirectRunner {
- import PathSettings.{ srcDir, testRoot }
-
- case class TestSet(kind: String, filter: Path => Boolean, msg: String)
- private def stdFilter(p: Path) = p.isDirectory || (p hasExtension "scala")
- private def antFilter(p: Path) = p.isFile && (p endsWith "build.xml")
-
- val testSets = {
- List(
- TestSet("pos", stdFilter, "Testing compiler (on files whose compilation should succeed)"),
- TestSet("neg", stdFilter, "Testing compiler (on files whose compilation should fail)"),
- TestSet("run", stdFilter, "Testing interpreter and backend"),
- TestSet("jvm", stdFilter, "Testing JVM backend"),
- TestSet("res", x => x.isFile && (x hasExtension "res"), "Testing resident compiler"),
- TestSet("shootout", stdFilter, "Testing shootout tests"),
- TestSet("script", stdFilter, "Testing script tests"),
- TestSet("scalacheck", stdFilter, "Testing ScalaCheck tests"),
- TestSet("scalap", _.isDirectory, "Run scalap decompiler tests"),
- TestSet("specialized", stdFilter, "Testing specialized tests"),
- TestSet("instrumented", stdFilter, "Testing instrumented tests"),
- TestSet("presentation", _.isDirectory, "Testing presentation compiler tests."),
- TestSet("ant", antFilter, "Run Ant task tests.")
- )
- }
+ import NestUI._
+ import NestUI.color._
+
+ // So we can ctrl-C a test run and still hear all
+ // the buffered failure info.
+ scala.sys addShutdownHook issueSummaryReport()
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
+ private var totalTests = 0
+ private val passedTests = mutable.ListBuffer[TestState]()
+ private val failedTests = mutable.ListBuffer[TestState]()
+
+ def comment(s: String) = echo(magenta("# " + s))
+ def levyJudgment() = {
+ if (totalTests == 0) echoMixed("No tests to run.")
+ else if (elapsedMillis == 0) echoMixed("Test Run ABORTED")
+ else if (isSuccess) echoPassed("Test Run PASSED")
+ else echoFailed("Test Run FAILED")
+ }
+
+ def passFailString(passed: Int, failed: Int, skipped: Int): String = {
+ val total = passed + failed + skipped
+ val isSuccess = failed == 0
+ def p0 = s"$passed/$total"
+ def p = ( if (isSuccess) bold(green(p0)) else p0 ) + " passed"
+ def f = if (failed == 0) "" else bold(red("" + failed)) + " failed"
+ def s = if (skipped == 0) "" else bold(yellow("" + skipped)) + " skipped"
+
+ oempty(p, f, s) mkString ", "
+ }
+
+ private var summarizing = false
+ private var elapsedMillis = 0L
+ private var expectedFailures = 0
+ private def isSuccess = failedTests.size == expectedFailures
+
+ def issueSummaryReport() {
+ // Don't run twice
+ if (!summarizing) {
+ summarizing = true
+
+ val passed0 = passedTests.toList
+ val failed0 = failedTests.toList
+ val passed = passed0.size
+ val failed = failed0.size
+ val skipped = totalTests - (passed + failed)
+ val passFail = passFailString(passed, failed, skipped)
+ val elapsed = if (elapsedMillis > 0) " (elapsed time: " + elapsedString(elapsedMillis) + ")" else ""
+ val message = passFail + elapsed
+
+ if (failed0.nonEmpty) {
+ echo(bold(cyan("##### Transcripts from failed tests #####\n")))
+ failed0 foreach { state =>
+ comment("partest " + state.testFile)
+ echo(state.transcriptString + "\n")
+ }
+ }
- private def printVersion() { NestUI outline (versionMsg + "\n") }
+ echo(message)
+ levyJudgment()
+ }
+ }
private val unaryArgs = List(
- "--pack", "--all", "--verbose", "--show-diff", "--show-log",
+ "--pack", "--all",
+ "--terse", "--verbose", "--show-diff", "--show-log", "--self-test",
"--failed", "--update-check", "--version", "--ansi", "--debug", "--help"
- ) ::: testSetArgs
+ ) ::: standardArgs
private val binaryArgs = List(
"--grep", "--srcpath", "--buildpath", "--classpath"
)
- // true if a test path matches the --grep expression.
- private def pathMatchesExpr(path: Path, expr: String) = {
- def pred(p: Path) = file2String(p.toFile) contains expr
- def greppable(f: Path) = f.isFile && (f hasExtension ("scala", "java"))
- def any(d: Path) = d.toDirectory.deepList() exists (f => greppable(f) && pred(f))
-
- (path.isFile && pred(path)) ||
- (path.isDirectory && any(path)) ||
- (pred(path changeExtension "check"))
- }
-
def main(argstr: String) {
val parsed = CommandLineParser(argstr) withUnaryArgs unaryArgs withBinaryArgs binaryArgs
- val args = onlyValidTestPaths(parsed.residualArgs)
- /* Early return on no args, version, or invalid args */
- if (argstr == "") return NestUI.usage()
- if (parsed isSet "--version") return printVersion
- if (parsed isSet "--help") return NestUI.usage()
+ if (parsed isSet "--debug") NestUI.setDebug()
+ if (parsed isSet "--verbose") NestUI.setVerbose()
+ if (parsed isSet "--terse") NestUI.setTerse()
+
+ // Early return on no args, version, or invalid args
+ if (parsed isSet "--version") return echo(versionMsg)
+ if ((argstr == "") || (parsed isSet "--help")) return NestUI.usage()
+
+ val (individualTests, invalid) = parsed.residualArgs map (p => Path(p)) partition denotesTestPath
+ if (invalid.nonEmpty) {
+ if (isPartestVerbose)
+ invalid foreach (p => echoWarning(s"Discarding invalid test path " + p))
+ else if (!isPartestTerse)
+ echoWarning(s"Discarding ${invalid.size} invalid test paths")
+ }
parsed get "--srcpath" foreach (x => setProp("partest.srcdir", x))
@@ -89,144 +116,102 @@ class ConsoleRunner extends DirectRunner {
else if (parsed isSet "--pack") new ConsoleFileManager("build/pack")
else new ConsoleFileManager // auto detection, see ConsoleFileManager.findLatest
- NestUI._verbose = parsed isSet "--verbose"
- fileManager.showDiff = true
- // parsed isSet "--show-diff"
fileManager.updateCheck = parsed isSet "--update-check"
- 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")
+ val partestTests = (
+ if (parsed isSet "--self-test") TestKinds.testsForPartest
+ else Nil
+ )
- 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
- }
- }
+ val grepExpr = parsed get "--grep" getOrElse ""
// If --grep is given we suck in every file it matches.
-
- val grepOption = parsed get "--grep"
- val grepPaths = grepOption.toList flatMap { expr =>
- val subjectDirs = testSetKinds map (srcDir / _ toDirectory)
- val testPaths = subjectDirs flatMap (_.list filter stdFilter)
- val paths = testPaths filter (p => pathMatchesExpr(p, expr))
-
+ var grepMessage = ""
+ val greppedTests = if (grepExpr == "") Nil else {
+ val paths = grepFor(grepExpr)
if (paths.isEmpty)
- NestUI.failure("--grep string '%s' matched no tests." format expr)
+ echoWarning(s"grep string '$grepExpr' matched no tests.\n")
- paths map (_.jfile)
+ paths.sortBy(_.toString)
}
- val grepMessage = grepOption map (x => "Argument '%s' matched %d test(s)".format(x, grepPaths.size)) getOrElse ""
-
- grepPaths foreach addTestFile
- 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 isRerun = parsed isSet "--failed"
+ val rerunTests = if (isRerun) TestKinds.failedTests else Nil
+ def miscTests = partestTests ++ individualTests ++ greppedTests ++ rerunTests
+ val givenKinds = standardArgs filter parsed.isSet
+ val kinds = (
+ if (parsed isSet "--all") standardKinds
+ else if (givenKinds.nonEmpty) givenKinds map (_ stripPrefix "--")
+ else if (invalid.isEmpty && miscTests.isEmpty && !isRerun) standardKinds // If no kinds, --grep, or individual tests were given, assume --all
+ else Nil
+ )
+ val kindsTests = kinds flatMap testsFor
val dir =
if (fileManager.testClasses.isDefined) fileManager.testClassesDir
else fileManager.testBuildFile getOrElse {
fileManager.latestCompFile.getParentFile.getParentFile.getAbsoluteFile
}
- 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 verbose (x + "\n"))
-
- NestUI.verbose("available processors: " + Runtime.getRuntime().availableProcessors())
-
- // Dragged down here so it isn't buried under the banner.
- if (grepMessage != "")
- NestUI.normal(grepMessage + "\n")
-
- val ((successes, failures), elapsedMillis) = timed(testCheckAll(enabledTestSets))
- val total = successes + failures
-
- val elapsedSecs = elapsedMillis/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)
+ def testContributors = {
+ List(
+ if (partestTests.isEmpty) "" else "partest self-tests",
+ if (rerunTests.isEmpty) "" else "previously failed tests",
+ if (kindsTests.isEmpty) "" else s"${kinds.size} named test categories",
+ if (greppedTests.isEmpty) "" else s"${greppedTests.size} tests matching '$grepExpr'",
+ if (individualTests.isEmpty) "" else "specified tests"
+ ) filterNot (_ == "") mkString ", "
}
- 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")
+ def banner = {
+ val vmBin = javaHome + fileSeparator + "bin"
+ val vmName = "%s (build %s, %s)".format(javaVmName, javaVmVersion, javaVmInfo)
+ val vmOpts = fileManager.JAVA_OPTS
+
+ s"""|Scala compiler classes in: $dir
+ |Scala version is: $versionMsg
+ |Scalac options are: ${fileManager.SCALAC_OPTS mkString " "}
+ |Java binaries in: $vmBin
+ |Java runtime is: $vmName
+ |Java options are: $vmOpts
+ |Source directory is: $srcDir
+ |Available processors: ${Runtime.getRuntime().availableProcessors()}
+ |Java Classpath: ${sys.props("java.class.path")}
+ """.stripMargin
+ }
- System exit ( if (failures == errors) 0 else 1 )
- }
+ chatty(banner)
- def runTests(testSet: TestSet): (Int, Int) = {
- val TestSet(kind, filter, msg) = testSet
+ val allTests = (miscTests ++ (kinds flatMap testsFor)).distinct
+ val grouped = (allTests groupBy kindOf).toList sortBy (x => standardKinds indexOf x._1)
- 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))
+ totalTests = allTests.size
+ expectedFailures = propOrNone("partest.errors") match {
+ case Some(num) => num.toInt
+ case _ => 0
}
- }
-
- /**
- * @return (success count, failure count)
- */
- def testCheckAll(enabledSets: List[TestSet]): (Int, Int) = {
- def kindOf(f: File) = {
- (srcDir relativize Path(f).toCanonical).segments match {
- case (".." :: "scaladoc" :: xs) => xs.head
- case xs => xs.head
+ val expectedFailureMessage = if (expectedFailures == 0) "" else s" (expecting $expectedFailures to fail)"
+ echo(s"Selected $totalTests tests drawn from $testContributors$expectedFailureMessage\n")
+
+ val (_, millis) = timed {
+ for ((kind, paths) <- grouped) {
+ val num = paths.size
+ val ss = if (num == 1) "" else "s"
+ comment(s"starting $num test$ss in $kind")
+ val results = runTestsForFiles(paths map (_.jfile), kind)
+ val (passed, failed) = results partition (_.isOk)
+
+ passedTests ++= passed
+ failedTests ++= failed
+ if (failed.nonEmpty) {
+ comment(passFailString(passed.size, failed.size, 0) + " in " + kind)
+ }
+ echo("")
}
}
-
- val (valid, invalid) = testFiles partition (x => testSetKinds contains kindOf(x))
- invalid foreach (x => NestUI.failure(
- "Invalid test file '%s', skipping.\n".format(x) +
- "(Test kind '%s' not in known set '%s')".format(kindOf(x), testSetKinds))
- )
-
- val grouped = (valid groupBy kindOf).toList sortBy (x => testSetKinds indexOf x._1)
- val runTestsFileLists =
- for ((kind, files) <- grouped) yield {
- NestUI.outline("\nTesting individual files\n")
- resultsToStatistics(runTestsForFiles(files, kind))
- }
-
- if (enabledSets.nonEmpty)
- NestUI.verbose("Run sets: "+enabledSets)
-
- val results = runTestsFileLists ::: (enabledSets map runTests)
-
- (results map (_._1) sum, results map (_._2) sum)
+ this.elapsedMillis = millis
+ issueSummaryReport()
+ System exit ( if (isSuccess) 0 else 1 )
}
}
View
105 src/partest/scala/tools/partest/nest/DirectCompiler.scala
@@ -0,0 +1,105 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Philipp Haller
+ */
+
+package scala.tools.partest
+package nest
+
+import scala.tools.nsc.{ Global, Settings, CompilerCommand, FatalError }
+import scala.tools.nsc.reporters.{ Reporter, ConsoleReporter }
+import scala.tools.nsc.util.{ FakePos, stackTraceString }
+import scala.tools.nsc.Properties.{ setProp, propOrEmpty }
+import scala.reflect.io.AbstractFile
+import scala.reflect.internal.util.Position
+import java.io.{ BufferedReader, PrintWriter, FileReader, Writer, FileWriter }
+
+class ExtConsoleReporter(settings: Settings, val writer: PrintWriter) extends ConsoleReporter(settings, Console.in, writer) {
+ shortname = true
+ // override def error(pos: Position, msg: String): Unit
+}
+
+class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
+ def this(cp: String) = this(cp, _ => ())
+
+ nowarnings.value = false
+ encoding.value = "UTF-8"
+ classpath.value = cp
+}
+
+class PartestGlobal(settings: Settings, reporter: Reporter) extends Global(settings, reporter) {
+ // override def abort(msg: String): Nothing
+ // override def globalError(msg: String): Unit
+ // override def supplementErrorMessage(msg: String): String
+}
+class DirectCompiler(val fileManager: FileManager) {
+ def newGlobal(settings: Settings, reporter: Reporter): PartestGlobal =
+ new PartestGlobal(settings, reporter)
+
+ def newGlobal(settings: Settings, logWriter: FileWriter): Global =
+ newGlobal(settings, new ExtConsoleReporter(settings, new PrintWriter(logWriter)))
+
+ def newSettings(): TestSettings = new TestSettings(fileManager.LATEST_LIB)
+ def newSettings(outdir: String): TestSettings = {
+ val cp = ClassPath.join(fileManager.LATEST_LIB, outdir)
+ val s = new TestSettings(cp)
+ s.outdir.value = outdir
+ s
+ }
+
+ def compile(runner: Runner, opts0: List[String], sources: List[File]): TestState = {
+ import runner._
+
+ val testSettings = new TestSettings(ClassPath.join(fileManager.LATEST_LIB, outDir.getPath))
+ val logWriter = new FileWriter(logFile)
+ val srcDir = if (testFile.isDirectory) testFile else Path(testFile).parent.jfile
+ val opts = fileManager.updatePluginPath(opts0, AbstractFile getDirectory outDir, AbstractFile getDirectory srcDir)
+ val command = new CompilerCommand(opts, testSettings)
+ val global = newGlobal(testSettings, logWriter)
+ val reporter = global.reporter.asInstanceOf[ExtConsoleReporter]
+ def errorCount = reporter.ERROR.count
+
+ def defineSettings(s: Settings) = {
+ s.outputDirs setSingleOutput outDir.getPath
+ // adding codelib.jar to the classpath
+ // codelib provides the possibility to override standard reify
+ // this shields the massive amount of reification tests from changes in the API
+ prependToClasspaths(s, codelib)
+ s.classpath append fileManager.CLASSPATH // adding this why?
+
+ // add the instrumented library version to classpath
+ if (kind == "specialized")
+ prependToClasspaths(s, speclib)
+
+ // check that option processing succeeded
+ opts0.isEmpty || command.ok
+ }
+
+ if (!defineSettings(testSettings))
+ if (opts0.isEmpty)
+ reporter.error(null, s"bad settings: $testSettings")
+ else
+ reporter.error(null, opts0.mkString("bad options: ", space, ""))
+
+ def ids = sources.map(_.testIdent) mkString space
+ vlog(s"% scalac $ids")
+
+ def execCompile() =
+ if (command.shouldStopWithInfo) {
+ logWriter append (command getInfoMessage global)
+ runner genFail "compilation stopped with info"
+ } else {
+ new global.Run compile sources.map(_.getPath)
+ if (!reporter.hasErrors) runner.genPass()
+ else {
+ reporter.printSummary()
+ reporter.writer.close()
+ runner.genFail(s"compilation failed with $errorCount errors")
+ }
+ }
+
+ try { execCompile() }
+ catch { case t: Throwable => reporter.error(null, t.getMessage) ; runner.genCrash(t) }
+ finally { logWriter.close() }
+ }
+}
View
52 src/partest/scala/tools/partest/nest/DirectRunner.scala
@@ -3,14 +3,12 @@
* @author Philipp Haller
*/
-// $Id$
-
package scala.tools.partest
package nest
import java.io.File
import scala.util.Properties.setProp
-import scala.tools.nsc.util.ScalaClassLoader
+import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
import scala.tools.nsc.io.Path
import scala.collection.{ mutable, immutable }
import java.util.concurrent._
@@ -22,41 +20,33 @@ trait DirectRunner {
import PartestDefaults.numThreads
- def denotesTestFile(arg: String) = Path(arg).hasExtension("scala", "res", "xml")
- def denotesTestDir(arg: String) = Path(arg).ifDirectory(_.files.nonEmpty) exists (x => x)
- def denotesTestPath(arg: String) = denotesTestDir(arg) || denotesTestFile(arg)
-
- /** No duplicate, no empty directories, don't mess with this unless
- * you like partest hangs.
- */
- def onlyValidTestPaths[T](args: List[T]): List[T] = {
- args.distinct filter (arg => denotesTestPath("" + arg) || {
- NestUI.warning("Discarding invalid test path '%s'\n" format arg)
- false
- })
- }
- def runTestsForFiles(_kindFiles: List[File], kind: String): immutable.Map[String, TestState] = {
- System.setProperty("line.separator", "\n")
+ Thread.setDefaultUncaughtExceptionHandler(
+ new Thread.UncaughtExceptionHandler {
+ def uncaughtException(thread: Thread, t: Throwable) {
+ val t1 = Exceptional unwrap t
+ System.err.println(s"Uncaught exception on thread $thread: $t1")
+ t1.printStackTrace()
+ }
+ }
+ )
+ def runTestsForFiles(kindFiles: List[File], kind: String): List[TestState] = {
- val allUrls = PathSettings.scalaCheck.toURL :: fileManager.latestUrls
- val scalaCheckParentClassLoader = ScalaClassLoader.fromURLs(allUrls)
- val kindFiles = onlyValidTestPaths(_kindFiles)
- val pool = Executors.newFixedThreadPool(numThreads)
- val manager = new RunnerManager(kind, fileManager, TestRunParams(scalaCheckParentClassLoader))
- val futures = kindFiles map (f => (f, pool submit callable(manager runTest f))) toMap
+ NestUI.resetTestNumber()
- pool.shutdown()
+ val allUrls = PathSettings.scalaCheck.toURL :: fileManager.latestUrls
+ val parentClassLoader = ScalaClassLoader fromURLs allUrls
+ val pool = Executors newFixedThreadPool numThreads
+ val manager = new RunnerManager(kind, fileManager, TestRunParams(parentClassLoader))
+ val futures = kindFiles map (f => pool submit callable(manager runTest f))
+ pool.shutdown()
try if (!pool.awaitTermination(4, TimeUnit.HOURS))
- NestUI.warning("Thread pool timeout elapsed before all tests were complete!")
+ NestUI warning "Thread pool timeout elapsed before all tests were complete!"
catch { case t: InterruptedException =>
- NestUI.warning("Thread pool was interrupted")
+ NestUI warning "Thread pool was interrupted"
t.printStackTrace()
}
- for ((file, future) <- futures) yield {
- val state = if (future.isCancelled) TestState.Timeout else future.get
- (file.getAbsolutePath, state)
- }
+ futures map (_.get)
}
}
View
47 src/partest/scala/tools/partest/nest/FileManager.scala
@@ -12,7 +12,7 @@ import java.io.{File, FilenameFilter, IOException, StringWriter,
FileInputStream, FileOutputStream, BufferedReader,
FileReader, PrintWriter, FileWriter}
import java.net.URI
-import scala.tools.nsc.io.{ Path, Directory, File => SFile }
+import scala.reflect.io.AbstractFile
import scala.collection.mutable
trait FileUtil {
@@ -62,16 +62,19 @@ trait FileManager extends FileUtil {
var LATEST_ACTORS: String
protected def relativeToLibrary(what: String): String = {
- if (LATEST_LIB endsWith ".jar") {
- (SFile(LATEST_LIB).parent / s"scala-$what.jar").toAbsolute.path
- }
- else {
+ def jarname = if (what startsWith "scala") s"$what.jar" else s"scala-$what.jar"
+ if (LATEST_LIB endsWith ".jar")
+ (SFile(LATEST_LIB).parent / jarname).toAbsolute.path
+ else
(SFile(LATEST_LIB).parent.parent / "classes" / what).toAbsolute.path
- }
}
def latestScaladoc = relativeToLibrary("scaladoc")
def latestInteractive = relativeToLibrary("interactive")
- def latestPaths = List(LATEST_LIB, LATEST_REFLECT, LATEST_COMP, LATEST_PARTEST, LATEST_ACTORS, latestScaladoc, latestInteractive)
+ def latestScalapFile = relativeToLibrary("scalap")
+ def latestPaths = List(
+ LATEST_LIB, LATEST_REFLECT, LATEST_COMP, LATEST_PARTEST, LATEST_ACTORS,
+ latestScalapFile, latestScaladoc, latestInteractive
+ )
def latestFiles = latestPaths map (p => new java.io.File(p))
def latestUrls = latestFiles map (_.toURI.toURL)
@@ -128,4 +131,34 @@ trait FileManager extends FileUtil {
f.printlnAll(f.lines.toList map replace: _*)
}
+
+ /** Massage args to merge plugins and fix paths.
+ * Plugin path can be relative to test root, or cwd is out.
+ * While we're at it, mix in the baseline options, too.
+ * That's how ant passes in the plugins dir.
+ */
+ def updatePluginPath(args: List[String], out: AbstractFile, srcdir: AbstractFile): List[String] = {
+ val dir = testRootDir
+ // The given path, or the output dir if ".", or a temp dir if output is virtual (since plugin loading doesn't like virtual)
+ def pathOrCwd(p: String) =
+ if (p == ".") {
+ val plugxml = "scalac-plugin.xml"
+ val pout = if (out.isVirtual) Directory.makeTemp() else Path(out.path)
+ val srcpath = Path(srcdir.path)
+ val pd = (srcpath / plugxml).toFile
+ if (pd.exists) pd copyTo (pout / plugxml)
+ pout
+ } else Path(p)
+ def absolutize(path: String) = pathOrCwd(path) match {
+ case x if x.isAbsolute => x.path
+ case x => (dir / x).toAbsolute.path
+ }
+
+ val xprefix = "-Xplugin:"
+ val (xplugs, others) = args partition (_ startsWith xprefix)
+ val Xplugin = if (xplugs.isEmpty) Nil else List(xprefix +
+ (xplugs map (_ stripPrefix xprefix) flatMap (_ split pathSeparator) map absolutize mkString pathSeparator)
+ )
+ SCALAC_OPTS.toList ::: others ::: Xplugin
+ }
}
View
111 src/partest/scala/tools/partest/nest/NestUI.scala
@@ -3,14 +3,37 @@
* @author Philipp Haller
*/
-// $Id$
-
package scala.tools.partest
package nest
import java.io.PrintWriter
+class Colors(enabled: => Boolean) {
+ import Console._
+
+ val bold = colored(BOLD)
+ val yellow = colored(YELLOW)
+ val green = colored(GREEN)
+ val blue = colored(BLUE)
+ val red = colored(RED)
+ val red_b = colored(RED_B)
+ val green_b = colored(GREEN_B)
+ val cyan = colored(CYAN)
+ val magenta = colored(MAGENTA)
+
+ private def colored(code: String): String => String =
+ s => if (enabled) code + s + RESET else s
+}
+
object NestUI {
+ private val testNum = new java.util.concurrent.atomic.AtomicInteger(1)
+ // @volatile private var testNumber = 1
+ private def testNumber = "%3d" format testNum.getAndIncrement()
+ def resetTestNumber() = testNum set 1
+
+ var colorEnabled = sys.props contains "partest.colors"
+ val color = new Colors(colorEnabled)
+ import color._
val NONE = 0
val SOME = 1
@@ -22,11 +45,57 @@ object NestUI {
private var _warning = ""
private var _default = ""
+ private var dotCount = 0
+ private val DotWidth = 72
+
+ def leftFlush() {
+ if (dotCount != 0) {
+ normal("\n")
+ dotCount = 0
+ }
+ }
+
+ def statusLine(state: TestState) = {
+ import state._
+ val word = bold(
+ if (isSkipped) yellow("--")
+ else if (isOk) green("ok")
+ else red("!!")
+ )
+ word + f" $testNumber%3s - $testIdent%-40s$reasonString"
+ }
+
+ def reportTest(state: TestState) = {
+ if (isTerse && state.isOk) {
+ if (dotCount >= DotWidth) {
+ outline("\n.")
+ dotCount = 1
+ }
+ else {
+ outline(".")
+ dotCount += 1
+ }
+ }
+ else echo(statusLine(state))
+ }
+
+ def echo(message: String): Unit = synchronized {
+ leftFlush()
+ print(message + "\n")
+ }
+ def chatty(msg: String) = if (isVerbose) echo(msg)
+
+ def echoSkipped(msg: String) = echo(yellow(msg))
+ def echoPassed(msg: String) = echo(bold(green(msg)))
+ def echoFailed(msg: String) = echo(bold(red(msg)))
+ def echoMixed(msg: String) = echo(bold(yellow(msg)))
+ def echoWarning(msg: String) = echo(bold(red(msg)))
+
def initialize(number: Int) = number match {
case MANY =>
_outline = Console.BOLD + Console.BLACK
_success = Console.BOLD + Console.GREEN
- _failure = Console.BOLD + Console.RED
+ _failure = Console.BOLD + Console.RED
_warning = Console.BOLD + Console.YELLOW
_default = Console.RESET
case SOME =>
@@ -61,10 +130,7 @@ object NestUI {
}
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("Usage: NestRunner [options] [test test ...]")
println
println(" Test categories:")
println(" --all run all tests")
@@ -74,16 +140,12 @@ object NestUI {
println(" --jvm run JVM backend tests")
println(" --res run resident compiler tests")
println(" --scalacheck run ScalaCheck tests")
- println(" --script run script runner tests")
- println(" --shootout run shootout tests")
println(" --instrumented run instrumented tests")
println(" --presentation run presentation compiler tests")
- println(" --grep <expr> run all tests whose source file contains <expr>")
println
println(" Other options:")
println(" --pack pick compiler/reflect/library in build/pack, and run all tests")
- println(" --show-log show log")
- println(" --show-diff show diff between log and check file")
+ println(" --grep <expr> run all tests whose source file contains <expr>")
println(" --failed run only those tests that failed during the last run")
println(" --update-check instead of failing tests with output change, update checkfile. (Use with care!)")
println(" --verbose show progress information")
@@ -100,11 +162,28 @@ object NestUI {
}
var _verbose = false
+ var _debug = false
+ var _terse = false
+ def isVerbose = _verbose
+ def isDebug = _debug
+ def isTerse = _terse
+
+ def setVerbose() {
+ _verbose = true
+ }
+ def setDebug() {
+ _debug = true
+ }
+ def setTerse() {
+ _terse = true
+ }
def verbose(msg: String) {
- if (_verbose) {
- outline("debug: ")
- println(msg)
- }
+ if (isVerbose)
+ System.err.println(msg)
+ }
+ def debug(msg: String) {
+ if (isDebug)
+ System.err.println(msg)
}
}
View
584 src/partest/scala/tools/partest/nest/Runner.scala
@@ -0,0 +1,584 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.tools.partest
+package nest
+
+import java.io.{ Console => _, _ }
+import java.net.URL
+import scala.tools.nsc.Properties.{ jdkHome, javaHome, propOrElse, propOrEmpty }
+import scala.util.Properties.{ envOrElse, isWin }
+import scala.tools.nsc.{ 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, ScalaClassLoader, stackTraceString }
+import ClassPath.{ join, split }
+import scala.tools.scalap.scalax.rules.scalasig.ByteCode
+import scala.collection.{ mutable, immutable }
+import scala.sys.process._
+import java.util.concurrent.{ Executors, TimeUnit, TimeoutException }
+import PartestDefaults.{ javaCmd, javacCmd }
+import scala.tools.scalap.Main.decompileScala
+
+trait PartestRunSettings {
+ def gitPath: Path
+ def reportPath: Path
+ def logPath: Path
+
+ def testPaths: List[Path]
+
+ def gitDiffOptions: List[String]
+ def extraScalacOptions: List[String]
+ def extraJavaOptions: List[String]
+}
+
+class TestTranscript {
+ import NestUI.color._
+ private val buf = mutable.ListBuffer[String]()
+ private def pass(s: String) = bold(green("% ")) + s
+ private def fail(s: String) = bold(red("% ")) + s
+
+ def add(action: String): this.type = { buf += action ; this }
+ def append(text: String) { val s = buf.last ; buf.trimEnd(1) ; buf += (s + text) }
+
+ // Colorize prompts according to pass/fail
+ def fail: List[String] = buf.toList match {
+ case Nil => Nil