From 68cbfeac525cad416a3e2fd4b90d13631dd81bc6 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 23 Feb 2010 08:21:00 +0000 Subject: Introducing partest to the idea of code reuse. --- .../scala/tools/partest/nest/CompileManager.scala | 2 +- .../scala/tools/partest/nest/ConsoleRunner.scala | 8 +- .../scala/tools/partest/nest/FileManager.scala | 65 ++++--------- .../scala/tools/partest/nest/StreamAppender.scala | 68 +++++++------ .../scala/tools/partest/nest/TestFile.scala | 5 - src/partest/scala/tools/partest/nest/Worker.scala | 107 +++++++-------------- src/partest/scala/tools/partest/package.scala | 6 +- 7 files changed, 102 insertions(+), 159 deletions(-) (limited to 'src') diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala index 517620e958..b3c6e9b4df 100644 --- a/src/partest/scala/tools/partest/nest/CompileManager.scala +++ b/src/partest/scala/tools/partest/nest/CompileManager.scala @@ -80,7 +80,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler { // check whether there is a ".flags" file val testBase = { - val logBase = fileManager.basename(log.getName) + val logBase = basename(log.getName) logBase.substring(0, logBase.length-4) } val argsFile = new File(log.getParentFile, testBase+".flags") diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala index 8542e08071..b10e56b50b 100644 --- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala +++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala @@ -157,10 +157,10 @@ class ConsoleRunner extends DirectRunner { System exit ( if (failures == errors) 0 else 1 ) } - def toStatistics[A](results: Iterable[(A, Int)]): (Int, Int) = - results - .map { case (file, resultCode) => if (resultCode == 0) (1, 0) else (0, 1) } - .reduceLeft((res1, res2) => (res1._1 + res2._1, res1._2 + res2._2)) + def toStatistics[A](results: Iterable[(A, Int)]): (Int, Int) = { + val (files, failures) = results map (_._2 == 0) partition (_ == true) + (files.size, failures.size) + } def runTests(testSet: TestSet): (Int, Int) = { val TestSet(loc, filter, kind, msg) = testSet diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala index b8f0770f3a..88d6ab9289 100644 --- a/src/partest/scala/tools/partest/nest/FileManager.scala +++ b/src/partest/scala/tools/partest/nest/FileManager.scala @@ -15,9 +15,6 @@ import java.net.URI import scala.tools.nsc.io.{ Path, Directory } trait FileManager { - - def basename(name: String): String = Path(name).stripExtension - /** * Compares two files using a Java implementation of the GNU diff * available at http://www.bmsi.com/java/#diff. @@ -27,19 +24,12 @@ trait FileManager { * @return the text difference between the compared files */ def compareFiles(f1: File, f2: File): String = { - var res = "" - try { - val diffWriter = new StringWriter - val args = Array(f1.getCanonicalPath(), f2.getCanonicalPath()) - DiffPrint.doDiff(args, diffWriter) - res = diffWriter.toString - if (res startsWith "No") - res = "" - } catch { - case e: IOException => - e.printStackTrace() - } - res + val diffWriter = new StringWriter + val args = Array(f1.getCanonicalPath(), f2.getCanonicalPath()) + + DiffPrint.doDiff(args, diffWriter) + val res = diffWriter.toString + if (res startsWith "No") "" else res } var JAVACMD: String @@ -68,47 +58,34 @@ trait FileManager { getLogFile(dir, fileBase, kind) } - def logFileExists(file: File, kind: String): Boolean = { - val logFile = getLogFile(file, kind) - logFile.exists && logFile.canRead - } + def logFileExists(file: File, kind: String) = + getLogFile(file, kind).canRead - def overwriteFileWith(dest: File, file: File): Boolean = - if (dest.exists && dest.isFile) - copyFile(file, dest) - else - false + def overwriteFileWith(dest: File, file: File) = + dest.isFile && copyFile(file, dest) def copyFile(from: File, to: File): Boolean = try { - val fromReader = new BufferedReader(new FileReader(from)) - val toWriter = new PrintWriter(new FileWriter(to)) - - new StreamAppender(fromReader, toWriter).run() - - fromReader.close() - toWriter.close() + val appender = StreamAppender(from, to) + appender.run() + appender.closeAll() true - } catch { - case _:IOException => false + } + catch { + case _: IOException => false } def mapFile(file: File, suffix: String, dir: File, replace: String => String) { val tmpFile = File.createTempFile("tmp", suffix, dir) // prefix required by API - val fileReader = new BufferedReader(new FileReader(file)) - val tmpFilePrinter = new PrintWriter(new FileWriter(tmpFile)) - val appender = new StreamAppender(fileReader, tmpFilePrinter) + val appender = StreamAppender(file, tmpFile) appender.runAndMap(replace) + appender.closeAll() - fileReader.close() - tmpFilePrinter.close() + val appender2 = StreamAppender(tmpFile, file) + appender2.run() + appender2.closeAll() - val tmpFileReader = new BufferedReader(new FileReader(tmpFile)) - val filePrinter= new PrintWriter(new FileWriter(file), true) - (new StreamAppender(tmpFileReader, filePrinter)).run - tmpFileReader.close() - filePrinter.close() tmpFile.delete() } } diff --git a/src/partest/scala/tools/partest/nest/StreamAppender.scala b/src/partest/scala/tools/partest/nest/StreamAppender.scala index c4636af323..8cebcf1685 100644 --- a/src/partest/scala/tools/partest/nest/StreamAppender.scala +++ b/src/partest/scala/tools/partest/nest/StreamAppender.scala @@ -8,27 +8,37 @@ package scala.tools.partest package nest -import java.io.{Writer, PrintWriter, Reader, BufferedReader, - IOException, InputStream, StringWriter, InputStreamReader, - OutputStreamWriter, StringReader, OutputStream} +import java.io._ object StreamAppender { + def wrapIn(in: InputStream): BufferedReader = new BufferedReader(new InputStreamReader(in)) + def wrapIn(reader: Reader): BufferedReader = new BufferedReader(reader) + def wrapIn(str: String): BufferedReader = new BufferedReader(new StringReader(str)) - def apply(reader: BufferedReader, writer: Writer): StreamAppender = { - val pwriter = new PrintWriter(writer, true) - new StreamAppender(reader, pwriter) - } + def wrapOut(out: OutputStream): PrintWriter = new PrintWriter(new OutputStreamWriter(out), true) + def wrapOut(writer: Writer): PrintWriter = new PrintWriter(writer, true) + def wrapOut(): PrintWriter = wrapOut(new StringWriter) + + def apply(reader: BufferedReader, writer: Writer): StreamAppender = + new StreamAppender(reader, wrapOut(writer)) def apply(reader: Reader, writer: Writer): StreamAppender = - apply(new BufferedReader(reader), writer) + apply(wrapIn(reader), writer) + + def apply(in: InputStream, writer: Writer): StreamAppender = + apply(wrapIn(in), writer) + + def apply(str: String, writer: Writer): StreamAppender = + apply(wrapIn(str), writer) + + def apply(in: File, out: File): StreamAppender = + apply(new FileReader(in), new FileWriter(out)) def appendToString(in1: InputStream, in2: InputStream): String = { val swriter1 = new StringWriter val swriter2 = new StringWriter - val reader1 = new BufferedReader(new InputStreamReader(in1)) - val reader2 = new BufferedReader(new InputStreamReader(in2)) - val app1 = StreamAppender(reader1, swriter1) - val app2 = StreamAppender(reader2, swriter2) + val app1 = StreamAppender(wrapIn(in1), swriter1) + val app2 = StreamAppender(wrapIn(in2), swriter2) val async = new Thread(app2) async.start() @@ -56,35 +66,29 @@ object StreamAppender { def concat(in: InputStream, err: InputStream, out: OutputStream) = new Runnable { override def run() { - val outWriter = new PrintWriter(new OutputStreamWriter(out), true) - val inApp = new StreamAppender(new BufferedReader(new InputStreamReader(in)), - outWriter) + val outWriter = wrapOut(out) + val inApp = StreamAppender(in, outWriter) + val errStringWriter = new StringWriter - val errApp = StreamAppender(new BufferedReader(new InputStreamReader(err)), - errStringWriter) + val errApp = StreamAppender(wrapIn(err), errStringWriter) + inParallel(inApp, errApp) // append error string to out - val errStrApp = new StreamAppender(new BufferedReader(new StringReader(errStringWriter.toString)), - outWriter) - errStrApp.run() + StreamAppender(errStringWriter.toString, outWriter).run() } } } class StreamAppender(reader: BufferedReader, writer: PrintWriter) extends Runnable { override def run() = runAndMap(identity) - - def runAndMap(f: String => String) { - try { - var line = reader.readLine() - while (line != null) { - writer.println(f(line)) - line = reader.readLine() - } - } catch { - case e: IOException => - e.printStackTrace() - } + private def lines() = Iterator continually reader.readLine() takeWhile (_ != null) + def closeAll() = { + reader.close() + writer.close() } + + def runAndMap(f: String => String) = + try lines() map f foreach (writer println _) + catch { case e: IOException => e.printStackTrace() } } diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala index e4f1d98c06..9eb6f63351 100644 --- a/src/partest/scala/tools/partest/nest/TestFile.scala +++ b/src/partest/scala/tools/partest/nest/TestFile.scala @@ -37,11 +37,6 @@ abstract class TestFile(kind: String) { settings appendToClasspath fileManager.CLASSPATH } - private def basename(name: String): String = { - val inx = name.lastIndexOf(".") - if (inx < 0) name else name.substring(0, inx) - } - override def toString(): String = kind+" "+file } diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 4bbd34766c..658464e2a6 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -9,18 +9,17 @@ package scala.tools.partest package nest import java.io._ -import java.net.{URLClassLoader, URL} -import java.util.{Timer, TimerTask} +import java.net.{ URLClassLoader, URL } +import java.util.{ Timer, TimerTask } -import scala.util.Properties.osName +import scala.util.Properties.{ isWin } import scala.tools.nsc.{ ObjectRunner, Settings, CompilerCommand, Global } import scala.tools.nsc.io.{ AbstractFile, PlainFile, Path, Directory, File => SFile } import scala.tools.nsc.reporters.ConsoleReporter import scala.tools.nsc.util.{ ClassPath, FakePos } -import scala.tools.util.PathResolver import ClassPath.{ join, split } -import scala.actors.{Actor, Exit, TIMEOUT} +import scala.actors.{ Actor, Exit, TIMEOUT } import scala.actors.Actor._ import scala.tools.scalap.scalax.rules.scalasig.{ByteCode, ClassFileParser, ScalaSigAttributeParsers} @@ -66,11 +65,6 @@ class Worker(val fileManager: FileManager) extends Actor { } } - private def basename(name: String): String = { - val inx = name.lastIndexOf(".") - if (inx < 0) name else name.substring(0, inx) - } - def printInfoStart(file: File, printer: PrintWriter) { NestUI.outline("testing: ", printer) val filesdir = file.getAbsoluteFile.getParentFile.getParentFile @@ -209,20 +203,16 @@ class Worker(val fileManager: FileManager) extends Actor { val in = proc.getInputStream val err = proc.getErrorStream val writer = new PrintWriter(new FileWriter(output), true) - val inApp = new StreamAppender(new BufferedReader(new InputStreamReader(in)), - writer) - val errApp = new StreamAppender(new BufferedReader(new InputStreamReader(err)), - writer) + val inApp = StreamAppender(in, writer) + val errApp = StreamAppender(err, writer) val async = new Thread(errApp) async.start() inApp.run() async.join() writer.close() - try { - proc.exitValue() - } catch { - case e: IllegalThreadStateException => 0 - } + + try proc.exitValue() + catch { case _: IllegalThreadStateException => 0 } } def execTest(outDir: File, logFile: File, fileBase: String) { @@ -289,7 +279,7 @@ class Worker(val fileManager: FileManager) extends Actor { def chkFile(s: String) = Directory(dir) / "%s%s.check".format(fileBase, s) val checkFile = if (chkFile("").isFile) chkFile("") else chkFile("-" + kind) - if (checkFile.exists && checkFile.canRead) Some(checkFile) else None + if (checkFile.canRead) Some(checkFile) else None } def existsCheckFile(dir: File, fileBase: String, kind: String) = @@ -323,6 +313,13 @@ class Worker(val fileManager: FileManager) extends Actor { NestUI.verbose("scalac: compilation of "+what+" failed\n") succeeded = false } + def diffCheck(latestDiff: String) = { + diff = latestDiff + if (latestDiff != "") { + NestUI.verbose("output differs from log file\n") + succeeded = false + } + } /** 1. Creates log file and output directory. * 2. Runs script function, providing log file and @@ -333,7 +330,7 @@ class Worker(val fileManager: FileManager) extends Actor { // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file, kind) - if (!fileManager.failed || (logFile.exists && logFile.canRead)) { + if (!fileManager.failed || logFile.canRead) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true @@ -422,11 +419,7 @@ class Worker(val fileManager: FileManager) extends Actor { // // NestUI.verbose(this+" finished running "+fileBase) execTest(outDir, logFile, fileBase) - diff = compareOutput(dir, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck(compareOutput(dir, fileBase, kind, logFile)) } }) @@ -481,16 +474,12 @@ class Worker(val fileManager: FileManager) extends Actor { if (succeeded) { // compare log file to check file val fileBase = basename(file.getName) val dir = file.getParentFile - if (!existsCheckFile(dir, fileBase, kind)) { - // diff is contents of logFile - diff = file2String(logFile) - } else - diff = compareOutput(dir, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck( + // diff is contents of logFile + if (!existsCheckFile(dir, fileBase, kind)) file2String(logFile) + else compareOutput(dir, fileBase, kind, logFile) + ) } }) @@ -499,7 +488,7 @@ class Worker(val fileManager: FileManager) extends Actor { case "buildmanager" => val logFile = createLogFile(file, kind) - if (!fileManager.failed || (logFile.exists && logFile.canRead)) { + if (!fileManager.failed || logFile.canRead) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true; diff = "" @@ -516,7 +505,7 @@ class Worker(val fileManager: FileManager) extends Actor { if (!outDir.exists) outDir.mkdir() val testFile = new File(file, fileBase + ".test") val changesDir = new File(file, fileBase + ".changes") - if ((changesDir.exists && !changesDir.isDirectory) || !testFile.exists || !testFile.isFile) { + if (changesDir.isFile || !testFile.isFile) { // if changes exists then it has to be a dir succeeded = false (null, null, null, null) @@ -570,7 +559,7 @@ class Worker(val fileManager: FileManager) extends Actor { (u split "=>").toList match { case origFileName::(newFileName::Nil) => val newFile = new File(changesDir, newFileName) - if (newFile.exists && newFile.isFile) { + if (newFile.isFile) { val v = overwriteFileWith(new File(outDir, origFileName), newFile) if (!v) NestUI.verbose("'update' operation on " + u + " failed") @@ -619,14 +608,9 @@ class Worker(val fileManager: FileManager) extends Actor { testReader.close() } - fileManager.mapFile(logFile, "tmp", file, {s => s.replace(sourcepath, "")}) - - diff = compareOutput(file, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + fileManager.mapFile(logFile, "tmp", file, _.replace(sourcepath, "")) + diffCheck(compareOutput(file, fileBase, kind, logFile)) } LogContext(logFile, Some((swr, wr))) } else @@ -641,7 +625,7 @@ class Worker(val fileManager: FileManager) extends Actor { //val (logFileOut, logFileErr) = createLogFiles(file, kind) val logFile = createLogFile(file, kind) - if (!fileManager.failed || (logFile.exists && logFile.canRead)) { + if (!fileManager.failed || logFile.canRead) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true; diff = ""; log = "" @@ -749,12 +733,7 @@ class Worker(val fileManager: FileManager) extends Actor { } fileManager.mapFile(logFile, "tmp", dir, replaceSlashes) - - diff = compareOutput(dir, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck(compareOutput(dir, fileBase, kind, logFile)) } catch { case e: Exception => @@ -772,7 +751,7 @@ class Worker(val fileManager: FileManager) extends Actor { // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file, kind) - if (!fileManager.failed || (logFile.exists && logFile.canRead)) { + if (!fileManager.failed || logFile.canRead) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true; diff = ""; log = "" @@ -825,11 +804,7 @@ class Worker(val fileManager: FileManager) extends Actor { succeeded = false } - diff = compareOutput(dir, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck(compareOutput(dir, fileBase, kind, logFile)) LogContext(logFile, Some((swr, wr))) } else @@ -883,11 +858,7 @@ class Worker(val fileManager: FileManager) extends Actor { case e: IOException => NestUI.verbose(e.getMessage()); succeeded = false } - val diff = fileManager.compareFiles(logFile, resFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck(fileManager.compareFiles(logFile, resFile)) } } }) @@ -898,7 +869,7 @@ class Worker(val fileManager: FileManager) extends Actor { // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file, kind) - if (!fileManager.failed || (logFile.exists && logFile.canRead)) { + if (!fileManager.failed || logFile.canRead) { val swr = new StringWriter val wr = new PrintWriter(swr) succeeded = true; diff = ""; log = "" @@ -920,7 +891,7 @@ class Worker(val fileManager: FileManager) extends Actor { try { val cmdString = - if (osName startsWith "Windows") { + if (isWin) { val batchFile = new File(file.getParentFile, fileBase+".bat") NestUI.verbose("batchFile: "+batchFile) batchFile.getAbsolutePath @@ -941,11 +912,7 @@ class Worker(val fileManager: FileManager) extends Actor { writer.close() - diff = compareOutput(file.getParentFile, fileBase, kind, logFile) - if (!diff.equals("")) { - NestUI.verbose("output differs from log file\n") - succeeded = false - } + diffCheck(compareOutput(file.getParentFile, fileBase, kind, logFile)) } catch { // *catch-all* case e: Exception => NestUI.verbose("caught "+e) diff --git a/src/partest/scala/tools/partest/package.scala b/src/partest/scala/tools/partest/package.scala index 9337d78ef4..1528c48f18 100644 --- a/src/partest/scala/tools/partest/package.scala +++ b/src/partest/scala/tools/partest/package.scala @@ -4,13 +4,15 @@ package scala.tools -import nsc.io.{ Directory } +import nsc.io.{ Path, Process, Directory } import util.{ PathResolver } import nsc.Properties.{ propOrElse, propOrNone, propOrEmpty } package object partest { import nest.NestUI + def basename(name: String): String = Path(name).stripExtension + object PartestDefaults { import nsc.Properties._ private def wrapAccessControl[T](body: => Option[T]): Option[T] = @@ -34,8 +36,6 @@ package object partest { } def vmArgString = { - import scala.tools.nsc.io.Process - val str = Process.javaVmArguments mkString " " "Java VM started with arguments: '%s'" format str } -- cgit v1.2.3