diff --git a/.idea/runConfigurations/Codegen_Tests_with_JVM_target_1_6_on_JDK_1_6.xml b/.idea/runConfigurations/Codegen_Tests_with_JVM_target_1_6_on_JDK_1_6.xml new file mode 100644 index 00000000000..26384fafa5c --- /dev/null +++ b/.idea/runConfigurations/Codegen_Tests_with_JVM_target_1_6_on_JDK_1_6.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/SpecialFiles.java b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/SpecialFiles.java index f374b2781d5..b808cebca21 100644 --- a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/SpecialFiles.java +++ b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/SpecialFiles.java @@ -47,7 +47,6 @@ public class SpecialFiles { excludedFiles.add("arrayOfKClasses.kt"); excludedFiles.add("enumKClassAnnotation.kt"); excludedFiles.add("primitivesAndArrays.kt"); - excludedFiles.add("kt6485.kt"); excludedFiles.add("getDelegateWithoutReflection.kt"); // Reflection is used to check full class name diff --git a/compiler/testData/codegen/box/regressions/kt6485.kt b/compiler/testData/codegen/box/regressions/kt6485.kt index 563ed276949..0304fd25b83 100644 --- a/compiler/testData/codegen/box/regressions/kt6485.kt +++ b/compiler/testData/codegen/box/regressions/kt6485.kt @@ -18,8 +18,17 @@ inline fun typeLiteral(): TypeLiteral = object : TypeLiteral() fun box(): String { assertEquals("java.lang.String", (typeLiteral().type as Class<*>).canonicalName) assertEquals("java.util.List", typeLiteral>().type.toString()) - assertEquals("java.lang.String[]", (typeLiteral>().type as Class<*>).canonicalName) - assertEquals("java.lang.Integer[]", (typeLiteral>().type as Class<*>).canonicalName) - assertEquals("java.lang.String[][]", (typeLiteral>>().type as Class<*>).canonicalName) + + //note that 'type' implementation for next cases is different on jdk 6 and 8: GenericArrayType and Class + assertEquals("java.lang.String[]", typeLiteral>().type.canonicalName) + assertEquals("java.lang.Integer[]", typeLiteral>().type.canonicalName) + assertEquals("java.lang.String[][]", typeLiteral>>().type.canonicalName) return "OK" -} \ No newline at end of file +} + +val Type.canonicalName: String + get() = when (this) { + is Class<*> -> this.canonicalName + is java.lang.reflect.GenericArrayType -> this.getGenericComponentType().canonicalName + "[]" + else -> null!! + } \ No newline at end of file diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java index d3fe570cdb7..6027ca93add 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractBlackBoxCodegenTest.java @@ -16,13 +16,9 @@ package org.jetbrains.kotlin.codegen; -import com.intellij.ide.highlighter.JavaFileType; -import com.intellij.openapi.util.io.FileUtil; -import kotlin.io.FilesKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; -import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.psi.KtDeclaration; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedFunction; @@ -31,9 +27,12 @@ import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import java.io.File; import java.lang.reflect.Method; -import java.util.ArrayList; import java.util.List; +import static org.jetbrains.kotlin.codegen.TestUtilsKt.clearReflectionCache; +import static org.jetbrains.kotlin.codegen.TestUtilsKt.getBoxMethodOrNull; +import static org.jetbrains.kotlin.codegen.TestUtilsKt.getGeneratedClass; + public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { @Override @@ -42,21 +41,6 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { blackBox(); } - - @NotNull - protected static List findJavaSourcesInDirectory(@NotNull File directory) { - List javaFilePaths = new ArrayList<>(1); - - FileUtil.processFilesRecursively(directory, file -> { - if (file.isFile() && FilesKt.getExtension(file).equals(JavaFileType.DEFAULT_EXTENSION)) { - javaFilePaths.add(file.getPath()); - } - return true; - }); - - return javaFilePaths; - } - protected void blackBox() { // If there are many files, the first 'box(): String' function will be executed. GeneratedClassLoader generatedClassLoader = generateAndCreateClassLoader(); @@ -67,8 +51,7 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { try { Method method = getBoxMethodOrNull(aClass); if (method != null) { - String r = (String) method.invoke(null); - assertEquals("OK", r); + callBoxMethodAndCheckResult(generatedClassLoader, aClass, method); return; } } @@ -80,21 +63,9 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { clearReflectionCache(generatedClassLoader); } } + fail("Can't find box method!"); } - private static void clearReflectionCache(@NotNull ClassLoader classLoader) { - try { - Class klass = classLoader.loadClass(JvmAbi.REFLECTION_FACTORY_IMPL.asSingleFqName().asString()); - Method method = klass.getDeclaredMethod("clearCaches"); - method.invoke(null); - } - catch (ClassNotFoundException e) { - // This is OK for a test without kotlin-reflect in the dependencies - } - catch (Exception e) { - throw ExceptionUtilsKt.rethrow(e); - } - } @Nullable private static String getFacadeFqName(@NotNull KtFile firstFile) { @@ -105,23 +76,4 @@ public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase { } return null; } - - private static Class getGeneratedClass(GeneratedClassLoader generatedClassLoader, String className) { - try { - return generatedClassLoader.loadClass(className); - } - catch (ClassNotFoundException e) { - fail("No class file was generated for: " + className); - } - return null; - } - - private static Method getBoxMethodOrNull(Class aClass) { - try { - return aClass.getMethod("box"); - } - catch (NoSuchMethodException e){ - return null; - } - } } diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractCompileKotlinAgainstKotlinTest.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractCompileKotlinAgainstKotlinTest.java index 51df42c38fa..e63495e8658 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractCompileKotlinAgainstKotlinTest.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/AbstractCompileKotlinAgainstKotlinTest.java @@ -36,7 +36,6 @@ import org.jetbrains.kotlin.utils.ExceptionUtilsKt; import java.io.File; import java.io.IOException; -import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Collections; @@ -87,9 +86,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest } private void invokeBox(@NotNull String className) throws Exception { - Method box = createGeneratedClassLoader().loadClass(className).getMethod("box"); - String result = (String) box.invoke(null); - assertEquals("OK", result); + callBoxMethodAndCheckResult(createGeneratedClassLoader(), className); } @NotNull diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java index 0f72edaec8a..f346c94a327 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; +import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; @@ -30,12 +31,14 @@ import kotlin.text.Charsets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.output.OutputFile; +import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection; import org.jetbrains.kotlin.checkers.CheckerTestUtil; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; +import org.jetbrains.kotlin.test.clientserver.TestProxy; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.config.*; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; @@ -62,9 +65,11 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -72,13 +77,16 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static org.jetbrains.kotlin.codegen.AbstractBlackBoxCodegenTest.findJavaSourcesInDirectory; +import static org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt.writeAllTo; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*; +import static org.jetbrains.kotlin.codegen.TestUtilsKt.*; import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar; public abstract class CodegenTestCase extends KtUsefulTestCase { private static final String DEFAULT_TEST_FILE_NAME = "a_test"; public static final String DEFAULT_JVM_TARGET_FOR_TEST = "kotlin.test.default.jvm.target"; + public static final String JAVA_COMPILATION_TARGET = "kotlin.test.java.compilation.target"; + public static final String RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT = "kotlin.test.box.in.separate.process.port"; protected KotlinCoreEnvironment myEnvironment; protected CodegenTestFiles myFiles; @@ -87,6 +95,8 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { protected ConfigurationKind configurationKind = ConfigurationKind.JDK_ONLY; private final String defaultJvmTarget = System.getProperty(DEFAULT_JVM_TARGET_FOR_TEST); + private final String boxInSeparateProcessPort = System.getProperty(RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT); + private final String javaCompilationTarget = System.getProperty(JAVA_COMPILATION_TARGET); protected final void createEnvironmentWithMockJdkAndIdeaAnnotations( @NotNull ConfigurationKind configurationKind, @@ -566,6 +576,21 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { } } + @NotNull + protected static List findJavaSourcesInDirectory(@NotNull File directory) { + List javaFilePaths = new ArrayList<>(1); + + FileUtil.processFilesRecursively(directory, file -> { + if (file.isFile() && FilesKt.getExtension(file).equals(JavaFileType.DEFAULT_EXTENSION)) { + javaFilePaths.add(file.getPath()); + } + return true; + }); + + return javaFilePaths; + } + + protected ConfigurationKind extractConfigurationKind(@NotNull List files) { boolean addRuntime = false; boolean addReflect = false; @@ -584,14 +609,24 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { } @NotNull - protected static List extractJavacOptions(@NotNull List files) { + protected List extractJavacOptions(@NotNull List files) { List javacOptions = new ArrayList<>(0); for (TestFile file : files) { javacOptions.addAll(InTextDirectivesUtils.findListWithPrefixes(file.content, "// JAVAC_OPTIONS:")); } + updateJavacOptions(javacOptions); return javacOptions; } + protected void updateJavacOptions(List javacOptions) { + if (javaCompilationTarget != null && !javacOptions.contains("-target")) { + javacOptions.add("-source"); + javacOptions.add(javaCompilationTarget); + javacOptions.add("-target"); + javacOptions.add(javaCompilationTarget); + } + } + public static class TestFile implements Comparable { public final String name; public final String content; @@ -664,4 +699,37 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { protected void doMultiFileTest(@NotNull File wholeFile, @NotNull List files, @Nullable File javaFilesDir) throws Exception { throw new UnsupportedOperationException("Multi-file test cases are not supported in this test"); } + + protected void callBoxMethodAndCheckResult(URLClassLoader classLoader, String className) + throws IOException, InvocationTargetException, IllegalAccessException { + Class aClass = getGeneratedClass(classLoader, className); + Method method = getBoxMethodOrNull(aClass); + assertTrue("Can't find box method in " + aClass,method != null); + callBoxMethodAndCheckResult(classLoader, aClass, method); + } + + protected void callBoxMethodAndCheckResult(URLClassLoader classLoader, Class aClass, Method method) + throws IOException, IllegalAccessException, InvocationTargetException { + String result; + if (boxInSeparateProcessPort != null) { + result = invokeBoxInSeparateProcess(classLoader, aClass); + } + else { + result = (String) method.invoke(null); + } + assertEquals("OK", result); + } + + @NotNull + private String invokeBoxInSeparateProcess(URLClassLoader classLoader, Class aClass) throws IOException { + List classPath = extractUrls(classLoader); + if (classLoader instanceof GeneratedClassLoader) { + File outDir = KotlinTestUtils.tmpDirForTest(this); + SimpleOutputFileCollection currentOutput = new SimpleOutputFileCollection(((GeneratedClassLoader) classLoader).getAllGeneratedFiles()); + writeAllTo(currentOutput, outDir); + classPath.add(0, outDir.toURI().toURL()); + } + + return new TestProxy(Integer.valueOf(boxInSeparateProcessPort), aClass.getCanonicalName(), classPath).runTest(); + } } diff --git a/compiler/tests-common/org/jetbrains/kotlin/codegen/testUtils.kt b/compiler/tests-common/org/jetbrains/kotlin/codegen/testUtils.kt new file mode 100644 index 00000000000..a4ce1200084 --- /dev/null +++ b/compiler/tests-common/org/jetbrains/kotlin/codegen/testUtils.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen + +import junit.framework.TestCase +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.utils.rethrow +import java.lang.reflect.Method +import java.net.URL +import java.net.URLClassLoader + +fun clearReflectionCache(classLoader: ClassLoader) { + try { + val klass = classLoader.loadClass(JvmAbi.REFLECTION_FACTORY_IMPL.asSingleFqName().asString()) + val method = klass.getDeclaredMethod("clearCaches") + method.invoke(null) + } + catch (e: ClassNotFoundException) { + // This is OK for a test without kotlin-reflect in the dependencies + } +} + + +fun getGeneratedClass(classLoader: ClassLoader, className: String): Class<*> { + try { + return classLoader.loadClass(className) + } + catch (e: ClassNotFoundException) { + error("No class file was generated for: " + className) + } +} + +fun getBoxMethodOrNull(aClass: Class<*>): Method? { + try { + return aClass.getMethod("box") + } + catch (e: NoSuchMethodException) { + return null + } +} + +fun ClassLoader?.extractUrls(): List { + return (this as? URLClassLoader)?.let { + it.urLs.toList() + it.parent.extractUrls() + } ?: emptyList() + +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.java b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/MessageHeader.kt similarity index 51% rename from compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.java rename to compiler/tests-common/org/jetbrains/kotlin/test/clientserver/MessageHeader.kt index e36f5a94b31..c2bfc48c0e4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.java +++ b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/MessageHeader.kt @@ -14,18 +14,11 @@ * limitations under the License. */ -package org.jetbrains.kotlin.codegen; +package org.jetbrains.kotlin.test.clientserver -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -/*This suite is used to run common java-backend tests under jdk 8, jdk 9 with default target 1.8 (and in future 1.9)*/ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - BlackBoxCodegenTestGenerated.class, - BlackBoxInlineCodegenTestGenerated.class, - CompileKotlinAgainstInlineKotlinTestGenerated.class, - CompileKotlinAgainstKotlinTestGenerated.class, - BlackBoxAgainstJavaCodegenTestGenerated.class -}) -public class CodegenJdkCommonTestSuite {} +enum class MessageHeader { + NEW_TEST, + CLASS_PATH, + RESULT, + ERROR +} \ No newline at end of file diff --git a/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProcessServer.kt b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProcessServer.kt new file mode 100644 index 00000000000..a87ad250b54 --- /dev/null +++ b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProcessServer.kt @@ -0,0 +1,104 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.test.clientserver + +import org.jetbrains.kotlin.codegen.getBoxMethodOrNull +import org.jetbrains.kotlin.codegen.getGeneratedClass +import java.io.File +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import java.net.ServerSocket +import java.net.Socket +import java.net.URL +import java.net.URLClassLoader +import java.util.concurrent.Executors + +//Use only JDK 1.6 compatible api +object TestProcessServer { + + val executor = Executors.newFixedThreadPool(1)!! + + @JvmStatic + fun main(args: Array) { + val portNumber = args[0].toInt() + println("Starting server on port $portNumber...") + + val serverSocket = ServerSocket(portNumber) + try { + while (true) { + val clientSocket = serverSocket.accept() + println("Socket established...") + executor.execute(ServerTest(clientSocket)) + } + } + finally { + serverSocket.close() + } + } +} + +private class ServerTest(val clientSocket: Socket) : Runnable { + private lateinit var className: String + private lateinit var testMethod: String + + override fun run() { + val input = ObjectInputStream(clientSocket.getInputStream()) + val output = ObjectOutputStream(clientSocket.getOutputStream()) + try { + var message = input.readObject() as MessageHeader + assert(message == MessageHeader.NEW_TEST, { "New test marker missed, but $message received" }) + className = input.readObject() as String + testMethod = input.readObject() as String + println("Preparing to execute test $className") + + message = input.readObject() as MessageHeader + assert(message == MessageHeader.CLASS_PATH, { "Class path marker missed, but $message received" }) + val classPath = input.readObject() as Array + + val result = executeTest(URLClassLoader(classPath, JDK_EXT_JARS_CLASS_LOADER)) + output.writeObject(MessageHeader.RESULT) + output.writeObject(result) + } + catch (e: Exception) { + output.writeObject(MessageHeader.ERROR) + output.writeObject(e) + } + finally { + output.close() + input.close() + clientSocket.close() + } + } + + fun executeTest(classLoader: ClassLoader): String { + val clazz = getGeneratedClass(classLoader, className) + return getBoxMethodOrNull(clazz)!!.invoke(null) as String + } + + companion object { + //Required for org.jetbrains.kotlin.codegen.BlackBoxCodegenTestGenerated.FullJdk#testClasspath + val JDK_EXT_JARS_CLASS_LOADER: ClassLoader + init { + val javaHome = System.getProperty("java.home") + val extFolder = File(javaHome + "/lib/ext/") + println(extFolder.canonicalPath) + val listFiles = extFolder.listFiles() + val additionalJars = listFiles?.filter { it.name.endsWith(".jar") }?.map { it.toURI().toURL() } ?: emptyList() + JDK_EXT_JARS_CLASS_LOADER = URLClassLoader(additionalJars.toTypedArray(), null) + } + } +} \ No newline at end of file diff --git a/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProxy.kt b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProxy.kt new file mode 100644 index 00000000000..28c054b4c25 --- /dev/null +++ b/compiler/tests-common/org/jetbrains/kotlin/test/clientserver/TestProxy.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.test.clientserver + +import org.jetbrains.kotlin.utils.rethrow +import java.io.File +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import java.net.Socket +import java.net.URL +import kotlin.test.fail + +class TestProxy(val serverPort: Int, val testClass: String, val classPath: List) { + + fun runTest(): String { + return Socket("localhost", serverPort).use { clientSocket -> + + val output = ObjectOutputStream(clientSocket.getOutputStream()) + val input = ObjectInputStream(clientSocket.getInputStream()) + try { + output.writeObject(MessageHeader.NEW_TEST) + output.writeObject(testClass) + output.writeObject("box") + + output.writeObject(MessageHeader.CLASS_PATH) + //filter out jdk libs + output.writeObject(filterOutJdkJars(classPath).toTypedArray()) + + val message = input.readObject() as MessageHeader + if (message == MessageHeader.RESULT) { + input.readObject() as String + } + else if (message == MessageHeader.ERROR) { + throw input.readObject() as Exception + } + else { + fail("Unknown message: $message") + } + } finally { + output.close() + input.close() + } + } + } + + fun filterOutJdkJars(classPath: List): List { + val javaHome = System.getProperty("java.home") + val javaFolder = File(javaHome) + return classPath.filterNot { + File(it.file).startsWith(javaFolder) + } + } +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.kt b/compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.kt new file mode 100644 index 00000000000..30bf7f8f4fa --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CodegenJdkCommonTestSuite.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen + +import org.jetbrains.kotlin.test.clientserver.TestProcessServer +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime +import org.junit.AfterClass +import org.junit.BeforeClass +import org.junit.runner.RunWith +import org.junit.runners.Suite +import java.io.File +import kotlin.test.assertNotNull + +/** + * This suite is used to run java codegen tests under jdk 1.6, 1.8 and 9 + * with different default targets - 1.6, 1.8, 1.9. + */ +@RunWith(Suite::class) +@Suite.SuiteClasses( + BlackBoxCodegenTestGenerated::class, + BlackBoxInlineCodegenTestGenerated::class, + CompileKotlinAgainstInlineKotlinTestGenerated::class, + CompileKotlinAgainstKotlinTestGenerated::class, + BlackBoxAgainstJavaCodegenTestGenerated::class +) +object CodegenJdkCommonTestSuite { + + private var jdkProcess: Process? = null + + @BeforeClass + @JvmStatic + fun setUp() { + val boxInSeparateProcessPort = System.getProperty(CodegenTestCase.RUN_BOX_TEST_IN_SEPARATE_PROCESS_PORT) + if (boxInSeparateProcessPort != null) { + val classpath = "out/test/tests-common" + + File.pathSeparatorChar + + ForTestCompileRuntime.runtimeJarForTests() + + File.pathSeparatorChar + + ForTestCompileRuntime.kotlinTestJarForTests() + + val jdk16 = System.getenv("JDK_16") + assertNotNull(jdk16, "Please specify JDK_16 system property to run codegen test in separate process") + + val builder = ProcessBuilder( + jdk16 + "bin/java", "-cp", classpath, + TestProcessServer::class.java.name, boxInSeparateProcessPort + ) + println("Starting separate process to run test: " + builder.command().joinToString()) + builder.inheritIO() + builder.redirectErrorStream(true) + jdkProcess = builder.start() + } + } + + @AfterClass + @JvmStatic + fun tearDown() { + if (jdkProcess != null) { + println("Stop separate test process") + jdkProcess!!.destroy() + } + } +}