summaryrefslogtreecommitdiff
path: root/test/junit/scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-08-27 14:00:36 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2014-09-10 00:05:11 +0200
commit35c53af7e3bbe19d50845e698c02a49d0a022409 (patch)
tree2d9dce67ed018e48b8342a1bd65773af301870bc /test/junit/scala
parent44b5c261a8e585c5747380895aa06c84f9d63f6c (diff)
downloadscala-35c53af7e3bbe19d50845e698c02a49d0a022409.tar.gz
scala-35c53af7e3bbe19d50845e698c02a49d0a022409.tar.bz2
scala-35c53af7e3bbe19d50845e698c02a49d0a022409.zip
Tools to run the compiler in JUnit tests
Diffstat (limited to 'test/junit/scala')
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala34
-rw-r--r--test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala81
2 files changed, 115 insertions, 0 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
index 256dff85c3..8518d5c832 100644
--- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
+++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala
@@ -1,7 +1,11 @@
package scala.tools.nsc.backend.jvm
+import scala.reflect.internal.util.BatchSourceFile
+import scala.reflect.io.VirtualDirectory
import scala.tools.asm.Opcodes
import scala.tools.asm.tree.{AbstractInsnNode, LabelNode, ClassNode, MethodNode}
+import scala.tools.cmd.CommandLineParser
+import scala.tools.nsc.{Settings, Global}
import scala.tools.partest.ASMConverters
import scala.collection.JavaConverters._
@@ -24,4 +28,34 @@ object CodeGenTools {
cls.methods.add(method)
cls
}
+
+ private def resetOutput(compiler: Global): Unit = {
+ compiler.settings.outputDirs.setSingleOutput(new VirtualDirectory("(memory)", None))
+ }
+
+ def newCompiler(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = {
+ val settings = new Settings()
+ val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs)
+ settings.processArguments(args, processAll = true)
+ val compiler = new Global(settings)
+ resetOutput(compiler)
+ compiler
+ }
+
+ def compile(compiler: Global = newCompiler())(code: String): List[(String, Array[Byte])] = {
+ compiler.reporter.reset()
+ resetOutput(compiler)
+ val run = new compiler.Run()
+ run.compileSources(List(new BatchSourceFile("unitTestSource.scala", code)))
+ val outDir = compiler.settings.outputDirs.getSingleOutput.get
+ (for (f <- outDir.iterator if !f.isDirectory) yield (f.name, f.toByteArray)).toList
+ }
+
+ def compileClasses(compiler: Global = newCompiler())(code: String): List[ClassNode] = {
+ compile(compiler)(code).map(p => AsmUtils.readClass(p._2)).sortBy(_.name)
+ }
+
+ def compileMethods(compiler: Global = newCompiler())(code: String): List[MethodNode] = {
+ compileClasses(compiler)(s"class C { $code }").head.methods.asScala.toList.filterNot(_.name == "<init>")
+ }
}
diff --git a/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
new file mode 100644
index 0000000000..640f22fc47
--- /dev/null
+++ b/test/junit/scala/tools/nsc/backend/jvm/DirectCompileTest.scala
@@ -0,0 +1,81 @@
+package scala.tools.nsc.backend.jvm
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.junit.Assert._
+import CodeGenTools._
+import scala.tools.asm.Opcodes._
+import scala.tools.partest.ASMConverters._
+
+@RunWith(classOf[JUnit4])
+class DirectCompileTest {
+ val compiler = newCompiler(extraArgs = "-Ybackend:GenBCode")
+
+ @Test
+ def testCompile(): Unit = {
+ val List(("C.class", bytes)) = compile(compiler)(
+ """
+ |class C {
+ | def f = 1
+ |}
+ """.stripMargin)
+ def s(i: Int, n: Int) = (bytes(i) & 0xff) << n
+ assertTrue((s(0, 24) | s(1, 16) | s(2, 8) | s(3, 0)) == 0xcafebabe) // mocha java latte machiatto surpreme dark roasted espresso
+ }
+
+ @Test
+ def testCompileClasses(): Unit = {
+ val List(cClass, cModuleClass) = compileClasses(compiler)(
+ """
+ |class C
+ |object C
+ """.stripMargin)
+
+ assertTrue(cClass.name == "C")
+ assertTrue(cModuleClass.name == "C$")
+
+ val List(dMirror, dModuleClass) = compileClasses(compiler)(
+ """
+ |object D
+ """.stripMargin)
+
+ assertTrue(dMirror.name == "D")
+ assertTrue(dModuleClass.name == "D$")
+ }
+
+ @Test
+ def testCompileMethods(): Unit = {
+ val List(f, g) = compileMethods(compiler)(
+ """
+ |def f = 10
+ |def g = f
+ """.stripMargin)
+ assertTrue(f.name == "f")
+ assertTrue(g.name == "g")
+
+ assertTrue(instructionsFromMethod(f).dropNonOp ===
+ List(IntOp(BIPUSH, 10), Op(IRETURN)))
+
+ assertTrue(instructionsFromMethod(g).dropNonOp ===
+ List(VarOp(ALOAD, 0), Method(INVOKEVIRTUAL, "C", "f", "()I", false), Op(IRETURN)))
+ }
+
+ @Test
+ def testDropNonOpAliveLabels(): Unit = {
+ val List(f) = compileMethods(compiler)("""def f(x: Int) = if (x == 0) "a" else "b"""")
+ assertTrue(instructionsFromMethod(f).dropNonOp === List(
+ VarOp(ILOAD, 1),
+ Op(ICONST_0),
+ Jump(IF_ICMPEQ, Label(6)),
+ Jump(GOTO, Label(10)),
+ Label(6),
+ Ldc(LDC, "a"),
+ Jump(GOTO, Label(13)),
+ Label(10),
+ Ldc(LDC, "b"),
+ Label(13),
+ Op(ARETURN)
+ ))
+ }
+}