diff options
7 files changed, 311 insertions, 224 deletions
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index ebfe638299..23e9f81fbd 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -10,7 +10,7 @@ package scala.tools.partest.nest import scala.tools.nsc.{Global, Settings} import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import java.io.{File, BufferedReader, PrintWriter, FileWriter} +import java.io.{File, BufferedReader, PrintWriter, FileWriter, StringWriter} class ExtConsoleReporter(override val settings: Settings, reader: BufferedReader, var writer: PrintWriter) extends ConsoleReporter(settings, reader, writer) { def this(settings: Settings) = { @@ -46,7 +46,7 @@ class DirectCompiler extends SimpleCompiler { def newReporter(sett: Settings) = new ExtConsoleReporter(sett, Console.in, - new PrintWriter(new FileWriter("scalac-out"))) + new PrintWriter(new StringWriter)) def compile(file: File, kind: String, log: File): Boolean = { val testSettings = newSettings diff --git a/src/partest/scala/tools/partest/nest/DirectRunner.scala b/src/partest/scala/tools/partest/nest/DirectRunner.scala new file mode 100644 index 0000000000..cdfc814773 --- /dev/null +++ b/src/partest/scala/tools/partest/nest/DirectRunner.scala @@ -0,0 +1,233 @@ +/* NEST (New Scala Test) + * Copyright 2007-2008 LAMP/EPFL + * @author Philipp Haller + */ + +// $Id: $ + +package scala.tools.partest.nest + +import java.io.{File, PrintStream, FileOutputStream, BufferedReader, + InputStreamReader, StringWriter, PrintWriter} +import java.util.StringTokenizer + +import scala.actors.Actor._ + +class DirectRunner { + private val version = System.getProperty("java.version", "") + private val isJava5 = version matches "1.[5|6|7].*" + + private val numActors = Integer.parseInt(System.getProperty("scalatest.actors", "8")) + + private var posCheck = false + private var negCheck = false + private var runCheck = false + private var jvmCheck = false + private var jvm5Check = false + private var resCheck = false + private var runAll = false + + private var testFiles: List[File] = List() + private val con = new PrintStream(Console.out) + private var out = con + + private val errors = + Integer.parseInt(System.getProperty("scalatest.errors", "0")) + + def denotesTestSet(arg: String) = + arg match { + case "--pos" => true + case "--neg" => true + case "--run" => true + case "--jvm" => true + case "--jvm5" => true + case "--res" => true + case _ => false + } + + def main(argstr: String) { + // tokenize args + var args: List[String] = List() + val st = new StringTokenizer(argstr) + while (st.hasMoreTokens) { + args = args ::: List(st.nextToken()) + } + + if (args.length == 0) + NestUI.usage() + else { + if (!args.exists(denotesTestSet(_))) runAll = true + for (arg <- args) { + arg match { + case "--pos" => posCheck = true + case "--neg" => negCheck = true + case "--run" => runCheck = true + case "--jvm" => jvmCheck = true + case "--jvm5" => jvm5Check = true + case "--res" => resCheck = true + case "--verbose" => NestUI._verbose = true + case "--show-diff" => FileManager.showDiff = true + case "--show-log" => FileManager.showLog = true + case "--failed" => FileManager.failed = true + case "--version" => //todo: printVersion + case "--ansi" => NestUI.initialize(NestUI.MANY) + case _ => + if (arg endsWith ".scala") { + val file = new File(arg) + if (file.isFile) { + NestUI.verbose("adding test file "+file) + testFiles = file :: testFiles + } else { + NestUI.failure("File \"" + arg + "\" not found") + System.exit(1) + } + } else if (out eq con) { + val file = new File(arg) + if (file.isFile || file.createNewFile) + out = new PrintStream(new FileOutputStream(file)) + else { + NestUI.failure("Result file \"" + arg + "\" not found") + System.exit(1) + } + } else + NestUI.usage() + } + } + + NestUI.outline("Source directory is : "+FileManager.srcDir.getAbsolutePath+"\n") + NestUI.outline("Scala binaries in : "+FileManager.BIN_DIR+"\n") + + // obtain scalac version + val cmd = FileManager.SCALAC_CMD+" -version" + NestUI.verbose("running "+cmd) + val proc = Runtime.getRuntime.exec(cmd) + val in = proc.getInputStream + val err = proc.getErrorStream + val exitCode = proc.waitFor() + NestUI.verbose("exit code: "+exitCode) + val scalaVersion = StreamAppender.appendToString(in, err) + + NestUI.outline("Scala version is : "+scalaVersion) + NestUI.outline("Scalac options are : "+FileManager.SCALAC_OPTS+"\n") + + val vmBin = System.getProperty("java.home", "")+File.separator+"bin" + val vmName = System.getProperty("java.vm.name", "")+" (build "+ + System.getProperty("java.vm.version", "")+", "+ + System.getProperty("java.vm.info", "")+")" + val vmOpts = System.getProperty("scalatest.java_options", "?") + NestUI.outline("Java binaries in : "+vmBin+"\n") + NestUI.outline("Java runtime is : "+vmName+"\n") + NestUI.outline("Java options are : "+vmOpts+"\n") + + val start = System.currentTimeMillis + + val (successes, failures) = testCheckAll() + + val end = System.currentTimeMillis + val total = successes + failures + + val elapsedSecs = (end - start)/1000 + val elapsedMins = elapsedSecs/60 + val elapsedHrs = elapsedMins/60 + val dispMins = elapsedMins - elapsedHrs * 60 + val dispSecs = elapsedSecs - elapsedMins * 60 + val dispElapsed = { + def form(num: Long) = if (num < 10) "0"+num else ""+num + form(elapsedHrs)+":"+form(dispMins)+":"+form(dispSecs) + } + + println + if (failures == 0) + NestUI.success("All of "+total+" tests were successful (elapsed time: "+dispElapsed+")\n") + else + NestUI.failure(failures+" of "+total+" tests failed (elapsed time: "+dispElapsed+")\n") + + if (failures == errors) + System.exit(0) + else + System.exit(1) + } + } + + def runTests(kind: String, check: Boolean, msg: String): (Int, Int) = { + if (check) { + val fileMgr = new FileManager + val kindFiles = + if (!testFiles.isEmpty) { + NestUI.verbose("testing "+testFiles) + testFiles + } + else if (kind == "res") //TODO: is there a nicer way? + fileMgr.getFiles(kind, check, ".res") + else + fileMgr.getFiles(kind, check) + if (!kindFiles.isEmpty) { + NestUI.outline("\n"+msg+"\n") + + val len = kindFiles.length + val (testsEach, lastFrag) = (len/numActors, len%numActors) + val last = numActors-1 + val workers = for (i <- List.range(0, numActors)) yield { + val toTest = kindFiles.slice(i*testsEach, (i+1)*testsEach) + val worker = new Worker + worker.start() + if (i == last) + worker ! RunTests(kind, (kindFiles splitAt (last*testsEach))._2) + else + worker ! RunTests(kind, toTest) + worker + } + var succs = 0; var fails = 0 + var logsToDelete: List[File] = List() + var outdirsToDelete: List[File] = List() + workers foreach { w => + receive { + case Results(s, f, logs, outdirs) => + logsToDelete = logsToDelete ::: logs.filter(_.toDelete) + outdirsToDelete = outdirsToDelete ::: outdirs + succs += s + fails += f + } + } + logsToDelete.foreach { log => + NestUI.verbose("deleting "+log+"\n") + FileManager.deleteRecursive(log) + } + outdirsToDelete.foreach { outdir => + NestUI.verbose("deleting "+outdir+"\n") + FileManager.deleteRecursive(outdir) + } + + (succs, fails) + + //val worker = new Worker + //worker.runTests(kind, kindFiles) + } else { + NestUI.failure("test dir empty") + (0, 0) + } + } else (0, 0) + } + + /** + * @return (success count, failure count) + */ + def testCheckAll(): (Int, Int) = { + if (runAll) { // run all tests + posCheck = true + negCheck = true + runCheck = true + jvmCheck = true + jvm5Check = true + //resCheck = true + } + val results = List(runTests("pos", posCheck, "Testing compiler (on files whose compilation should succeed)"), + runTests("neg", negCheck, "Testing compiler (on files whose compilation should fail)"), + runTests("run", runCheck, "Testing JVM backend"), + runTests("jvm", jvmCheck, "Testing JVM backend"), + runTests("jvm5", jvm5Check, "Testing JVM backend"), + runTests("res", resCheck, "Testing resident compiler")) + results reduceLeft { (p: (Int, Int), q: (Int, Int)) => + (p._1+q._1, p._2+q._2) } + } +} diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index 08f11da3d3..bb9a3f4842 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -14,6 +14,7 @@ object FileManager { val PATH_SEP = File.pathSeparatorChar val CLASSPATH = System.getProperty("java.class.path", ".") + NestUI.verbose("CLASSPATH: "+CLASSPATH) val SCALAHOME = System.getProperty("scala.home", ".") NestUI.verbose("SCALAHOME: "+SCALAHOME) val JAVACMD = System.getProperty("scalatest.javacmd", "java") @@ -82,23 +83,26 @@ elif [ -d "$PREFIX/bin" ]; then val bin = new File(PREFIX, "bin") if (dists.isDirectory) { - latestFile = prefixFile("dists/latest/bin") - latestLibFile = prefixFile("dists/latest/lib/scala-library.jar") - latestCompFile = prefixFile("dists/latest/lib/scala-compiler.jar") + latestFile = prefixFile("dists/latest/bin") + latestLibFile = prefixFile("dists/latest/lib/scala-library.jar") + latestActFile = prefixFile("dists/latest/lib/scala-library.jar") + latestCompFile = prefixFile("dists/latest/lib/scala-compiler.jar") latestPartestFile = prefixFile("dists/latest/lib/scala-partest.jar") - latestFjbgFile = prefixFile("lib/fjbg.jar") // starr + latestFjbgFile = prefixFile("lib/fjbg.jar") // starr } else if (build.isDirectory) { - latestFile = prefixFile("build/quick/bin") - latestLibFile = prefixFile("build/quick/lib/library") - latestCompFile = prefixFile("build/quick/lib/compiler") + latestFile = prefixFile("build/quick/bin") + latestLibFile = prefixFile("build/quick/lib/library") + latestActFile = prefixFile("build/quick/lib/actors") + latestCompFile = prefixFile("build/quick/lib/compiler") latestPartestFile = prefixFile("build/quick/lib/partest") - latestFjbgFile = prefixFile("lib/fjbg.jar") // starr + latestFjbgFile = prefixFile("lib/fjbg.jar") // starr } else if (bin.isDirectory) { - latestFile = prefixFile("bin") - latestLibFile = prefixFile("lib/scala-library.jar") - latestCompFile = prefixFile("lib/scala-compiler.jar") + latestFile = prefixFile("bin") + latestLibFile = prefixFile("lib/scala-library.jar") + latestActFile = prefixFile("lib/scala-library.jar") + latestCompFile = prefixFile("lib/scala-compiler.jar") latestPartestFile = prefixFile("lib/scala-partest.jar") } else @@ -133,6 +137,7 @@ elif [ -d "$PREFIX/bin" ]; then var latestFile: File = _ var latestLibFile: File = _ + var latestActFile: File = _ var latestCompFile: File = _ var latestPartestFile: File = _ var latestFjbgFile: File = _ @@ -150,6 +155,10 @@ elif [ -d "$PREFIX/bin" ]; then } } + var showDiff = false + var showLog = false + var failed = false + private def basename(name: String): String = { val inx = name.lastIndexOf(".") if (inx < 0) name else name.substring(0, inx) diff --git a/src/partest/scala/tools/partest/nest/NestRunner.scala b/src/partest/scala/tools/partest/nest/NestRunner.scala index 45be1670b2..e2974e4183 100644 --- a/src/partest/scala/tools/partest/nest/NestRunner.scala +++ b/src/partest/scala/tools/partest/nest/NestRunner.scala @@ -7,205 +7,9 @@ package scala.tools.partest.nest -import java.io.{File, PrintStream, FileOutputStream, BufferedReader, - InputStreamReader, StringWriter, PrintWriter} - -import scala.actors.Actor._ - object NestRunner { - private val version = System.getProperty("java.version", "") - private val isJava5 = version matches "1.[5|6|7].*" - - private val numActors = Integer.parseInt(System.getProperty("scalatest.actors", "8")) - - private var posCheck = false - private var negCheck = false - private var jvmCheck = false - private var jvm5Check = false - private var runCheck = false - private var resCheck = false - private var shootoutCheck = false - - private var conservative = false - - var showDiff = false - var showLog = false - var failed = false - - private var testFiles: List[File] = List() - private val con = new PrintStream(Console.out) - private var out = con - - private val errors = - Integer.parseInt(System.getProperty("scalatest.errors", "0")) - def main(args: Array[String]) { - if (args.length == 0) - NestUI.usage() - else { - for (arg <- args) { - arg match { - case "--pos" => posCheck = true - case "--neg" => negCheck = true - case "--jvm" => jvmCheck = true - case "--jvm5" => jvm5Check = true - case "--run" => runCheck = true - case "--res" => resCheck = true - case "--shootout" => shootoutCheck = true - case "--conservative" => conservative = true - case "--verbose" => NestUI._verbose = true - case "--show-diff" => showDiff = true - case "--show-log" => showLog = true - case "--failed" => failed = true - case "--version" => //todo: printVersion - case "--ansi" => NestUI.initialize(NestUI.MANY) - case _ => - if (arg endsWith ".scala") { - val file = new File(arg) - if (file.isFile) { - NestUI.verbose("adding test file "+file) - testFiles = file :: testFiles - } else { - NestUI.failure("File \"" + arg + "\" not found") - System.exit(1) - } - } else if (out eq con) { - val file = new File(arg) - if (file.isFile || file.createNewFile) - out = new PrintStream(new FileOutputStream(file)) - else { - NestUI.failure("Result file \"" + arg + "\" not found") - System.exit(1) - } - } else - NestUI.usage() - } - } - - NestUI.outline("Source directory is : "+FileManager.srcDir.getAbsolutePath+"\n") - NestUI.outline("Scala binaries in : "+FileManager.BIN_DIR+"\n") - - // obtain scalac version - val cmd = FileManager.SCALAC_CMD+" -version" - NestUI.verbose("running "+cmd) - val proc = Runtime.getRuntime.exec(cmd) - val in = proc.getInputStream - val err = proc.getErrorStream - val exitCode = proc.waitFor() - NestUI.verbose("exit code: "+exitCode) - val scalaVersion = StreamAppender.appendToString(in, err) - - NestUI.outline("Scala version is : "+scalaVersion) - NestUI.outline("Scalac options are : "+FileManager.SCALAC_OPTS+"\n") - - val vmBin = System.getProperty("java.home", "")+File.separator+"bin" - val vmName = System.getProperty("java.vm.name", "")+" (build "+ - System.getProperty("java.vm.version", "")+", "+ - System.getProperty("java.vm.info", "")+")" - val vmOpts = System.getProperty("scalatest.java_options", "?") - NestUI.outline("Java binaries in : "+vmBin+"\n") - NestUI.outline("Java runtime is : "+vmName+"\n") - NestUI.outline("Java options are : "+vmOpts+"\n") - - val start = System.currentTimeMillis - val (successes, failures) = testCheckAll() - val end = System.currentTimeMillis - val total = successes + failures - - val elapsedSecs = (end - start)/1000 - val elapsedMins = elapsedSecs/60 - val elapsedHrs = elapsedMins/60 - val dispMins = elapsedMins - elapsedHrs * 60 - val dispSecs = elapsedSecs - elapsedMins * 60 - val dispElapsed = { - def form(num: Long) = if (num < 10) "0"+num else ""+num - form(elapsedHrs)+":"+form(dispMins)+":"+form(dispSecs) - } - - println - if (failures == 0) - NestUI.success("All of "+total+" tests were successful (elapsed time: "+dispElapsed+")\n") - else - NestUI.failure(failures+" of "+total+" tests failed (elapsed time: "+dispElapsed+")\n") - - if (failures == errors) - System.exit(0) - else - System.exit(1) - } - } - - def runTests(kind: String, check: Boolean, msg: String): (Int, Int) = { - if (check) { - val fileMgr = new FileManager - val kindFiles = - if (!testFiles.isEmpty) { - NestUI.verbose("testing "+testFiles) - testFiles - } - else if (kind == "res") //TODO: is there a nicer way? - fileMgr.getFiles(kind, check, ".res") - else - fileMgr.getFiles(kind, check) - if (!kindFiles.isEmpty) { - NestUI.outline("\n"+msg+"\n") - - val len = kindFiles.length - val (testsEach, lastFrag) = (len/numActors, len%numActors) - val last = numActors-1 - val workers = for (i <- List.range(0, numActors)) yield { - val toTest = kindFiles.slice(i*testsEach, (i+1)*testsEach) - val worker = new Worker - worker.start() - if (i == last) - worker ! RunTests(kind, (kindFiles splitAt (last*testsEach))._2) - else - worker ! RunTests(kind, toTest) - worker - } - var succs = 0; var fails = 0 - var logsToDelete: List[File] = List() - var outdirsToDelete: List[File] = List() - workers foreach { w => - receive { - case Results(s, f, logs, outdirs) => - logsToDelete = logsToDelete ::: logs.filter(_.toDelete) - outdirsToDelete = outdirsToDelete ::: outdirs - succs += s - fails += f - } - } - logsToDelete.foreach { log => - NestUI.verbose("deleting "+log+"\n") - FileManager.deleteRecursive(log) - } - outdirsToDelete.foreach { outdir => - NestUI.verbose("deleting "+outdir+"\n") - FileManager.deleteRecursive(outdir) - } - - (succs, fails) - - //val worker = new Worker - //worker.runTests(kind, kindFiles) - } else { - NestUI.failure("test dir empty") - (0, 0) - } - } else (0, 0) - } - - /** - * @return (success count, failure count) - */ - def testCheckAll(): (Int, Int) = { - val results = List(runTests("pos", posCheck, "Testing compiler (on files whose compilation should succeed)"), - runTests("neg", negCheck, "Testing compiler (on files whose compilation should fail)"), - runTests("run", runCheck, "Testing JVM backend"), - runTests("jvm", jvmCheck, "Testing JVM backend"), - runTests("jvm5", jvm5Check, "Testing JVM backend"), - runTests("res", resCheck, "Testing resident compiler")) - results reduceLeft { (p: (Int, Int), q: (Int, Int)) => - (p._1+q._1, p._2+q._2) } + val argstr = args.mkString(" ") + (new ReflectiveRunner).main(argstr) } } diff --git a/src/partest/scala/tools/partest/nest/NestUI.scala b/src/partest/scala/tools/partest/nest/NestUI.scala index 4f295c1111..21eeb0b1b7 100644 --- a/src/partest/scala/tools/partest/nest/NestUI.scala +++ b/src/partest/scala/tools/partest/nest/NestUI.scala @@ -65,8 +65,6 @@ object NestUI { println(" --neg next files test a compilation failure") println(" --jvm next files test the JVM backend") println(" --run next files test the interpreter and all backends") - println(" --shootout ...") - println(" --conservative ...") println(" --verbose display progress information") println(" --version output version information and exit") println diff --git a/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala new file mode 100644 index 0000000000..228eb7ff6c --- /dev/null +++ b/src/partest/scala/tools/partest/nest/ReflectiveRunner.scala @@ -0,0 +1,42 @@ +/* NEST (New Scala Test) + * Copyright 2007-2008 LAMP/EPFL + * @author Philipp Haller + */ + +// $Id: $ + +package scala.tools.partest.nest + +/* This class is used to load an instance of DirectRunner using + * a custom class loader. + * The purpose is to "auto-detect" a good classpath for the + * rest of the classes (Worker, CompileManager etc.), so that + * the main NestRunner can be started merely by putting its + * class on the classpath (ideally). + */ +class ReflectiveRunner { + // we might also use FileManager.CLASSPATH + // to use the same classes as used by `scala` that + // was used to start the runner. + + import FileManager.{latestCompFile, latestLibFile, latestActFile, + latestPartestFile, latestFjbgFile} + + val sepUrls = Array(latestCompFile.toURL, latestLibFile.toURL, + latestActFile.toURL, latestPartestFile.toURL, + latestFjbgFile.toURL) + val sepLoader = new java.net.URLClassLoader(sepUrls, null) + + val sepRunnerClass = + sepLoader.loadClass("scala.tools.partest.nest.DirectRunner") + val sepRunner = sepRunnerClass.newInstance() + + val stringClass = Class.forName("java.lang.String") + val sepMainMethod = + sepRunnerClass.getMethod("main", Array(stringClass)) + + def main(args: String) { + val cargs: Array[AnyRef] = Array(args) + sepMainMethod.invoke(sepRunner, cargs) + } +} diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 74ca8d918e..f4594c1348 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -159,13 +159,14 @@ class Worker extends Actor { err.close out.close*/ - if (NestRunner.showLog) { + if (FileManager.showLog) { // produce log as string in `log` val reader = new BufferedReader(new FileReader(logFile)) - val writer = new PrintWriter(new StringWriter, true) + val swriter = new StringWriter + val pwriter = new PrintWriter(swriter, true) val appender = new StreamAppender(reader, writer) appender.run() - log = writer.toString + log = swriter.toString } } @@ -198,7 +199,7 @@ class Worker extends Actor { // when option "--failed" is provided // execute test only if log file is present // (which means it failed before) - if (!NestRunner.failed || (logFile.exists && logFile.canRead)) { + if (!FileManager.failed || (logFile.exists && logFile.canRead)) { val swr = new StringWriter val wr = new PrintWriter(swr) success = true @@ -246,8 +247,8 @@ class Worker extends Actor { wr.flush() swr.flush() NestUI.normal(swr.toString) - if (!success && NestRunner.showDiff) NestUI.normal(diff) - if (!success && NestRunner.showLog) NestUI.normal(log) + if (!success && FileManager.showDiff) NestUI.normal(diff) + if (!success && FileManager.showLog) NestUI.normal(log) } } // for each file NestUI.verbose("finished testing "+kind+" with "+errors+" errors") @@ -326,7 +327,7 @@ class Worker extends Actor { // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file, kind) - if (!NestRunner.failed || (logFile.exists && logFile.canRead)) { + if (!FileManager.failed || (logFile.exists && logFile.canRead)) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true; diff = ""; log = "" @@ -365,8 +366,8 @@ class Worker extends Actor { swr.flush() NestUI.normal(swr.toString) - if (!succeeded && NestRunner.showDiff) NestUI.normal(diff) - if (!succeeded && NestRunner.showLog) { + if (!succeeded && FileManager.showDiff) NestUI.normal(diff) + if (!succeeded && FileManager.showLog) { // output log file val logReader = new BufferedReader(new FileReader(logFile)) val logWriter = new PrintWriter(new StringWriter, true) @@ -456,8 +457,8 @@ class Worker extends Actor { errors += 1 } - if (!succeeded && NestRunner.showDiff) NestUI.normal(diff) - if (!succeeded && NestRunner.showLog) { + if (!succeeded && FileManager.showDiff) NestUI.normal(diff) + if (!succeeded && FileManager.showLog) { // output log file val logReader = new BufferedReader(new FileReader(logFile)) val logWriter = new PrintWriter(new StringWriter, true) |