summaryrefslogtreecommitdiff
path: root/src/partest
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-08-22 19:49:46 +0000
committerPaul Phillips <paulp@improving.org>2011-08-22 19:49:46 +0000
commit80952759fbaaf3a99f6bc0ca528da726b5a438e7 (patch)
tree6a81273c34bc51830ce60a7b4d65aa6111a8ef51 /src/partest
parent4b29535009d7848d870252b5b08f53844544de64 (diff)
downloadscala-80952759fbaaf3a99f6bc0ca528da726b5a438e7.tar.gz
scala-80952759fbaaf3a99f6bc0ca528da726b5a438e7.tar.bz2
scala-80952759fbaaf3a99f6bc0ca528da726b5a438e7.zip
Created infrastructure for testing icode + sett...
Created infrastructure for testing icode + settings/partest yak shaving. See enclosed test files/run/inline-ex-handlers.scala. To compare optimized and unoptimized icode after a given phase, all you need in a partest source file is this: import scala.tools.partest.IcodeTest object Test extends IcodeTest { override def printIcodeAfterPhase = "inlineExceptionHandlers" } Other things can be done, see IcodeTest.scala. Review by ureche.
Diffstat (limited to 'src/partest')
-rw-r--r--src/partest/scala/tools/partest/DirectTest.scala49
-rw-r--r--src/partest/scala/tools/partest/IcodeTest.scala45
-rw-r--r--src/partest/scala/tools/partest/ReplTest.scala18
-rw-r--r--src/partest/scala/tools/partest/nest/FileManager.scala20
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala29
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala11
6 files changed, 143 insertions, 29 deletions
diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala
new file mode 100644
index 0000000000..95a8ae57dd
--- /dev/null
+++ b/src/partest/scala/tools/partest/DirectTest.scala
@@ -0,0 +1,49 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.partest
+
+import scala.tools.nsc._
+import io.Directory
+import util.BatchSourceFile
+
+/** A class for testing code which is embedded as a string.
+ * It allows for more complete control over settings, compiler
+ * configuration, sequence of events, etc. than does partest.
+ */
+abstract class DirectTest extends App {
+ // The program being tested in some fashion
+ def code: String
+ // produce the output to be compared against a checkfile
+ def show(): Unit
+
+ // override to add additional settings with strings
+ def extraSettings: String = ""
+ // a default Settings object
+ def settings: Settings = newSettings(extraSettings)
+ // a custom Settings object
+ def newSettings(argString: String) = {
+ val s = new Settings
+ s processArgumentString (argString + " " + debugSettings)
+ s
+ }
+ // compile the code, optionally first adding to the settings
+ def compile(args: String*) = {
+ val settings = newSettings(extraSettings +: args mkString " ")
+ val global = new Global(settings)
+ new global.Run compileSources List(new BatchSourceFile("<partest>", code))
+ !global.reporter.hasErrors
+ }
+
+ /** Constructor/main body **/
+ try show()
+ catch { case t => println(t) ; sys.exit(1) }
+
+ /** Debugger interest only below this line **/
+ protected val isDebug = (sys.props contains "partest.debug") || (sys.env contains "PARTEST_DEBUG")
+ protected def debugSettings = sys.props.getOrElse("partest.debug.settings", "")
+
+ final def log(msg: => Any) { if (isDebug) Console println msg }
+}
diff --git a/src/partest/scala/tools/partest/IcodeTest.scala b/src/partest/scala/tools/partest/IcodeTest.scala
new file mode 100644
index 0000000000..5a8ec2890f
--- /dev/null
+++ b/src/partest/scala/tools/partest/IcodeTest.scala
@@ -0,0 +1,45 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.partest
+
+import scala.tools.nsc._
+import nest.FileUtil._
+import io.Directory
+
+/** A trait for testing icode. All you need is this in a
+ * partest source file:
+ * {{{
+ * object Test extends IcodeTest
+ * }}}
+ * And then the generated output will be the icode for everything
+ * in that file. See source for possible customizations.
+ */
+abstract class IcodeTest extends DirectTest {
+ // override to check icode at a different point.
+ def printIcodeAfterPhase = "icode"
+ // override to use source code other than the file being tested.
+ def code = io.File(sys.props("partest.test-path")).slurp()
+
+ override def extraSettings: String = "-usejavacp -Xprint-icode:" + printIcodeAfterPhase
+
+ // Compile, read in all the *.icode files, delete them, and return their contents
+ def collectIcode(args: String*): List[String] = {
+ compile(args: _*)
+ val icodeFiles = Directory(".").files.toList filter (_ hasExtension "icode")
+
+ try icodeFiles sortBy (_.name) flatMap (f => f.lines.toList)
+ finally icodeFiles foreach (f => f.delete())
+ }
+
+ // Default show() compiles the code with and without optimization and
+ // outputs the diff.
+ def show() {
+ val lines1 = collectIcode("")
+ val lines2 = collectIcode("-optimise")
+
+ println(compareContents(lines1, lines2))
+ }
+}
diff --git a/src/partest/scala/tools/partest/ReplTest.scala b/src/partest/scala/tools/partest/ReplTest.scala
index 02ab154d4b..02cf61902a 100644
--- a/src/partest/scala/tools/partest/ReplTest.scala
+++ b/src/partest/scala/tools/partest/ReplTest.scala
@@ -12,28 +12,16 @@ import java.lang.reflect.{ Method => JMethod, Field => JField }
/** A trait for testing repl code. It drops the first line
* of output because the real repl prints a version number.
*/
-abstract class ReplTest extends App {
- def code: String
- // override to add additional settings with strings
- def extraSettings: String = ""
+abstract class ReplTest extends DirectTest {
// override to transform Settings object immediately before the finish
def transformSettings(s: Settings): Settings = s
-
// final because we need to enforce the existence of a couple settings.
- final def settings: Settings = {
- val s = new Settings
+ final override def settings: Settings = {
+ val s = super.settings
s.Yreplsync.value = true
s.Xnojline.value = true
- val settingString = sys.props("scala.partest.debug.repl-args") match {
- case null => extraSettings
- case s => extraSettings + " " + s
- }
- s processArgumentString settingString
transformSettings(s)
}
def eval() = ILoop.runForTranscript(code, settings).lines drop 1
def show() = eval() foreach println
-
- try show()
- catch { case t => println(t) ; sys.exit(1) }
}
diff --git a/src/partest/scala/tools/partest/nest/FileManager.scala b/src/partest/scala/tools/partest/nest/FileManager.scala
index bf564ea9a7..a39aa27f32 100644
--- a/src/partest/scala/tools/partest/nest/FileManager.scala
+++ b/src/partest/scala/tools/partest/nest/FileManager.scala
@@ -16,7 +16,7 @@ import scala.tools.nsc.io.{ Path, Directory, File => SFile }
import sys.process._
import scala.collection.mutable
-trait FileManager {
+trait FileUtil {
/**
* Compares two files using a Java implementation of the GNU diff
* available at http://www.bmsi.com/java/#diff.
@@ -33,6 +33,24 @@ trait FileManager {
val res = diffWriter.toString
if (res startsWith "No") "" else res
}
+ def compareContents(lines1: Seq[String], lines2: Seq[String]): String = {
+ val xs1 = lines1.toArray[AnyRef]
+ val xs2 = lines2.toArray[AnyRef]
+
+ val diff = new Diff(xs1, xs2)
+ val change = diff.diff_2(false)
+ val writer = new StringWriter
+ val p = new DiffPrint.NormalPrint(xs1, xs2, writer)
+
+ p.print_script(change)
+ val res = writer.toString
+ if (res startsWith "No ") ""
+ else res
+ }
+}
+object FileUtil extends FileUtil { }
+
+trait FileManager extends FileUtil {
def testRootDir: Directory
def testRootPath: String
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
index a00b94eba9..f2e34ced30 100644
--- a/src/partest/scala/tools/partest/nest/TestFile.scala
+++ b/src/partest/scala/tools/partest/nest/TestFile.scala
@@ -13,29 +13,32 @@ import scala.tools.nsc.Settings
import scala.tools.nsc.util.ClassPath
import scala.tools.nsc.io._
-abstract class TestFile(kind: String) {
+trait TestFileCommon {
def file: JFile
- def fileManager: FileManager
+ def kind: String
- val dir = file.toAbsolute.parent
- val fileBase = file.stripExtension
- lazy val objectDir = dir / "%s-%s.obj".format(fileBase, kind) createDirectory true
- val flags: Option[String] = dir / "%s.flags".format(fileBase) ifFile { _.slurp().trim }
+ val dir = file.toAbsolute.parent
+ val fileBase = file.stripExtension
+ val flags = dir / (fileBase + ".flags") ifFile (f => f.slurp().trim)
+ lazy val objectDir = dir / (fileBase + "-" + kind + ".obj") createDirectory true
def setOutDirTo = objectDir
+}
+
+abstract class TestFile(val kind: String) extends TestFileCommon {
+ def file: JFile
+ def fileManager: FileManager
- def defineSettings(settings: Settings, setOutDir: Boolean): Boolean = {
+ def defineSettings(settings: Settings, setOutDir: Boolean) = {
settings.classpath append dir.path
if (setOutDir)
- settings.outdir.value = setOutDirTo.path
+ settings.outputDirs setSingleOutput setOutDirTo.path
// have to catch bad flags somewhere
- flags foreach { f =>
- if (!settings.processArgumentString(f)._1)
- return false
+ (flags forall (f => settings.processArgumentString(f)._1)) && {
+ settings.classpath append fileManager.CLASSPATH
+ true
}
- settings.classpath append fileManager.CLASSPATH
- true
}
override def toString(): String = "%s %s".format(kind, file)
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
index 2298c097b9..a8900e115d 100644
--- a/src/partest/scala/tools/partest/nest/Worker.scala
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -298,6 +298,16 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
if (argString != "")
NestUI.verbose("Found javaopts file '%s', using options: '%s'".format(argsFile, argString))
+ val testFullPath = {
+ val d = new File(logFile.getParentFile, fileBase)
+ if (d.isDirectory) d.getAbsolutePath
+ else {
+ val f = new File(logFile.getParentFile, fileBase + ".scala")
+ if (f.isFile) f.getAbsolutePath
+ else ""
+ }
+ }
+
// 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
@@ -313,6 +323,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
"-Dpartest.output="+outDir.getAbsolutePath,
"-Dpartest.lib="+LATEST_LIB,
"-Dpartest.cwd="+outDir.getParent,
+ "-Dpartest.test-path="+testFullPath,
"-Dpartest.testname="+fileBase,
"-Djavacmd="+JAVACMD,
"-Djavaccmd="+javacCmd,