|
Scala example source code file (Worker.scala)
The Scala Worker.scala source code/* NEST (New Scala Test) * Copyright 2007-2011 LAMP/EPFL * @author Philipp Haller */ // $Id$ package scala.tools.partest package nest import java.io._ import java.net.URL import java.util.{ Timer, TimerTask } import scala.util.Properties.{ 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.actors.{ Actor, Exit, TIMEOUT } import scala.actors.Actor._ import scala.tools.scalap.scalax.rules.scalasig.ByteCode import scala.collection.{ mutable, immutable } import scala.tools.nsc.interactive.{ BuildManager, RefinedBuildManager } import scala.sys.process._ case class RunTests(kind: String, files: List[File]) case class Results(results: Map[String, Int]) class LogContext(val file: File, val writers: Option[(StringWriter, PrintWriter)]) object LogContext { def apply(file: File, swr: StringWriter, wr: PrintWriter): LogContext = { require (file != null) new LogContext(file, Some((swr, wr))) } def apply(file: File): LogContext = new LogContext(file, None) } abstract class TestResult { def file: File } case class Result(override val file: File, context: LogContext) extends TestResult case class Timeout(override val file: File) extends TestResult class ScalaCheckFileManager(val origmanager: FileManager) extends FileManager { def testRootDir: Directory = origmanager.testRootDir def testRootPath: String = origmanager.testRootPath var JAVACMD: String = origmanager.JAVACMD var JAVAC_CMD: String = origmanager.JAVAC_CMD var CLASSPATH: String = join(origmanager.CLASSPATH, PathSettings.scalaCheck.path) var LATEST_LIB: String = origmanager.LATEST_LIB } object Output { def init() { System.setOut(outRedirect) System.setErr(errRedirect) } import scala.util.DynamicVariable private def out = java.lang.System.out private def err = java.lang.System.err private val redirVar = new DynamicVariable[Option[PrintStream]](None) class Redirecter(stream: PrintStream) extends PrintStream(new OutputStream { def write(b: Int) = withStream(_ write b) private def withStream(f: PrintStream => Unit) = f(redirVar.value getOrElse stream) override def write(b: Array[Byte]) = withStream(_ write b) override def write(b: Array[Byte], off: Int, len: Int) = withStream(_.write(b, off, len)) override def flush = withStream(_.flush) override def close = withStream(_.close) }) object outRedirect extends Redirecter(out) object errRedirect extends Redirecter(err) // this supports thread-safe nested output redirects def withRedirected[T](newstream: PrintStream)(func: => T): T = { // note down old redirect destination // this may be None in which case outRedirect and errRedirect print to stdout and stderr val saved = redirVar.value // set new redirecter // this one will redirect both out and err to newstream redirVar.value = Some(newstream) try func finally { newstream.flush() redirVar.value = saved } } } class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor { import fileManager._ val scalaCheckFileManager = new ScalaCheckFileManager(fileManager) var reporter: ConsoleReporter = _ val timer = new Timer val javacCmd = if ((fileManager.JAVAC_CMD.indexOf("${env.JAVA_HOME}") != -1) || fileManager.JAVAC_CMD.equals("/bin/javac") || fileManager.JAVAC_CMD.equals("\\bin\\javac")) "javac" else fileManager.JAVAC_CMD def cancelTimerTask() = if (currentTimerTask != null) currentTimerTask.cancel() def updateTimerTask(body: => Unit) = { cancelTimerTask() currentTimerTask = new KickableTimerTask(body) timer.schedule(currentTimerTask, fileManager.oneTestTimeout) } class KickableTimerTask(body: => Unit) extends TimerTask { def run() = body def kick() = { cancel() body } } /** Formerly deeper inside, these next few things are now promoted outside so * I can see what they're doing when the world comes to a premature stop. */ private var filesRemaining: List[File] = Nil private val toDelete = new mutable.HashSet[File] private val status = new mutable.HashMap[String, Int] private var currentTimerTask: KickableTimerTask = _ private var currentFileStart: Long = System.currentTimeMillis private var currentTestFile: File = _ private var kind: String = "" private def fileBase = basename(currentTestFile.getName) private def compareFiles(f1: File, f2: File): String = try fileManager.compareFiles(f1, f2) catch { case t => t.toString } // maps canonical file names to the test result (0: OK, 1: FAILED, 2: TIMOUT) private def updateStatus(key: String, num: Int) = status(key) = num private def cleanup() { toDelete foreach (_.deleteRecursively()) toDelete.clear() } sys addShutdownHook cleanup() private def resetAll() { cancelTimerTask() filesRemaining = Nil cleanup() status.clear() currentTestFile = null currentTimerTask = null } def currentFileElapsed = (System.currentTimeMillis - currentFileStart) / 1000 def forceTimeout() = { println("Let's see what them threads are doing before I kill that test.") sys.allThreads foreach { t => println(t) t.getStackTrace foreach println println("") } currentTimerTask.kick() } /** This does something about absolute paths and file separator * chars before diffing. */ // private def replaceSlashes(dir: File, s: String): String = { val base = (dir.getAbsolutePath + File.separator).replace('\\', '/') s.replace('\\', '/').replaceAll("""\Q%s\E""" format base, "") } private def currentFileString = { "Current test file is: %s\n Started: %s (%s seconds ago)\n Current time: %s".format( currentTestFile, new java.util.Date(currentFileStart), currentFileElapsed, new java.util.Date() ) } private def getNextFile(): File = { if (filesRemaining.isEmpty) { currentTestFile = null } else { currentTestFile = filesRemaining.head filesRemaining = filesRemaining.tail currentFileStart = System.currentTimeMillis } currentTestFile } override def toString = ( ">> Partest Worker in state " + getState + ":\n" + currentFileString + "\n" + "There are " + filesRemaining.size + " files remaining:\n" + "\nstatus hashmap contains " + status.size + " entries:\n" + status.toList.map(x => " " + x._1 + " -> " + x._2).sorted.mkString("\n") + "\n" ) def workerError(msg: String): Unit = reporter.error( FakePos("scalac"), msg + "\n scalac -help gives more information" ) def act() { react { case RunTests(testKind, files) => val master = sender kind = testKind runTests(files) { results => master ! Results(results.toMap) resetAll() } } } def printInfoStart(file: File, printer: PrintWriter) { NestUI.outline("testing: ", printer) val filesdir = file.getAbsoluteFile.getParentFile.getParentFile val testdir = filesdir.getParentFile val totalWidth = 56 val name = { // 1. try with [...]/files/run/test.scala val name = file.getAbsolutePath drop testdir.getAbsolutePath.length if (name.length <= totalWidth) name // 2. try with [...]/run/test.scala else file.getAbsolutePath drop filesdir.getAbsolutePath.length } NestUI.normal("[...]%s%s".format(name, " " * (totalWidth - name.length)), printer) } def printInfoEnd(success: Boolean, printer: PrintWriter) { NestUI.normal("[", printer) if (success) NestUI.success(" OK ", printer) else NestUI.failure("FAILED", printer) NestUI.normal("]\n", printer) } def printInfoTimeout(printer: PrintWriter) { NestUI.normal("[", printer) NestUI.failure("TIMOUT", printer) NestUI.normal("]\n", printer) } def createLogFile(file: File) = fileManager.getLogFile(file, kind) def createOutputDir(dir: File): File = { val outDir = Path(dir) / Directory("%s-%s.obj".format(fileBase, kind)) outDir.createDirectory() toDelete += outDir.jfile outDir.jfile } def javac(outDir: File, files: List[File], output: File): Boolean = { // compile using command-line javac compiler val cmd = "%s -d %s -classpath %s %s".format( javacCmd, outDir.getAbsolutePath, join(outDir.toString, CLASSPATH), files mkString " " ) try runCommand(cmd, output) catch exHandler(output, "javac command '" + cmd + "' failed:\n") } /** Runs command redirecting standard out and * error out to output file. */ def runCommand(command: String, outFile: File): Boolean = { NestUI.verbose("running command:\n"+command) (command #> outFile !) == 0 } def execTest(outDir: File, logFile: File, classpathPrefix: String = ""): Boolean = { // check whether there is a ".javaopts" file val argsFile = new File(logFile.getParentFile, fileBase + ".javaopts") val argString = file2String(argsFile) if (argString != "") NestUI.verbose("Found javaopts file '%s', using options: '%s'".format(argsFile, argString)) // Note! As this currently functions, JAVA_OPTS must precede argString // because when an option is repeated to java only the last one wins. // That means until now all the .javaopts files were being ignored because // they all attempt to change options which are also defined in // partest.java_opts, leading to debug output like: // // debug: Found javaopts file 'files/shootout/message.scala-2.javaopts', using options: '-Xss32k' // debug: java -Xss32k -Xss2m -Xms256M -Xmx1024M -classpath [...] val extras = if (isPartestDebug) List("-Dpartest.debug=true") else Nil val propertyOptions = List( "-Djava.library.path="+logFile.getParentFile.getAbsolutePath, "-Dpartest.output="+outDir.getAbsolutePath, "-Dpartest.lib="+LATEST_LIB, "-Dpartest.cwd="+outDir.getParent, "-Dpartest.testname="+fileBase, "-Djavacmd="+JAVACMD, "-Djavaccmd="+javacCmd, "-Duser.language=en -Duser.country=US" ) ++ extras val classpath = if (classpathPrefix != "") join(classpathPrefix, CLASSPATH) else CLASSPATH val cmd = ( List( JAVACMD, JAVA_OPTS, argString, "-classpath " + join(outDir.toString, classpath) ) ++ propertyOptions ++ List( "scala.tools.nsc.MainGenericRunner", "-usejavacp", "Test", "jvm" ) ) mkString " " runCommand(cmd, logFile) } def getCheckFilePath(dir: File, suffix: String = "") = { def chkFile(s: String) = (Directory(dir) / "%s%s.check".format(fileBase, s)).toFile if (chkFile("").isFile || suffix == "") chkFile("") else chkFile("-" + suffix) } def getCheckFile(dir: File) = Some(getCheckFilePath(dir, kind)) filter (_.canRead) def compareOutput(dir: File, logFile: File): String = { val checkFile = getCheckFilePath(dir, kind) // if check file exists, compare with log file val diff = if (checkFile.canRead) compareFiles(logFile, checkFile.jfile) else file2String(logFile) if (diff != "" && fileManager.updateCheck) { NestUI.verbose("output differs from log file: updating checkfile\n") val toWrite = if (checkFile.exists) checkFile else getCheckFilePath(dir, "") toWrite writeAll file2String(logFile) "" } else diff } def isJava(f: File) = SFile(f) hasExtension "java" def isScala(f: File) = SFile(f) hasExtension "scala" def isJavaOrScala(f: File) = isJava(f) || isScala(f) def outputLogFile(logFile: File) { val lines = SFile(logFile).lines if (lines.nonEmpty) { NestUI.normal("Log file '" + logFile + "': \n") lines foreach (x => NestUI.normal(x + "\n")) } } def logStackTrace(logFile: File, t: Throwable, msg: String): Boolean = { SFile(logFile).writeAll(msg, stackTraceString(t)) outputLogFile(logFile) // if running the test threw an exception, output log file false } def exHandler(logFile: File): PartialFunction[Throwable, Boolean] = exHandler(logFile, "") def exHandler(logFile: File, msg: String): PartialFunction[Throwable, Boolean] = { case e: Exception => logStackTrace(logFile, e, msg) } /** Runs a list of tests. * * @param files The list of test files */ def runTests(files: List[File])(topcont: Map[String, Int] => Unit) { val compileMgr = new CompileManager(fileManager) if (kind == "scalacheck") fileManager.CLASSPATH += File.pathSeparator + PathSettings.scalaCheck filesRemaining = files // You don't default "succeeded" to true. var succeeded = false var done = filesRemaining.isEmpty var errors = 0 var diff = "" def initNextTest() = { val swr = new StringWriter val wr = new PrintWriter(swr, true) diff = "" ((swr, wr)) } def fail(what: Any) = { NestUI.verbose("scalac: compilation of "+what+" failed\n") false } def diffCheck(latestDiff: String) = { diff = latestDiff succeeded = diff == "" succeeded } def timed[T](body: => T): (T, Long) = { val t1 = System.currentTimeMillis val result = body val t2 = System.currentTimeMillis (result, t2 - t1) } /** 1. Creates log file and output directory. * 2. Runs script function, providing log file and output directory as arguments. */ def runInContext(file: File, script: (File, File) => Boolean): LogContext = { // When option "--failed" is provided, execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file) if (fileManager.failed && !logFile.canRead) LogContext(logFile) else { val (swr, wr) = initNextTest() printInfoStart(file, wr) NestUI.verbose(this+" running test "+fileBase) val dir = file.getParentFile val outDir = createOutputDir(dir) NestUI.verbose("output directory: "+outDir) // run test-specific code succeeded = try { if (isPartestDebug) { val (result, millis) = timed(script(logFile, outDir)) fileManager.recordTestTiming(file.getPath, millis) result } else script(logFile, outDir) } catch exHandler(logFile) LogContext(logFile, swr, wr) } } def compileFilesIn(dir: File, logFile: File, outDir: File): Boolean = { val testFiles = dir.listFiles.toList filter isJavaOrScala def isInGroup(f: File, num: Int) = SFile(f).stripExtension endsWith ("_" + num) val groups = (0 to 9).toList map (num => testFiles filter (f => isInGroup(f, num))) val noGroupSuffix = testFiles filterNot (groups.flatten contains) def compileGroup(g: List[File]): Boolean = { val (scalaFiles, javaFiles) = g partition isScala val allFiles = javaFiles ++ scalaFiles // scala+java, then java, then scala (scalaFiles.isEmpty || compileMgr.shouldCompile(outDir, allFiles, kind, logFile) || fail(g)) && { (javaFiles.isEmpty || javac(outDir, javaFiles, logFile)) && { (scalaFiles.isEmpty || compileMgr.shouldCompile(outDir, scalaFiles, kind, logFile) || fail(scalaFiles)) } } } (noGroupSuffix.isEmpty || compileGroup(noGroupSuffix)) && (groups forall compileGroup) } def failCompileFilesIn(dir: File, logFile: File, outDir: File): Boolean = { val testFiles = dir.listFiles.toList val sourceFiles = testFiles filter isJavaOrScala sourceFiles.isEmpty || compileMgr.shouldFailCompile(outDir, sourceFiles, kind, logFile) || fail(testFiles filter isScala) } def runTestCommon(file: File, expectFailure: Boolean)( onSuccess: (File, File) => Boolean, onFail: (File, File) => Unit = (_, _) => ()): LogContext = { runInContext(file, (logFile: File, outDir: File) => { val result = if (file.isDirectory) { if (expectFailure) failCompileFilesIn(file, logFile, outDir) else compileFilesIn(file, logFile, outDir) } else { if (expectFailure) compileMgr.shouldFailCompile(List(file), kind, logFile) else compileMgr.shouldCompile(List(file), kind, logFile) } if (result) onSuccess(logFile, outDir) else { onFail(logFile, outDir) ; false } }) } def runJvmTest(file: File): LogContext = runTestCommon(file, expectFailure = false)((logFile, outDir) => { val dir = file.getParentFile execTest(outDir, logFile) && diffCheck(compareOutput(dir, logFile)) }) def runSpecializedTest(file: File): LogContext = runTestCommon(file, expectFailure = false)((logFile, outDir) => { val dir = file.getParentFile // adding the instrumented library to the classpath execTest(outDir, logFile, PathSettings.srcSpecLib.toString) && diffCheck(compareOutput(dir, logFile)) }) def processSingleFile(file: File): LogContext = kind match { case "scalacheck" => val succFn: (File, File) => Boolean = { (logFile, outDir) => NestUI.verbose("compilation of "+file+" succeeded\n") val outURL = outDir.getAbsoluteFile.toURI.toURL val logWriter = new PrintStream(new FileOutputStream(logFile), true) Output.withRedirected(logWriter) { // this classloader is test specific: its parent contains library classes and others ScalaClassLoader.fromURLs(List(outURL), params.scalaCheckParentClassLoader).run("Test", Nil) } NestUI.verbose(file2String(logFile)) // obviously this must be improved upon val lines = SFile(logFile).lines map (_.trim) filterNot (_ == "") toBuffer; if (lines forall (x => !x.startsWith("!"))) { NestUI.verbose("test for '" + file + "' success: " + succeeded) true } else { NestUI.normal("ScalaCheck test failed. Output:\n") lines foreach (x => NestUI.normal(x + "\n")) false } } runTestCommon(file, expectFailure = false)( succFn, (logFile, outDir) => outputLogFile(logFile) ) case "pos" => runTestCommon(file, expectFailure = false)( (logFile, outDir) => true, (_, _) => () ) case "neg" => runTestCommon(file, expectFailure = true)((logFile, outDir) => { // compare log file to check file val dir = file.getParentFile // diff is contents of logFile diffCheck(compareOutput(dir, logFile)) }) case "run" | "jvm" => runJvmTest(file) case "specialized" => runSpecializedTest(file) case "presentation" => runJvmTest(file) // for the moment, it's exactly the same as for a run test case "buildmanager" => val logFile = createLogFile(file) if (!fileManager.failed || logFile.canRead) { val (swr, wr) = initNextTest() printInfoStart(file, wr) val (outDir, testFile, changesDir) = ( if (!file.isDirectory) (null, null, null) else { NestUI.verbose(this+" running test "+fileBase) val outDir = createOutputDir(file) val testFile = new File(file, fileBase + ".test") val changesDir = new File(file, fileBase + ".changes") if (changesDir.isFile || !testFile.isFile) { // if changes exists then it has to be a dir if (!testFile.isFile) NestUI.verbose("invalid build manager test file") if (changesDir.isFile) NestUI.verbose("invalid build manager changes directory") (null, null, null) } else { copyTestFiles(file, outDir) NestUI.verbose("outDir: "+outDir) NestUI.verbose("logFile: "+logFile) (outDir, testFile, changesDir) } } ) if (outDir != null) { // Pre-conditions satisfied try { val sourcepath = outDir.getAbsolutePath+File.separator // configure input/output files val logWriter = new PrintStream(new FileOutputStream(logFile), true) val testReader = new BufferedReader(new FileReader(testFile)) val logConsoleWriter = new PrintWriter(logWriter, true) // create proper settings for the compiler val settings = new Settings(workerError) settings.outdir.value = outDir.getAbsoluteFile.getAbsolutePath settings.sourcepath.value = sourcepath settings.classpath.value = fileManager.CLASSPATH settings.Ybuildmanagerdebug.value = true // simulate Build Manager loop val prompt = "builder > " reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter) val bM: BuildManager = new RefinedBuildManager(settings) { override protected def newCompiler(settings: Settings) = new BuilderGlobal(settings, reporter) } def testCompile(line: String): Boolean = { NestUI.verbose("compiling " + line) val args = (line split ' ').toList val command = new CompilerCommand(args, settings) command.ok && { bM.update(filesToSet(settings.sourcepath.value, command.files), Set.empty) !reporter.hasErrors } } val updateFiles = (line: String) => { NestUI.verbose("updating " + line) val res = ((line split ' ').toList).forall(u => { (u split "=>").toList match { case origFileName::(newFileName::Nil) => val newFile = new File(changesDir, newFileName) if (newFile.isFile) { val v = overwriteFileWith(new File(outDir, origFileName), newFile) if (!v) NestUI.verbose("'update' operation on " + u + " failed") v } else { NestUI.verbose("File " + newFile + " is invalid") false } case a => NestUI.verbose("Other =: " + a) false } }) NestUI.verbose("updating " + (if (res) "succeeded" else "failed")) res } def loop(): Boolean = { testReader.readLine() match { case null | "" => NestUI.verbose("finished") true case s if s startsWith ">>update " => updateFiles(s stripPrefix ">>update ") && loop() case s if s startsWith ">>compile " => val files = s stripPrefix ">>compile " logWriter.println(prompt + files) // In the end, it can finish with an error if (testCompile(files)) loop() else { val t = testReader.readLine() (t == null) || (t == "") } case s => NestUI.verbose("wrong command in test file: " + s) false } } Output.withRedirected(logWriter) { try loop() finally testReader.close() } fileManager.mapFile(logFile, replaceSlashes(new File(sourcepath), _)) diffCheck(compareOutput(file, logFile)) } LogContext(logFile, swr, wr) } else LogContext(logFile) } else LogContext(logFile) case "res" => { // simulate resident compiler loop val prompt = "\nnsc> " // when option "--failed" is provided // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file) if (!fileManager.failed || logFile.canRead) { val (swr, wr) = initNextTest() printInfoStart(file, wr) NestUI.verbose(this+" running test "+fileBase) val dir = file.getParentFile val outDir = createOutputDir(dir) val resFile = new File(dir, fileBase + ".res") NestUI.verbose("outDir: "+outDir) NestUI.verbose("logFile: "+logFile) //NestUI.verbose("logFileErr: "+logFileErr) NestUI.verbose("resFile: "+resFile) // run compiler in resident mode // $SCALAC -d "$os_dstbase".obj -Xresident -sourcepath . "$@" val sourcedir = logFile.getParentFile.getAbsoluteFile val sourcepath = sourcedir.getAbsolutePath+File.separator NestUI.verbose("sourcepath: "+sourcepath) val argString = "-d "+outDir.getAbsoluteFile.getPath+ " -Xresident"+ " -sourcepath "+sourcepath val argList = argString split ' ' toList // configure input/output files val logOut = new FileOutputStream(logFile) val logWriter = new PrintStream(logOut, true) val resReader = new BufferedReader(new FileReader(resFile)) val logConsoleWriter = new PrintWriter(new OutputStreamWriter(logOut), true) // create compiler val settings = new Settings(workerError) settings.sourcepath.value = sourcepath settings.classpath.value = fileManager.CLASSPATH reporter = new ConsoleReporter(settings, scala.Console.in, logConsoleWriter) val command = new CompilerCommand(argList, settings) object compiler extends Global(command.settings, reporter) val resCompile = (line: String) => { NestUI.verbose("compiling "+line) val cmdArgs = (line split ' ').toList map (fs => new File(dir, fs).getAbsolutePath) NestUI.verbose("cmdArgs: "+cmdArgs) val sett = new Settings(workerError) sett.sourcepath.value = sourcepath val command = new CompilerCommand(cmdArgs, sett) command.ok && { (new compiler.Run) compile command.files !reporter.hasErrors } } def loop(action: String => Boolean): Boolean = { logWriter.print(prompt) resReader.readLine() match { case null | "" => logWriter.flush() ; true case line => action(line) && loop(action) } } Output.withRedirected(logWriter) { try loop(resCompile) finally resReader.close() } fileManager.mapFile(logFile, replaceSlashes(dir, _)) diffCheck(compareOutput(dir, logFile)) LogContext(logFile, swr, wr) } else LogContext(logFile) } case "shootout" => { // when option "--failed" is provided // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file) if (!fileManager.failed || logFile.canRead) { val (swr, wr) = initNextTest() printInfoStart(file, wr) NestUI.verbose(this+" running test "+fileBase) val dir = file.getParentFile val outDir = createOutputDir(dir) // 2. define file {outDir}/test.scala that contains code to compile/run val testFile = new File(outDir, "test.scala") NestUI.verbose("outDir: "+outDir) NestUI.verbose("logFile: "+logFile) NestUI.verbose("testFile: "+testFile) // 3. cat {test}.scala.runner {test}.scala > testFile val runnerFile = new File(dir, fileBase+".scala.runner") val bodyFile = new File(dir, fileBase+".scala") SFile(testFile).writeAll( file2String(runnerFile), file2String(bodyFile) ) // 4. compile testFile val ok = compileMgr.shouldCompile(List(testFile), kind, logFile) NestUI.verbose("compilation of " + testFile + (if (ok) "succeeded" else "failed")) if (ok) { execTest(outDir, logFile) && { NestUI.verbose(this+" finished running "+fileBase) diffCheck(compareOutput(dir, logFile)) } } LogContext(logFile, swr, wr) } else LogContext(logFile) } case "scalap" => runInContext(file, (logFile: File, outDir: File) => { val sourceDir = Directory(if (file.isFile) file.getParent else file) val sources = sourceDir.files filter (_ hasExtension "scala") map (_.jfile) toList val results = sourceDir.files filter (_.name == "result.test") map (_.jfile) toList if (sources.length != 1 || results.length != 1) { NestUI.warning("Misconfigured scalap test directory: " + sourceDir + " \n") false } else { val resFile = results.head // 2. Compile source file if (!compileMgr.shouldCompile(outDir, sources, kind, logFile)) { NestUI.normal("compilerMgr failed to compile %s to %s".format(sources mkString ", ", outDir)) false } else { // 3. Decompile file and compare results val isPackageObject = sourceDir.name startsWith "package" val className = sourceDir.name.capitalize + (if (!isPackageObject) "" else ".package") val url = outDir.toURI.toURL val loader = ScalaClassLoader.fromURLs(List(url), this.getClass.getClassLoader) val clazz = loader.loadClass(className) val byteCode = ByteCode.forClass(clazz) val result = scala.tools.scalap.Main.decompileScala(byteCode.bytes, isPackageObject) SFile(logFile) writeAll result diffCheck(compareFiles(logFile, resFile)) } } }) case "script" => { // when option "--failed" is provided // execute test only if log file is present // (which means it failed before) val logFile = createLogFile(file) if (!fileManager.failed || logFile.canRead) { val (swr, wr) = initNextTest() printInfoStart(file, wr) NestUI.verbose(this+" running test "+fileBase) // check whether there is an args file val argsFile = new File(file.getParentFile, fileBase+".args") NestUI.verbose("argsFile: "+argsFile) val argString = file2String(argsFile) try { val cmdString = if (isWin) { val batchFile = new File(file.getParentFile, fileBase+".bat") NestUI.verbose("batchFile: "+batchFile) batchFile.getAbsolutePath } else file.getAbsolutePath succeeded = ((cmdString+argString) #> logFile !) == 0 diffCheck(compareOutput(file.getParentFile, logFile)) } catch { // *catch-all* case e: Exception => NestUI.verbose("caught "+e) succeeded = false } LogContext(logFile, swr, wr) } else LogContext(logFile) } } def reportAll(results: Map[String, Int], cont: Map[String, Int] => Unit) { timer.cancel() cont(results) } object TestState { val Ok = 0 val Fail = 1 val Timeout = 2 } def reportResult(state: Int, logFile: File, writers: Option[(StringWriter, PrintWriter)]) { val isGood = state == TestState.Ok val isFail = state == TestState.Fail val isTimeout = state == TestState.Timeout val hasLog = logFile != null if (isGood) { // add logfile from deletion list if test passed if (hasLog) toDelete += logFile } else { errors += 1 NestUI.verbose("incremented errors: "+errors) } writers foreach { case (swr, wr) => if (isTimeout) printInfoTimeout(wr) else printInfoEnd(isGood, wr) wr.flush() swr.flush() NestUI.normal(swr.toString) if (isFail) { if ((fileManager.showDiff || isPartestDebug) && diff != "") NestUI.normal(diff) else if (fileManager.showLog) showLog(logFile) } } cleanup() } def finish() = { done = true cancelTimerTask() reportAll(status.toMap, topcont) } Actor.loopWhile(!done) { val parent = self actor { val testFile = getNextFile() if (testFile == null) finish() else { updateTimerTask(parent ! Timeout(testFile)) val context = try processSingleFile(testFile) catch { case t => succeeded = false try { val logFile = createLogFile(testFile) logStackTrace(logFile, t, "Possible compiler crash during test of: " + testFile + "\n") LogContext(logFile) } catch { case t => LogContext(null) } } parent ! Result(testFile, context) } } react { case Timeout(file) => updateStatus(file.getAbsolutePath, TestState.Timeout) val swr = new StringWriter val wr = new PrintWriter(swr, true) printInfoStart(file, wr) reportResult( TestState.Timeout, null, Some((swr, wr)) ) case Result(file, logs) => val state = if (succeeded) TestState.Ok else TestState.Fail updateStatus(file.getAbsolutePath, state) reportResult( state, logs.file, logs.writers ) } } } private def filesToSet(pre: String, fs: List[String]): Set[AbstractFile] = fs flatMap (s => Option(AbstractFile getFile (pre + s))) toSet private def copyTestFiles(testDir: File, destDir: File) { val invalidExts = List("changes", "svn", "obj") testDir.listFiles.toList filter ( f => (isJavaOrScala(f) && f.isFile) || (f.isDirectory && !(invalidExts.contains(SFile(f).extension)))) foreach { f => fileManager.copyFile(f, destDir) } } def showLog(logFile: File) { file2String(logFile) match { case "" if logFile.canRead => () case "" => NestUI.failure("Couldn't open log file: " + logFile + "\n") case s => NestUI.normal(s) } } } Other Scala examples (source code examples)Here is a short list of links related to this Scala Worker.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.