summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Haller <hallerp@gmail.com>2008-02-25 20:39:53 +0000
committerPhilipp Haller <hallerp@gmail.com>2008-02-25 20:39:53 +0000
commit0c6ab69119308a4248e416ce325d1a9e1c649516 (patch)
tree9a4718fe03c2d44b6a905bdd99671c95ea9f77dc
parent1bfbf4d63c24c429ad58332f67d661c004313268 (diff)
downloadscala-0c6ab69119308a4248e416ce325d1a9e1c649516.tar.gz
scala-0c6ab69119308a4248e416ce325d1a9e1c649516.tar.bz2
scala-0c6ab69119308a4248e416ce325d1a9e1c649516.zip
Fixed #535 and #539
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala59
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala11
-rw-r--r--src/partest/scala/tools/partest/nest/NestRunner.scala11
-rw-r--r--src/partest/scala/tools/partest/nest/StreamAppender.scala2
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala241
5 files changed, 244 insertions, 80 deletions
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 81bbf076db..3f9a20959d 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -8,7 +8,6 @@ import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.reporters.{Reporter, ConsoleReporter}
import java.io.{File, BufferedReader, PrintWriter, FileWriter}
-import java.net.URLClassLoader
class ExtConsoleReporter(override val settings: Settings, reader: BufferedReader, var writer: PrintWriter) extends ConsoleReporter(settings, reader, writer) {
def this(settings: Settings) = {
@@ -106,10 +105,13 @@ class DirectCompiler extends SimpleCompiler {
}
class ReflectiveCompiler extends SimpleCompiler {
- import FileManager.{latestCompFile, latestPartestFile}
+ import FileManager.{latestCompFile, latestPartestFile, latestFjbgFile}
- val sepUrls = Array(latestCompFile.toURL, latestPartestFile.toURL)
- val sepLoader = new URLClassLoader(sepUrls)
+ val sepUrls = Array(latestCompFile.toURL, latestPartestFile.toURL,
+ latestFjbgFile.toURL)
+ //NestUI.verbose("constructing URLClassLoader from URLs "+latestCompFile+" and "+latestPartestFile)
+
+ val sepLoader = new java.net.URLClassLoader(sepUrls, null)
val sepCompilerClass =
sepLoader.loadClass("scala.tools.partest.nest.DirectCompiler")
@@ -123,12 +125,22 @@ class ReflectiveCompiler extends SimpleCompiler {
val sepCompileMethod2 =
sepCompilerClass.getMethod("compile", Array(fileClass, stringClass, fileClass))
+ /* This method throws java.lang.reflect.InvocationTargetException
+ * if the compiler crashes.
+ * This exception is handled in the shouldCompile and shouldFailCompile
+ * methods of class CompileManager.
+ */
def compile(file: File, kind: String): Boolean = {
val fileArgs: Array[AnyRef] = Array(file, kind)
val res = sepCompileMethod.invoke(sepCompiler, fileArgs).asInstanceOf[java.lang.Boolean]
res.booleanValue()
}
+ /* This method throws java.lang.reflect.InvocationTargetException
+ * if the compiler crashes.
+ * This exception is handled in the shouldCompile and shouldFailCompile
+ * methods of class CompileManager.
+ */
def compile(file: File, kind: String, log: File): Boolean = {
val fileArgs: Array[AnyRef] = Array(file, kind, log)
val res = sepCompileMethod2.invoke(sepCompiler, fileArgs).asInstanceOf[java.lang.Boolean]
@@ -145,20 +157,47 @@ class CompileManager {
compiler = new ReflectiveCompiler
}
+ /* This method returns true iff compilation succeeds.
+ */
def shouldCompile(file: File, kind: String): Boolean = {
createSeparateCompiler()
- compiler.compile(file, kind)
- /*compiler.compile(file, kind) || {
- NestUI.verbose("creating new separate compiler")
- createSeparateCompiler()
+ try {
compiler.compile(file, kind)
- }*/
+ } catch {
+ case ite: java.lang.reflect.InvocationTargetException =>
+ NestUI.verbose("while invoking compiler ("+file+"):")
+ NestUI.verbose("caught "+ite)
+ ite.printStackTrace
+ ite.getCause.printStackTrace
+ false
+ }
}
+ /* This method returns true iff compilation fails
+ * _and_ the compiler does _not_ crash.
+ *
+ * If the compiler crashes, this method returns false.
+ */
def shouldFailCompile(file: File, kind: String, log: File): Boolean = {
// always create new separate compiler
createSeparateCompiler()
- !compiler.compile(file, kind, log)
+
+ try {
+ // simulating compiler crash
+ /*if (file.getName().endsWith("bug752.scala")) {
+ NestUI.verbose("simulating compiler crash")
+ throw new java.lang.reflect.InvocationTargetException(new Throwable)
+ }*/
+
+ !compiler.compile(file, kind, log)
+ } catch {
+ case ite: java.lang.reflect.InvocationTargetException =>
+ NestUI.verbose("while invoking compiler ("+file+"):")
+ NestUI.verbose("caught "+ite)
+ ite.printStackTrace
+ ite.getCause.printStackTrace
+ false
+ }
}
}
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
index b55ebdcfea..0d45f8ae1f 100644
--- a/src/partest/scala/tools/partest/nest/FileManager.scala
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -40,7 +40,7 @@ else
(libs.listFiles(new FilenameFilter {
def accept(dir: File, name: String) =
name.endsWith(".jar")
- }) map {file => file.getAbsolutePath}).mkString(""+PATH_SEP)
+ }) map {file => file.getCanonicalFile.getAbsolutePath}).mkString(""+PATH_SEP)
}
/*
@@ -87,6 +87,7 @@ elif [ -d "$PREFIX/bin" ]; then
latestLibFile = prefixFile("build/quick/lib/library")
latestCompFile = prefixFile("build/quick/lib/compiler")
latestPartestFile = prefixFile("build/quick/lib/partest")
+ latestFjbgFile = prefixFile("build/quick/lib/fjbg.jar")
}
else if (bin.exists && bin.isDirectory) {
latestFile = prefixFile("bin")
@@ -118,6 +119,7 @@ elif [ -d "$PREFIX/bin" ]; then
var latestLibFile: File = _
var latestCompFile: File = _
var latestPartestFile: File = _
+ var latestFjbgFile: File = _
// initialize above fields
findLatest()
@@ -188,9 +190,9 @@ class FileManager {
var testFiles: List[File] = List()
- def getFiles(kind: String, doCheck: Boolean): List[File] = {
+ def getFiles(kind: String, doCheck: Boolean, ending: String): List[File] = {
val filter = new FilenameFilter {
- def accept(dir: File, name: String): Boolean = name endsWith ".scala"
+ def accept(dir: File, name: String): Boolean = name endsWith ending
}
val dir = new File(FileManager.srcDir, kind)
NestUI.verbose("look in "+dir+" for tests")
@@ -207,4 +209,7 @@ class FileManager {
Nil
}
}
+
+ def getFiles(kind: String, doCheck: Boolean): List[File] =
+ getFiles(kind, doCheck, ".scala")
}
diff --git a/src/partest/scala/tools/partest/nest/NestRunner.scala b/src/partest/scala/tools/partest/nest/NestRunner.scala
index f9f2a44af4..5598db3a15 100644
--- a/src/partest/scala/tools/partest/nest/NestRunner.scala
+++ b/src/partest/scala/tools/partest/nest/NestRunner.scala
@@ -20,6 +20,7 @@ object NestRunner {
private var jvmCheck = false
private var jvm5Check = false
private var runCheck = false
+ private var resCheck = false
private var shootoutCheck = false
private var conservative = false
@@ -48,6 +49,7 @@ object NestRunner {
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
@@ -82,6 +84,7 @@ object NestRunner {
NestUI.outline("Scala binaries in : "+FileManager.BIN_DIR+"\n")
// obtain scalac version
+ //TODO: this does not work under Windows!
val cmd = FileManager.SCALAC_CMD+" -version"
NestUI.verbose("running "+cmd)
val proc = Runtime.getRuntime.exec(cmd)
@@ -138,7 +141,10 @@ object NestRunner {
NestUI.verbose("testing "+testFiles)
testFiles
}
- else fileMgr.getFiles(kind, check)
+ 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")
@@ -180,7 +186,8 @@ object NestRunner {
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("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/StreamAppender.scala b/src/partest/scala/tools/partest/nest/StreamAppender.scala
index eddf47cbfc..4a5e5c2f8b 100644
--- a/src/partest/scala/tools/partest/nest/StreamAppender.scala
+++ b/src/partest/scala/tools/partest/nest/StreamAppender.scala
@@ -17,7 +17,9 @@ class StreamAppender(from: Reader, to: Writer) extends Thread {
writer.println(line)
line = reader.readLine()
}
+ reader.close()
writer.flush()
+ writer.close()
} catch {
case e: IOException =>
e.printStackTrace()
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
index bf02c1fb9b..3dc0ecf82c 100644
--- a/src/partest/scala/tools/partest/nest/Worker.scala
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -6,7 +6,7 @@ package scala.tools.partest.nest
import java.io.{File, FileInputStream, FileOutputStream, PrintStream,
PrintWriter, StringWriter, FileWriter, InputStreamReader,
- FileReader}
+ FileReader, OutputStreamWriter}
import java.net.URL
@@ -87,7 +87,6 @@ class Worker extends Actor {
proc.waitFor()
inApp.join()
errApp.join()
- writer.close()
if (NestRunner.showLog) {
// produce log as string in `log`
@@ -96,7 +95,6 @@ class Worker extends Actor {
val appender = new StreamAppender(reader, writer)
appender.start()
appender.join()
- reader.close()
log = writer.toString
}
@@ -148,53 +146,61 @@ class Worker extends Actor {
diff = ""
printInfoStart(file, wr)
- if (!compileMgr.shouldCompile(file, kind)) {
- NestUI.verbose("compilation of "+file+" failed\n")
- success = false
- } else {
- // -------- run test --------
+ try { // *catch-all*
- //TODO: detect whether we have to use Runtime.exec
- val useRuntime = true
-
- if (useRuntime) {
- execTest(outDir, logFile)
+ if (!compileMgr.shouldCompile(file, kind)) {
+ NestUI.verbose("compilation of "+file+" failed\n")
+ success = false
} else {
- val classpath: List[URL] =
- outDir.toURL ::
- List(file.getParentFile.toURL) :::
- (List.fromString(CLASSPATH, PATH_SEP) map { x =>
- (new File(x)).toURL }) :::
- (List.fromString(EXT_CLASSPATH, PATH_SEP) map { x =>
- (new File(x)).toURL })
- try {
- NestUI.verbose("classpath: "+classpath)
- val out = new FileOutputStream(logFile, true)
- Console.withOut(new PrintStream(out)) {
- ObjectRunner.run(classpath, "Test", List("jvm"))
+ // -------- run test --------
+
+ //TODO: detect whether we have to use Runtime.exec
+ val useRuntime = true
+
+ if (useRuntime) {
+ execTest(outDir, logFile)
+ } else {
+ val classpath: List[URL] =
+ outDir.toURL ::
+ List(file.getParentFile.toURL) :::
+ (List.fromString(CLASSPATH, PATH_SEP) map { x =>
+ (new File(x)).toURL }) :::
+ (List.fromString(EXT_CLASSPATH, PATH_SEP) map { x =>
+ (new File(x)).toURL })
+ try {
+ NestUI.verbose("classpath: "+classpath)
+ 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+")")
}
- out.flush
- out.close
- } catch {
- case e: Exception =>
- NestUI.verbose(e+" ("+file.getPath+")")
}
- }
- NestUI.verbose(this+" finished running "+fileBase)
+ NestUI.verbose(this+" finished running "+fileBase)
- diff = compareOutput(dir, fileBase, kind, logFile)
- if (!diff.equals("")) {
- NestUI.verbose("output differs from log file\n")
- success = false
- }
+ diff = compareOutput(dir, fileBase, kind, logFile)
+ if (!diff.equals("")) {
+ NestUI.verbose("output differs from log file\n")
+ success = false
+ }
- // delete output dir
- FileManager.deleteRecursive(outDir)
+ // delete output dir
+ FileManager.deleteRecursive(outDir)
+
+ // delete log file only if test was successful
+ if (success)
+ FileManager.deleteRecursive(logFile)
+ } // successful compile
+ } catch { // *catch-all*
+ case e: Exception =>
+ NestUI.verbose("caught "+e)
+ success = false
+ }
- // delete log file only if test was successful
- if (success)
- FileManager.deleteRecursive(logFile)
- } // successful compile
if (!success) {
errors += 1
NestUI.verbose("incremented errors: "+errors)
@@ -247,9 +253,15 @@ class Worker extends Actor {
case "pos" => {
def posTestRun(file: File, wr: PrintWriter) = new CompileTestRun(file, wr) {
def runTest() {
- if (!compileMgr.shouldCompile(file, kind)) {
- succeeded = false
- errors += 1
+ try {
+ if (!compileMgr.shouldCompile(file, kind)) {
+ succeeded = false
+ errors += 1
+ }
+ } catch {
+ case e: Exception =>
+ succeeded = false
+ errors += 1
}
}
}
@@ -278,29 +290,37 @@ class Worker extends Actor {
succeeded = true; diff = ""; log = ""
printInfoStart(file, wr)
- if (!compileMgr.shouldFailCompile(file, kind, logFile)) {
- succeeded = false
- errors += 1
- } else { //TODO: else compare log file to check file
- val fileBase: String = basename(file.getName)
- val dir = file.getParentFile
- val outDir = new File(dir, fileBase + "-" + kind + ".obj")
-
- NestUI.verbose("comparing output with check file...")
- diff = compareOutput(dir, fileBase, kind, logFile)
- if (!diff.equals("")) {
- NestUI.verbose("output differs from log file\n")
+ try {
+ if (!compileMgr.shouldFailCompile(file, kind, logFile)) {
succeeded = false
errors += 1
+ } else { // compare log file to check file
+ val fileBase: String = basename(file.getName)
+ val dir = file.getParentFile
+ val outDir = new File(dir, fileBase + "-" + kind + ".obj")
+
+ NestUI.verbose("comparing output with check file...")
+ diff = compareOutput(dir, fileBase, kind, logFile)
+ if (!diff.equals("")) {
+ NestUI.verbose("output differs from log file\n")
+ succeeded = false
+ errors += 1
+ }
+
+ // delete output dir
+ FileManager.deleteRecursive(outDir)
+
+ // delete log file only if test was successful
+ if (succeeded)
+ FileManager.deleteRecursive(logFile)
}
-
- // delete output dir
- FileManager.deleteRecursive(outDir)
-
- // delete log file only if test was successful
- if (succeeded)
- FileManager.deleteRecursive(logFile)
+ } catch {
+ case e: Exception =>
+ NestUI.verbose("caught "+e)
+ succeeded = false
+ errors += 1
}
+
printInfoEnd(succeeded, wr)
wr.flush()
swr.flush()
@@ -332,6 +352,97 @@ class Worker extends Actor {
case "jvm5" => {
runJvmTests(kind, files)
}
+ case "res" => {
+ for (file <- files) {
+ 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 = new File(dir, fileBase + "-" + kind + ".obj")
+ if (!outDir.exists)
+ outDir.mkdir()
+ val logFile = new File(dir, fileBase + "-" + kind + ".log")
+ val resFile = new File(dir, fileBase + ".res")
+
+ // run scalac in resident mode:
+ // $SCALAC -d "$os_dstbase".obj -Xresident -sourcepath . "$@"
+ val cmd =
+ JAVACMD+
+ " -classpath "+outDir+PATH_SEP+CLASSPATH+PATH_SEP+EXT_CLASSPATH+
+ " -Djavacmd="+JAVACMD+
+ " scala.tools.nsc.Main"+
+ " -d "+outDir.getCanonicalFile.getAbsolutePath+
+ " -Xresident"+
+ " -sourcepath "+logFile.getParentFile.getCanonicalFile.getAbsolutePath
+ NestUI.verbose(cmd)
+
+ val proc = Runtime.getRuntime.exec(cmd, null, dir)
+
+ val in = proc.getInputStream
+ val err = proc.getErrorStream
+ val out = proc.getOutputStream
+
+ val writer = new FileWriter(logFile)
+ val reader = new FileReader(resFile)
+ val errWriter = new StringWriter
+
+ val inApp = new StreamAppender(new InputStreamReader(in), writer)
+ val errApp = new StreamAppender(new InputStreamReader(err), errWriter)
+ val outApp = new StreamAppender(reader, new OutputStreamWriter(out))
+
+ inApp.start()
+ errApp.start()
+ outApp.start()
+
+ val exitCode = proc.waitFor()
+ NestUI.verbose("finished with exit code "+exitCode)
+
+ inApp.join()
+ errApp.join()
+ outApp.join()
+
+ //writer.close()
+ //reader.close()
+
+ // compare log file with check file
+ diff = compareOutput(dir, fileBase, kind, logFile)
+ if (!diff.equals("")) {
+ NestUI.verbose("output differs from log file\n")
+ succeeded = false
+ errors += 1
+ }
+
+ if (!succeeded && NestRunner.showDiff) NestUI.normal(diff)
+ if (!succeeded && NestRunner.showLog) {
+ // output log file
+ val logReader = new FileReader(logFile)
+ val logWriter = new StringWriter
+ val logAppender = new StreamAppender(logReader, logWriter)
+ logAppender.start()
+ logAppender.join()
+ val log = logWriter.toString
+ NestUI.normal(log)
+ }
+
+ // delete output dir
+ FileManager.deleteRecursive(outDir)
+ // delete log file only if test was successful
+ if (succeeded)
+ FileManager.deleteRecursive(logFile)
+
+ printInfoEnd(succeeded, wr)
+ wr.flush()
+ swr.flush()
+ NestUI.normal(swr.toString)
+ }
+ NestUI.verbose("finished testing "+kind+" with "+errors+" errors")
+ NestUI.verbose("created "+compileMgr.numSeparateCompilers+" separate compilers")
+ (files.length-errors, errors)
+ }
}
}
}