diff --git a/.idea/libraries/robolectric.xml b/.idea/libraries/robolectric.xml
index 768c8e5b709..e38e94b81fd 100644
--- a/.idea/libraries/robolectric.xml
+++ b/.idea/libraries/robolectric.xml
@@ -2,58 +2,40 @@
+
+
+
-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
-
+
-
-
+
+
\ No newline at end of file
diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractParcelBoxTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractParcelBoxTest.kt
index ee5d46dee1b..50b754fee4b 100644
--- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractParcelBoxTest.kt
+++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractParcelBoxTest.kt
@@ -22,52 +22,142 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.codegen.getClassFiles
-import org.jetbrains.org.objectweb.asm.ClassReader
-import org.jetbrains.org.objectweb.asm.tree.ClassNode
+import org.jetbrains.kotlin.utils.PathUtil
+import org.jetbrains.org.objectweb.asm.ClassWriter
+import org.jetbrains.org.objectweb.asm.ClassWriter.COMPUTE_FRAMES
+import org.jetbrains.org.objectweb.asm.ClassWriter.COMPUTE_MAXS
+import org.jetbrains.org.objectweb.asm.Label
+import org.jetbrains.org.objectweb.asm.Opcodes.*
+import org.jetbrains.org.objectweb.asm.Type
+import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
+import org.junit.runner.JUnitCore
import java.io.File
-import java.net.URLClassLoader
-import java.nio.ByteBuffer
-import java.security.ProtectionDomain
-
+import java.nio.file.Files
+import java.util.concurrent.TimeUnit
abstract class AbstractParcelBoxTest : CodegenTestCase() {
protected companion object {
val BASE_DIR = "plugins/android-extensions/android-extensions-compiler/testData/parcel/box"
val LIBRARY_KT = File(File(BASE_DIR).parentFile, "boxLib.kt")
+
+ private val JUNIT_GENERATED_TEST_CLASS_BYTES by lazy { constructSyntheticTestClass() }
+ private val JUNIT_GENERATED_TEST_CLASS_FQNAME = "test.JunitTest"
+
+ private fun constructSyntheticTestClass(): ByteArray {
+ return with(ClassWriter(COMPUTE_MAXS or COMPUTE_FRAMES)) {
+ visit(49, ACC_PUBLIC, JUNIT_GENERATED_TEST_CLASS_FQNAME.replace('.', '/'), null, "java/lang/Object", emptyArray())
+ visitSource(null, null)
+
+ with(visitAnnotation("Lorg/junit/runner/RunWith;", true)) {
+ visit("value", Type.getType("Lorg/robolectric/RobolectricTestRunner;"))
+ visitEnd()
+ }
+
+ with(visitAnnotation("Lorg/robolectric/annotation/Config;", true)) {
+ visit("manifest", "--none")
+ visitEnd()
+ }
+
+ with(visitMethod(ACC_PUBLIC, "", "()V", null, null)) {
+ visitVarInsn(ALOAD, 0)
+ visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false)
+
+ visitInsn(RETURN)
+ visitMaxs(-1, -1)
+ visitEnd()
+ }
+
+ with(visitMethod(ACC_PUBLIC, "test", "()V", null, null)) {
+ visitAnnotation("Lorg/junit/Test;", true).visitEnd()
+
+ val v = InstructionAdapter(this)
+
+ val assertionOk = Label()
+
+ v.invokestatic("test/TestKt", "box", "()Ljava/lang/String;", false) // -> ret
+ v.dup() // -> ret, ret
+ v.aconst("OK") // -> ret, ret, ok
+ v.invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z", false) // -> ret, eq
+ v.ifne(assertionOk) // -> ret
+
+ val assertionErrorType = Type.getObjectType("java/lang/AssertionError")
+
+ v.anew(assertionErrorType) // -> ret, ae
+ v.dupX1() // -> ae, ret, ae
+ v.swap() // -> ae, ae, ret
+ v.invokespecial(assertionErrorType.internalName, "", "(Ljava/lang/Object;)V", false) // -> ae
+ v.athrow()
+
+ v.visitLabel(assertionOk)
+ v.pop() // -> [empty]
+ v.areturn(Type.VOID_TYPE)
+
+ visitMaxs(-1, -1)
+ visitEnd()
+ }
+
+ visitEnd()
+ toByteArray()
+ }
+ }
}
override fun doTest(filePath: String) {
super.doTest(File(BASE_DIR, filePath + ".kt").absolutePath)
}
- open protected fun getClassLoaderWithGeneratedFiles(): ClassLoader {
- return object : URLClassLoader(arrayOf(), this::class.java.classLoader) {
- init {
- for (classFile in classFileFactory.getClassFiles().sortedBy { it.relativePath }) {
- val bytes = classFile.asByteArray()
- val className = ClassNode().also { ClassReader(bytes).accept(it, ClassReader.EXPAND_FRAMES) }.name
- try {
- defineClass(className.replace('/', '.'), ByteBuffer.wrap(bytes), null as ProtectionDomain?)
- } catch (e: Throwable) {
- throw RuntimeException("Can't load class $className", e)
- }
- }
- }
- }
+ private fun getClasspathForTest(): List {
+ val kotlinRuntimeJar = PathUtil.kotlinPathsForIdeaPlugin.stdlibPath
+ val layoutLibJars = listOf(File("ideaSDK/plugins/android/lib/layoutlib.jar"), File("ideaSDK/plugins/android/lib/layoutlib-api.jar"))
+
+ val robolectricJars = File("dependencies/robolectric")
+ .listFiles { f: File -> f.extension == "jar" }
+ .sortedBy { it.nameWithoutExtension }
+
+ val junitCoreResourceName = JUnitCore::class.java.name.replace('.', '/') + ".class"
+ val junitJar = File(JUnitCore::class.java.classLoader.getResource(junitCoreResourceName).file.substringBeforeLast('!'))
+
+ val androidExtensionsRuntime = File("out/production/android-extensions-runtime")
+
+ return listOf(kotlinRuntimeJar) + layoutLibJars + robolectricJars + junitJar + androidExtensionsRuntime
}
override fun doMultiFileTest(wholeFile: File, files: List, javaFilesDir: File?) {
- if (true) { // TODO Parcelable box tests are disabled because of OOM. Currently investigating
- return
- }
-
compile(files + TestFile(LIBRARY_KT.name, LIBRARY_KT.readText()), javaFilesDir)
- val testClass = Class.forName("test.TestKt", false, getClassLoaderWithGeneratedFiles())
+ val javaBin = File(System.getProperty("java.home").takeIf { it.isNotEmpty() } ?: error("JAVA_HOME is not set"), "bin")
+ val javaExe = File(javaBin, "java.exe").takeIf { it.exists() } ?: File(javaBin, "java")
+ assert(javaExe.exists()) { "Can't find 'java' executable in $javaBin" }
+
+ val libraryClasspath = getClasspathForTest()
+ val dirForTestClasses = Files.createTempDirectory("parcel").toFile()
+
+ fun writeClass(fqNameOrPath: String, bytes: ByteArray) {
+ val path = if (fqNameOrPath.endsWith(".class")) fqNameOrPath else (fqNameOrPath.replace('.', '/') + ".class")
+ File(dirForTestClasses, path).also { it.parentFile.mkdirs() }.writeBytes(bytes)
+ }
+
try {
- testClass.getDeclaredMethod("box").invoke(testClass)
- } catch (e: Throwable) {
- throw AssertionError(classFileFactory.createText(), e)
+ writeClass(JUNIT_GENERATED_TEST_CLASS_FQNAME, JUNIT_GENERATED_TEST_CLASS_BYTES)
+ classFileFactory.getClassFiles().forEach { writeClass(it.relativePath, it.asByteArray()) }
+
+ val process = ProcessBuilder(
+ javaExe.absolutePath,
+ "-ea",
+ "-classpath",
+ (libraryClasspath + dirForTestClasses).joinToString(File.pathSeparator),
+ JUnitCore::class.java.name,
+ JUNIT_GENERATED_TEST_CLASS_FQNAME
+ ).inheritIO().start()
+
+ process.waitFor(3, TimeUnit.MINUTES)
+ if (process.exitValue() != 0) {
+ throw AssertionError(classFileFactory.createText())
+ }
+ } finally {
+ if (!dirForTestClasses.deleteRecursively()) {
+ throw AssertionError("Unable to delete $dirForTestClasses")
+ }
}
}
diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/ParcelBoxTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/ParcelBoxTest.kt
index 1b3827c4a25..4950eabf616 100644
--- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/ParcelBoxTest.kt
+++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/ParcelBoxTest.kt
@@ -16,14 +16,6 @@
package org.jetbrains.kotlin.android.parcel
-import org.junit.Test
-import org.junit.runner.RunWith
-//import org.robolectric.RobolectricTestRunner
-//import org.robolectric.annotation.Config
-
-// This class is not generated because it uses the custom test runner
-//@RunWith(RobolectricTestRunner::class)
-//@Config(manifest = Config.NONE)
class ParcelBoxTest : AbstractParcelBoxTest() {
fun testSimple() = doTest("simple")
fun testPrimitiveTypes() = doTest("primitiveTypes")
diff --git a/update_dependencies.xml b/update_dependencies.xml
index 05206734c41..93b63fd8c02 100644
--- a/update_dependencies.xml
+++ b/update_dependencies.xml
@@ -247,9 +247,12 @@
+
+