worker.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 698 行 · 第 1/2 页

SCALA
698
字号
/* NEST (New Scala Test) * @author Philipp Haller */// $Id: Worker.scala 14547 2008-04-07 16:34:10Z phaller $package scala.tools.partest.nestimport java.io.{File, FileInputStream, FileOutputStream, PrintStream,                PrintWriter, StringWriter, FileWriter, InputStreamReader,                FileReader, OutputStreamWriter, BufferedReader}import java.net.URLimport scala.tools.nsc.{ObjectRunner, GenericRunnerCommand}import scala.actors.Actorimport scala.actors.Actor._case class RunTests(kind: String, files: List[File])case class Results(succ: Int, fail: Int, logs: List[LogFile], outdirs: List[File])class LogFile(parent: File, child: String) extends File(parent, child) {  var toDelete = false}class Worker(val fileManager: FileManager) extends Actor {  import fileManager._  import scala.tools.nsc.{Settings, CompilerCommand, Global}  import scala.tools.nsc.reporters.ConsoleReporter  import scala.tools.nsc.util.FakePos  var reporter: ConsoleReporter = _  def error(msg: String) {    reporter.error(FakePos("scalac"),                   msg + "\n  scalac -help  gives more information")  }  def act() {    react {      case RunTests(kind, files) =>        NestUI.verbose("received "+files.length+" to test")        val (succ, fail) = runTests(kind, files)        sender ! Results(succ, fail, createdLogFiles, createdOutputDirs)    }  }  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    val testdir = filesdir.getParentFile    val totalWidth = 56    val name = {      // 1. try with [...]/files/run/test.scala      val testPathLen = testdir.getAbsolutePath.length      val name = file.getAbsolutePath.substring(testPathLen)      if (name.length <= totalWidth)        name      // 2. try with [...]/run/test.scala      else {        val filesPathLen = filesdir.getAbsolutePath.length        file.getAbsolutePath.substring(filesPathLen)      }    }    NestUI.normal("[...]"+name+List.toString(List.make(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)  }  var log = ""  var createdLogFiles: List[LogFile] = List()  var createdOutputDirs: List[File] = List()  def createLogFile(dir: File, fileBase: String, kind: String): LogFile = {    val logFile = new LogFile(dir, fileBase + "-" + kind + ".log")    createdLogFiles = logFile :: createdLogFiles    logFile  }  def createLogFile(file: File, kind: String): LogFile = {    val dir = file.getParentFile    val fileBase = basename(file.getName)    createLogFile(dir, fileBase, kind)  }  def createOutputDir(dir: File, fileBase: String, kind: String): File = {    val outDir = new File(dir, fileBase + "-" + kind + ".obj")    createdOutputDirs = outDir :: createdOutputDirs    outDir  }  /* Note: not yet used/tested. */  def execTestObjectRunner(file: File, outDir: File, logFile: File) {    val consFM = new ConsoleFileManager    import consFM.{latestCompFile, latestLibFile, latestActFile,                   latestPartestFile, latestFjbgFile}    val classpath: List[URL] =      outDir.toURL ::      //List(file.getParentFile.toURL) :::      List(latestCompFile.toURL, latestLibFile.toURL,           latestActFile.toURL, latestPartestFile.toURL,           latestFjbgFile.toURL) :::      (List.fromString(CLASSPATH, File.pathSeparatorChar) map { x =>        (new File(x)).toURL })    NestUI.verbose("ObjectRunner classpath: "+classpath)    try {      // configure input/output files      val logOut    = new FileOutputStream(logFile)      val logWriter = new PrintStream(logOut)      // grab global lock      fileManager.synchronized {        val oldStdOut = System.out        val oldStdErr = System.err        System.setOut(logWriter)        System.setErr(logWriter)        /*         " -Djava.library.path="+logFile.getParentFile.getAbsolutePath+         " -Dscalatest.output="+outDir.getAbsolutePath+         " -Dscalatest.lib="+LATEST_LIB+         " -Dscalatest.cwd="+outDir.getParent+         " -Djavacmd="+JAVACMD+         */        System.setProperty("java.library.path", logFile.getParentFile.getCanonicalFile.getAbsolutePath)        System.setProperty("scalatest.output", outDir.getCanonicalFile.getAbsolutePath)        System.setProperty("scalatest.lib", LATEST_LIB)        System.setProperty("scalatest.cwd", outDir.getParent)        ObjectRunner.run(classpath, "Test", List("jvm"))        logWriter.flush()        logWriter.close()        System.setOut(oldStdOut)        System.setErr(oldStdErr)      }      /*val out = new FileOutputStream(logFile, true)      Console.withOut(new PrintStream(out)) {        ObjectRunner.run(classpath, "Test", List("jvm"))      }      out.flush      out.close*/    } catch {      case e: Exception =>        NestUI.verbose(e+" ("+file.getPath+")")        e.printStackTrace()    }  }  def execTest(outDir: File, logFile: File, fileBase: String) {    // check whether there is a ".javaopts" file    val argsFile = new File(logFile.getParentFile, fileBase+".javaopts")    val argString = if (argsFile.exists) {      NestUI.verbose("argsFile: "+argsFile)      val fileReader = new FileReader(argsFile)      val reader = new BufferedReader(fileReader)      val options = reader.readLine()      reader.close()      options    } else ""    NestUI.verbose("JAVA_OPTS: "+argString)    def quote(path: String) = "\""+path+"\""    val cmd =      JAVACMD+      " "+argString+      " -classpath "+outDir+File.pathSeparator+CLASSPATH+      " -Djava.library.path="+logFile.getParentFile.getAbsolutePath+      " -Dscalatest.output="+outDir.getAbsolutePath+      " -Dscalatest.lib="+LATEST_LIB+      " -Dscalatest.cwd="+outDir.getParent+      " -Djavacmd="+JAVACMD+      " scala.tools.nsc.MainGenericRunner"+      " Test jvm"    NestUI.verbose(cmd)    val proc = Runtime.getRuntime.exec(cmd)    val in = proc.getInputStream    val err = proc.getErrorStream    val writer = new PrintWriter(new FileWriter(logFile), true)    val inApp = new StreamAppender(new BufferedReader(new InputStreamReader(in)),                                   writer)    val errApp = new StreamAppender(new BufferedReader(new InputStreamReader(err)),                                    writer)    val async = new Thread(errApp)    async.start()    inApp.run()    async.join()    writer.close()    if (fileManager.showLog) {      // produce log as string in `log`      val reader = new BufferedReader(new FileReader(logFile))      val swriter = new StringWriter      val pwriter = new PrintWriter(swriter, true)      val appender = new StreamAppender(reader, writer)      appender.run()      log = swriter.toString    }  }  def existsCheckFile(dir: File, fileBase: String, kind: String) = {    val checkFile = {      val chkFile = new File(dir, fileBase + ".check")      if (chkFile.isFile)        chkFile      else        new File(dir, fileBase + "-" + kind + ".check")    }    checkFile.exists && checkFile.canRead  }  def compareOutput(dir: File, fileBase: String, kind: String, logFile: File): String = {    // if check file exists, compare with log file    val checkFile = {      val chkFile = new File(dir, fileBase + ".check")      if (chkFile.isFile)        chkFile      else        new File(dir, fileBase + "-" + kind + ".check")    }    if (!checkFile.exists || !checkFile.canRead) ""    else fileManager.compareFiles(logFile, checkFile)  }  def file2String(logFile: File) = {    val logReader = new BufferedReader(new FileReader(logFile))    val strWriter = new StringWriter    val logWriter = new PrintWriter(strWriter, true)    val logAppender = new StreamAppender(logReader, logWriter)    logAppender.run()    logReader.close()    strWriter.toString  }  /** Runs a list of tests.   *   * @param kind  The test kind (pos, neg, run, etc.)   * @param files The list of test files   */  def runTests(kind: String, files: List[File]): (Int, Int) = {    val compileMgr = new CompileManager(fileManager)    var errors = 0    var succeeded = true    var diff = ""    var log = ""    def runInContext(file: File, kind: String, script: (File, File) => Unit) {      // when option "--failed" is provided      // 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)) {        val swr = new StringWriter        val wr = new PrintWriter(swr)        succeeded = true        diff = ""        log = ""        printInfoStart(file, wr)        val fileBase: String = basename(file.getName)        NestUI.verbose(this+" running test "+fileBase)        val dir = file.getParentFile        val outDir = createOutputDir(dir, fileBase, kind)        // run test-specific code        try {          script(logFile, outDir)        } catch {          case e: Exception =>            e.printStackTrace            succeeded = false        }        if (!succeeded) {          errors += 1          NestUI.verbose("incremented errors: "+errors)        } else {          // delete log file only if test was successful          logFile.toDelete = true        }        printInfoEnd(succeeded, wr)        wr.flush()        swr.flush() //TODO: needed?        NestUI.normal(swr.toString)        if (!succeeded && fileManager.showDiff && diff != "")          NestUI.normal(diff)        else if (!succeeded && fileManager.showLog)          showLog(logFile)      }    }    def runJvmTest(file: File, kind: String) {      runInContext(file, kind, (logFile: File, outDir: File) => {        if (!compileMgr.shouldCompile(file, kind, logFile)) {          NestUI.verbose("compilation of "+file+" failed\n")          succeeded = false        } else { // run test          val fileBase = basename(file.getName)          val dir      = file.getParentFile          //TODO: detect whether we have to use Runtime.exec          val useRuntime = true          if (useRuntime)            execTest(outDir, logFile, fileBase)          else            execTestObjectRunner(file, outDir, logFile)          NestUI.verbose(this+" finished running "+fileBase)          diff = compareOutput(dir, fileBase, kind, logFile)          if (!diff.equals("")) {            NestUI.verbose("output differs from log file\n")            succeeded = false          }        }      })    }    kind match {      case "pos" =>        for (file <- files) {          runInContext(file, kind, (logFile: File, outDir: File) => {            if (!compileMgr.shouldCompile(file, kind, logFile)) {              NestUI.verbose("compilation of "+file+" failed\n")              succeeded = false            }          })        }      case "neg" =>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?