From 80952759fbaaf3a99f6bc0ca528da726b5a438e7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 22 Aug 2011 19:49:46 +0000 Subject: 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. --- src/partest/scala/tools/partest/DirectTest.scala | 49 ++++++++++++++++++++++ src/partest/scala/tools/partest/IcodeTest.scala | 45 ++++++++++++++++++++ src/partest/scala/tools/partest/ReplTest.scala | 18 ++------ .../scala/tools/partest/nest/FileManager.scala | 20 ++++++++- .../scala/tools/partest/nest/TestFile.scala | 29 +++++++------ src/partest/scala/tools/partest/nest/Worker.scala | 11 +++++ 6 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 src/partest/scala/tools/partest/DirectTest.scala create mode 100644 src/partest/scala/tools/partest/IcodeTest.scala (limited to 'src/partest') 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("", 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, -- cgit v1.2.3