diff options
-rw-r--r-- | test/files/run/classfile-format-52.check | 2 | ||||
-rw-r--r-- | test/files/run/classfile-format-52.scala | 80 |
2 files changed, 82 insertions, 0 deletions
diff --git a/test/files/run/classfile-format-52.check b/test/files/run/classfile-format-52.check new file mode 100644 index 0000000000..5d24ef03cc --- /dev/null +++ b/test/files/run/classfile-format-52.check @@ -0,0 +1,2 @@ +hello from publicMethod +hello from staticMethod diff --git a/test/files/run/classfile-format-52.scala b/test/files/run/classfile-format-52.scala new file mode 100644 index 0000000000..f0ad7c2ed6 --- /dev/null +++ b/test/files/run/classfile-format-52.scala @@ -0,0 +1,80 @@ +import java.io.{File, FileOutputStream} + +import scala.tools.nsc.settings.ScalaVersion +import scala.tools.partest._ +import scala.tools.asm +import asm.{AnnotationVisitor, ClassWriter, FieldVisitor, Handle, MethodVisitor, Opcodes} +import Opcodes._ + +// This test ensures that we can read JDK 8 (classfile format 52) files, including those +// with default methods. To do that it first uses ASM to generate an interface called +// HasDefaultMethod. Then it runs a normal compile on Scala source that extends that +// interface. Any failure will be dumped to std out. +// +// By it's nature the test can only work on JDK 8+ because under JDK 7- the +// interface won't verify. +object Test extends DirectTest { + override def extraSettings: String = "-optimise -usejavacp -d " + testOutput.path + " -cp " + testOutput.path + + def generateInterface() { + val interfaceName = "HasDefaultMethod" + val methodType = "()Ljava/lang/String;" + + val cw = new ClassWriter(0) + cw.visit(52, ACC_PUBLIC+ACC_ABSTRACT+ACC_INTERFACE, interfaceName, null, "java/lang/Object", null) + + def createMethod(flags:Int, name: String) { + val method = cw.visitMethod(flags, name, methodType, null, null) + method.visitCode() + method.visitLdcInsn(s"hello from $name") + method.visitInsn(ARETURN) + method.visitMaxs(1, 1) + method.visitEnd() + } + + createMethod(ACC_PUBLIC, "publicMethod") + createMethod(ACC_PUBLIC+ACC_STATIC, "staticMethod") + createMethod(ACC_PRIVATE, "privateMethod") + + cw.visitEnd() + val bytes = cw.toByteArray() + + val fos = new FileOutputStream(new File(s"${testOutput.path}/$interfaceName.class")) + try + fos write bytes + finally + fos.close() + + } + + def code = +""" +class Driver extends HasDefaultMethod { + println(publicMethod()) + println(HasDefaultMethod.staticMethod()) +} +""" + + override def show(): Unit = { + // redirect err to out, for logging + val prevErr = System.err + System.setErr(System.out) + try { + // this test is only valid under JDK 1.8+ + // cheat a little by using 'ScalaVersion' because it can parse java versions just as well + val requiredJavaVersion = ScalaVersion("1.8") + val executingJavaVersion = ScalaVersion(System.getProperty("java.specification.version")) + if (executingJavaVersion >= requiredJavaVersion) { + generateInterface() + compile() + Class.forName("Driver").newInstance() + } else { + // under other versions just dump the expected results + println("hello from publicMethod") + println("hello from staticMethod") + } + } + finally + System.setErr(prevErr) + } +} |