diff options
author | Paul Phillips <paulp@improving.org> | 2010-04-11 00:32:00 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-04-11 00:32:00 +0000 |
commit | e93c1a93a2c8a40265b34bb9f1dd61b9470c908d (patch) | |
tree | b9f13ffbe1d1ef59380e32f74380f9797b7fd2cb /src/partest | |
parent | 71b6aca681ab697304590a96b13847b9bba141dc (diff) | |
download | scala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.tar.gz scala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.tar.bz2 scala-e93c1a93a2c8a40265b34bb9f1dd61b9470c908d.zip |
Introduces scala.tools.cmd providing command li...
Introduces scala.tools.cmd providing command line tool infrastructure.
For a quick look at what can be done, see
scala.tools.cmd.Demo
For a more involved, potentially eye-straining look, see
scala.tools.partest.PartestSpec
To experience it through the eyes of Joe Partest User, run
test/partest
Review by community.
Diffstat (limited to 'src/partest')
-rw-r--r-- | src/partest/scala/tools/partest/Compilable.scala | 4 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/Config.scala | 3 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/Partest.scala | 14 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/PartestSpec.scala | 134 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/Runner.scala | 5 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/ant/JavaTask.scala | 12 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/ant/PartestTask.scala | 90 | ||||
-rw-r--r-- | src/partest/scala/tools/partest/package.scala | 6 |
8 files changed, 88 insertions, 180 deletions
diff --git a/src/partest/scala/tools/partest/Compilable.scala b/src/partest/scala/tools/partest/Compilable.scala index a1d987ad6d..c11532f278 100644 --- a/src/partest/scala/tools/partest/Compilable.scala +++ b/src/partest/scala/tools/partest/Compilable.scala @@ -27,8 +27,10 @@ trait PartestCompilation { // } def javac(args: List[String]): Boolean = { + val allArgString = fromArgs(javacpArg :: javacOpts :: args) + // javac -d outdir -classpath <basepath> <files> - val cmd = "%s -d %s %s %s".format(javacCmd, outDir, javacpArg, fromArgs(args)) + 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)) diff --git a/src/partest/scala/tools/partest/Config.scala b/src/partest/scala/tools/partest/Config.scala index 7d8bb80835..288a3034e9 100644 --- a/src/partest/scala/tools/partest/Config.scala +++ b/src/partest/scala/tools/partest/Config.scala @@ -23,8 +23,6 @@ trait Config { * run we only allocate one worker so the output isn't interspersed. */ def workerTimeout = 3600 // 1 hour, probably overly generous - def testTimeout = testTimeout_ flatMap safeToInt getOrElse 900 // test timeout - def testWarning = testWarning_ flatMap safeToInt getOrElse (testTimeout / 10) // test warning 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 @@ -121,6 +119,7 @@ trait Config { "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 " "), diff --git a/src/partest/scala/tools/partest/Partest.scala b/src/partest/scala/tools/partest/Partest.scala index 019ed270e5..d6adcc6053 100644 --- a/src/partest/scala/tools/partest/Partest.scala +++ b/src/partest/scala/tools/partest/Partest.scala @@ -6,7 +6,7 @@ package scala.tools package partest import nsc.io._ -import nsc.util.CommandLine +import nsc.util._ import category.AllCategories /** Global object for a Partest run. It is completely configured by the list @@ -15,10 +15,15 @@ import category.AllCategories * for the complete list. */ class Partest(args: List[String]) extends { - val parsed = PartestSpecReference(args: _*) -} with Universe with PartestSpec with AllCategories { + val parsed = PartestSpec(args: _*) +} with Universe with PartestSpec with cmd.Instance with AllCategories { - debug("Partest object created with args: " + (args mkString " ")) + 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) @@ -30,7 +35,6 @@ class Partest(args: List[String]) extends { // Coarse validation of partest directory: holds a file called partest. (partestDir / "partest").isFile || error("'%s' is not a valid partest directory." format partestDir) - def runSets = toArgs(parsed.getOrElse("--runsets", "")) 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)) diff --git a/src/partest/scala/tools/partest/PartestSpec.scala b/src/partest/scala/tools/partest/PartestSpec.scala index a8a1d9b0cb..e4259d70be 100644 --- a/src/partest/scala/tools/partest/PartestSpec.scala +++ b/src/partest/scala/tools/partest/PartestSpec.scala @@ -6,9 +6,8 @@ package scala.tools package partest -import Properties._ import nsc.io._ -import nsc.util.{ CommandLine, CommandLineSpec, CommandLineReferenceSpec } +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 @@ -16,93 +15,90 @@ import nsc.util.{ CommandLine, CommandLineSpec, CommandLineReferenceSpec } * a private accumulator. What emerges is a full list of the valid unary * and binary arguments, as well as autogenerated help. */ -trait PartestSpec extends CommandLineSpec { - override def isPassthroughProperty(key: String) = key == "partest.options" - override def isSysPropOption(key: String) = { - val segments = (key split '.').toList - if (segments.size == 2 && segments.head == "partest") Some(segments.last) - else None - } - - private var _testKinds: List[String] = Nil - private def kind(s: String) = returning(s)(_testKinds +:= _) +trait PartestSpec extends Spec with Meta.StdOpts with Interpolation { + def referenceSpec = PartestSpec + def programInfo = Spec.Names("partest", "scala.tools.partest.Runner") + private val kind = new Spec.Accumulator[String]() + protected def testKinds = kind.get - def testKinds = _testKinds - def versionMsg = Properties.versionMsg + 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""") - - heading ("Test categories:") - 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" ?) + | 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" ? + 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 (default: test)" |> "test" - val buildDir = "builddir" / "path from ~ to test build (default: build/pack)" |> "build/pack" - val srcDir = "srcdir" / "path from --rootdir to sources (default: files)" |> "files" - val javaOpts = "javaopts" / "flags to java on all runs (overrides JAVA_OPTS)" |> envOrElse("JAVA_OPTS", "") - val scalacOpts = "scalacopts" / "flags to scalac on all tests (overrides SCALAC_OPTS)" |> envOrElse("SCALAC_OPTS", "") - ("pack" / "alias for --builddir build/pack") ?+> List("--builddir", "build/pack") - ("quick" / "alias for --builddir build/quick") ?+> List("--builddir", "build/quick") + 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" ? + 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" |> "14400" - val testWarning_ = "test-warning" / "Test warning in seconds" >> ; // defaults to testTimeout / 10 - val testTimeout_ = "test-timeout" / "Test timeout in seconds" >> ; // defaults to 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 isVersion = "version" / "print version" ? + val timeout = "timeout" / "Overall timeout in seconds" defaultTo 14400 + 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" --? + + "version" / "print version" --> runAndExit(println(Properties.versionMsg)) // no help for anything below this line - secret options // mostly intended for property configuration. - val runsets = "runsets" |> "" - val isNoAlarms = ("noalarms" ?) - val isInsideAnt = ("is-in-ant" ?) + val runSets = ("runsets" --^) getOrElse Nil + val isNoAlarms = "noalarms" --? + val isInsideAnt = "is-in-ant" --? } -object PartestSpecReference extends PartestSpec with CommandLineReferenceSpec { - import CommandLineSpec._ +object PartestSpec extends PartestSpec with Property { + lazy val propMapper = new PropertyMapper(PartestSpec) { + override def isPassThrough(key: String) = key == "partest.options" + } - def parsed: CommandLine = null - override def creator(args: List[String]) = - new ThisCommandLine(args) { - override def onlyKnownOptions = true - override def errorFn(msg: String) = printAndExit("Error: " + msg) - } + type ThisCommandLine = PartestCommandLine + class PartestCommandLine(args: List[String]) extends SpecCommandLine(args) { + override def onlyKnownOptions = true + override def errorFn(msg: String) = printAndExit("Error: " + msg) - def main(args: Array[String]): Unit = println(bashCompletion("partest")) + def propertyArgs = PartestSpec.propertyArgs + } - /** Append bash completion for partest to the given file. - */ - def appendCompletionTo(f: File) = f appendAll bashCompletion("partest") + override def creator(args: List[String]): PartestCommandLine = new PartestCommandLine(args) } - diff --git a/src/partest/scala/tools/partest/Runner.scala b/src/partest/scala/tools/partest/Runner.scala index 7f67c93478..1a28e60896 100644 --- a/src/partest/scala/tools/partest/Runner.scala +++ b/src/partest/scala/tools/partest/Runner.scala @@ -9,13 +9,10 @@ package partest import nsc.io._ object Runner { - def main(mainArgs: Array[String]) { - val propArgs = PartestSpecReference.sysPropsAsOptions() - val args = (propArgs ++ mainArgs).toList + def main(args: Array[String]) { val runner = Partest(args: _*) import runner._ - if (isVersion) return println(versionMsg) if (args.isEmpty) return println(helpMsg) if (isValidate) return validateAll() diff --git a/src/partest/scala/tools/partest/ant/JavaTask.scala b/src/partest/scala/tools/partest/ant/JavaTask.scala index 0bebf91368..6740554dd8 100644 --- a/src/partest/scala/tools/partest/ant/JavaTask.scala +++ b/src/partest/scala/tools/partest/ant/JavaTask.scala @@ -12,19 +12,21 @@ package ant import org.apache.tools.ant.Task import org.apache.tools.ant.taskdefs.Java -import org.apache.tools.ant.types.{ EnumeratedAttribute, Commandline, Environment, PropertySet } +import org.apache.tools.ant.types.Environment import scala.tools.nsc.io._ -import scala.tools.nsc.util.{ ClassPath, CommandLineSpec } -import CommandLineSpec._ +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 "-Xms64M -Xmx768M -Xss768K -XX:MaxPermSize=96M" - protected def runnerArgs = List("-usejavacp", "scala.tools.partest.Runner", "--javaopts", partestJVMArgs) + 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) diff --git a/src/partest/scala/tools/partest/ant/PartestTask.scala b/src/partest/scala/tools/partest/ant/PartestTask.scala deleted file mode 100644 index 65848fabb0..0000000000 --- a/src/partest/scala/tools/partest/ant/PartestTask.scala +++ /dev/null @@ -1,90 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala Parallel Testing ** -** / __/ __// _ | / / / _ | (c) 2007-2010, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -/**** Note -- this isn't used anymore, but I left it in for the moment. ****/ - -package scala.tools -package partest -package ant - -import java.io.{ File => JFile } - -import org.apache.tools.ant.Task -import org.apache.tools.ant.types.{ Reference, FileSet} - -import scala.reflect.BeanProperty -import scala.tools.ant.sabbus.CompilationPathProperty -import scala.tools.nsc.io -import scala.tools.nsc.util.CommandLineSpec._ - -class PartestTask extends Task with CompilationPathProperty { - /** Used only in ant task */ - @BeanProperty protected var errorOnFailed: Boolean = _ - @BeanProperty protected var jUnitReportDir: JFile = _ - - /** Propagated to partest run via system properties */ - @BeanProperty protected var debug: Boolean = _ - @BeanProperty protected var javaOpts: String = _ - @BeanProperty protected var partestOpts: String = _ - @BeanProperty protected var runSets: String = _ - @BeanProperty protected var scalacOpts: String = _ - @BeanProperty protected var showDiff: Boolean = _ - @BeanProperty protected var showLog: Boolean = _ - @BeanProperty protected var srcDir: String = _ - @BeanProperty protected var timeout: Int = _ - - /** Translating ant information into command line arguments. */ - private def notEmpty(s: String) = s != null && s.length > 0 - private def quoted(s: String) = if (s exists (_.isWhitespace)) "\"" + s.trim + "\"" else s - private def optionCollection = List[(Boolean, () => List[String])]( - debug -> (() => List("--debug")), - showLog -> (() => List("--show-log")), - showDiff -> (() => List("--show-diff")), - (timeout > 0) -> (() => List("--timeout", timeout.toString)), - notEmpty(javaOpts) -> (() => List("--javaopts", javaOpts)), - notEmpty(scalacOpts) -> (() => List("--scalacopts", scalacOpts)), - notEmpty(srcDir) -> (() => List("--srcdir", srcDir)), - notEmpty(partestOpts) -> (() => toArgs(partestOpts)) - ) - - private def antPropOrNone(name: String) = Option(getProject getProperty name) - private def antPropsToCommandLine() = { - setProp("partest.isInAnt", "true") - val partestDir = antPropOrNone("partest.dir") getOrElse error("Mandatory attribute 'partest.dir' is not set.") - - val root = List("--rootdir", io.Path(partestDir).path) - val opts = optionCollection collect { case (true, f) => f() } flatten - val sets = Option(runSets).toList flatMap toArgs map toOpt - - root ++ opts ++ sets - } - private def antRunTests() = { - val args = antPropsToCommandLine() - val runner = Partest(args: _*) - import runner._ - - normal("Ant options translate to command line: partest " + fromArgs(args)) - printConfigBanner() - - val result = launchTestSuite() - val msg = result.toString - - if (result.hasFailures && errorOnFailed) error(msg) - else log(msg) - } - - override def execute() { - try antRunTests() - catch { - case x => - System.err.println("Uncaught exception %s in partest ant ask: aborting." format x) - x.printStackTrace() - throw x - } - } -} diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index 3ef4db7cd8..f6d216e379 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -5,7 +5,6 @@ package scala.tools import nsc.io.{ File, Path, Process, Directory } -import nsc.util.CommandLineSpec import java.nio.charset.CharacterCodingException package object partest { @@ -18,13 +17,12 @@ package object partest { 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 safeToInt(s: String) = try Some(s.toInt) catch { case _: NumberFormatException => None } 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) = CommandLineSpec toArgs line - private[partest] def fromArgs(args: List[String]) = CommandLineSpec fromArgs args + private[partest] def toArgs(line: String) = cmd toArgs line + private[partest] def fromArgs(args: List[String]) = cmd fromArgs args /** Strings, argument lists, etc. */ |