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()
+ }
+ }
+}