Add tests for compilation against abi classes
This commit is contained in:
@@ -153,6 +153,7 @@ import org.jetbrains.kotlin.jps.incremental.AbstractJvmProtoComparisonTest
|
|||||||
import org.jetbrains.kotlin.kapt.cli.test.AbstractArgumentParsingTest
|
import org.jetbrains.kotlin.kapt.cli.test.AbstractArgumentParsingTest
|
||||||
import org.jetbrains.kotlin.kapt.cli.test.AbstractKaptToolIntegrationTest
|
import org.jetbrains.kotlin.kapt.cli.test.AbstractKaptToolIntegrationTest
|
||||||
import org.jetbrains.kotlin.jvm.abi.AbstractCompareJvmAbiTest
|
import org.jetbrains.kotlin.jvm.abi.AbstractCompareJvmAbiTest
|
||||||
|
import org.jetbrains.kotlin.jvm.abi.AbstractCompileAgainstJvmAbiTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTest
|
import org.jetbrains.kotlin.kapt3.test.AbstractClassFileToSourceStubConverterTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest
|
import org.jetbrains.kotlin.kapt3.test.AbstractKotlinKaptContextTest
|
||||||
import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg
|
import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg
|
||||||
@@ -1074,6 +1075,10 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractCompareJvmAbiTest> {
|
testClass<AbstractCompareJvmAbiTest> {
|
||||||
model("compare", recursive = false, extension = null)
|
model("compare", recursive = false, extension = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractCompileAgainstJvmAbiTest> {
|
||||||
|
model("compile", recursive = false, extension = null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testGroup("plugins/kapt3/kapt3-compiler/test", "plugins/kapt3/kapt3-compiler/testData") {
|
testGroup("plugins/kapt3/kapt3-compiler/test", "plugins/kapt3/kapt3-compiler/testData") {
|
||||||
|
|||||||
@@ -30,4 +30,5 @@ abstract class AbstractCompareJvmAbiTest : BaseJvmAbiTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package org.jetbrains.kotlin.jvm.abi
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
|
||||||
|
abstract class AbstractCompileAgainstJvmAbiTest : BaseJvmAbiTest() {
|
||||||
|
fun doTest(path: String) {
|
||||||
|
val testDir = File(path)
|
||||||
|
val lib = Compilation(testDir, "lib").also { make(it) }
|
||||||
|
val app = Compilation(testDir, "app", dependencies = listOf(lib)).also { make(it) }
|
||||||
|
runApp(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runApp(compilation: Compilation) {
|
||||||
|
val runtimeDeps = compilation.dependencies.map { dep ->
|
||||||
|
check(dep.destinationDir.exists()) { "Dependency '${dep.name}' of '${compilation.name}' was not built" }
|
||||||
|
dep.destinationDir
|
||||||
|
}
|
||||||
|
|
||||||
|
val runtimeClasspath = listOf(compilation.destinationDir) + runtimeDeps + kotlinJvmStdlib
|
||||||
|
val urls = runtimeClasspath.map { it.toURI().toURL() }.toTypedArray()
|
||||||
|
val classloader = URLClassLoader(urls)
|
||||||
|
val appClass = classloader.loadClass("app.AppKt")
|
||||||
|
val runAppMethod = appClass.getMethod("runAppAndReturnOk")
|
||||||
|
|
||||||
|
assertEquals("OK", runAppMethod.invoke(null))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@ import junit.framework.TestCase
|
|||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.incremental.AbstractIncrementalCompilerRunnerTestBase
|
|
||||||
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
|
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -32,7 +31,11 @@ abstract class BaseJvmAbiTest : TestCase() {
|
|||||||
private fun abiOption(option: String, value: String): String =
|
private fun abiOption(option: String, value: String): String =
|
||||||
"plugin:${JvmAbiCommandLineProcessor.COMPILER_PLUGIN_ID}:$option=$value"
|
"plugin:${JvmAbiCommandLineProcessor.COMPILER_PLUGIN_ID}:$option=$value"
|
||||||
|
|
||||||
inner class Compilation(val projectDir: File, val name: String) {
|
inner class Compilation(
|
||||||
|
val projectDir: File,
|
||||||
|
val name: String,
|
||||||
|
val dependencies: Collection<Compilation> = emptyList()
|
||||||
|
) {
|
||||||
val srcDir: File
|
val srcDir: File
|
||||||
get() = projectDir.resolve(name)
|
get() = projectDir.resolve(name)
|
||||||
|
|
||||||
@@ -50,11 +53,16 @@ abstract class BaseJvmAbiTest : TestCase() {
|
|||||||
check(abiPluginJar.exists()) { "Plugin jar '$abiPluginJar' does not exist" }
|
check(abiPluginJar.exists()) { "Plugin jar '$abiPluginJar' does not exist" }
|
||||||
check(compilation.srcDir.exists()) { "Source dir '${compilation.srcDir}' does not exist" }
|
check(compilation.srcDir.exists()) { "Source dir '${compilation.srcDir}' does not exist" }
|
||||||
|
|
||||||
|
val abiDependencies = compilation.dependencies.map { dep ->
|
||||||
|
check(dep.abiDir.exists()) { "Dependency '${dep.name}' of '${compilation.name}' was not built" }
|
||||||
|
dep.abiDir
|
||||||
|
}
|
||||||
|
|
||||||
val messageCollector = TestMessageCollector()
|
val messageCollector = TestMessageCollector()
|
||||||
val compiler = K2JVMCompiler()
|
val compiler = K2JVMCompiler()
|
||||||
val args = compiler.createArguments().apply {
|
val args = compiler.createArguments().apply {
|
||||||
freeArgs = listOf(compilation.srcDir.canonicalPath)
|
freeArgs = listOf(compilation.srcDir.canonicalPath)
|
||||||
classpath = kotlinJvmStdlib.canonicalPath
|
classpath = (abiDependencies + kotlinJvmStdlib).joinToString(File.pathSeparator) { it.canonicalPath }
|
||||||
pluginClasspaths = arrayOf(abiPluginJar.canonicalPath)
|
pluginClasspaths = arrayOf(abiPluginJar.canonicalPath)
|
||||||
pluginOptions = arrayOf(abiOption("outputDir", compilation.abiDir.canonicalPath))
|
pluginOptions = arrayOf(abiOption("outputDir", compilation.abiDir.canonicalPath))
|
||||||
destination = compilation.destinationDir.canonicalPath
|
destination = compilation.destinationDir.canonicalPath
|
||||||
@@ -66,7 +74,7 @@ abstract class BaseJvmAbiTest : TestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val kotlinJvmStdlib = File("dist/kotlinc/lib/kotlin-stdlib.jar").also {
|
protected val kotlinJvmStdlib = File("dist/kotlinc/lib/kotlin-stdlib.jar").also {
|
||||||
UsefulTestCase.assertExists(it)
|
UsefulTestCase.assertExists(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.jvm.abi;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/jvm-abi-gen/testData/compile")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class CompileAgainstJvmAbiTestGenerated extends AbstractCompileAgainstJvmAbiTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInCompile() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/jvm-abi-gen/testData/compile"), Pattern.compile("^([^\\.]+)$"), TargetBackend.ANY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("anonymousObject")
|
||||||
|
public void testAnonymousObject() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/anonymousObject/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classes")
|
||||||
|
public void testClasses() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/classes/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("clinit")
|
||||||
|
public void testClinit() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/clinit/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("privateOnlyConstructors")
|
||||||
|
public void testPrivateOnlyConstructors() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/privateOnlyConstructors/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevel")
|
||||||
|
public void testTopLevel() throws Exception {
|
||||||
|
runTest("plugins/jvm-abi-gen/testData/compile/topLevel/");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
val i = getInterface()
|
||||||
|
val value = i.getInt()
|
||||||
|
if (value != 10) error("getInterface().getInt() is '$value', but is expected to be '10'")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
interface Interface {
|
||||||
|
fun getInt(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInterface(): Interface =
|
||||||
|
object : Interface {
|
||||||
|
override fun getInt(): Int = 10
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun useI(i: I) {
|
||||||
|
i.iProperty
|
||||||
|
i.iMethod()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useA(a: A) {
|
||||||
|
a.iProperty
|
||||||
|
a.iMethod()
|
||||||
|
|
||||||
|
a.aProperty
|
||||||
|
a.aMethod()
|
||||||
|
a.aInlineMethod()
|
||||||
|
A.aConst
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useB(b: B) {
|
||||||
|
b.iProperty
|
||||||
|
b.iMethod()
|
||||||
|
|
||||||
|
b.aProperty
|
||||||
|
b.aMethod()
|
||||||
|
b.aInlineMethod()
|
||||||
|
|
||||||
|
b.bProperty
|
||||||
|
b.bMethod()
|
||||||
|
b.bInlineMethod()
|
||||||
|
B.bConst
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
useI(A())
|
||||||
|
useA(A())
|
||||||
|
useB(B())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
val iProperty: Int
|
||||||
|
fun iMethod(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
open class A : I {
|
||||||
|
override val iProperty: Int = 0
|
||||||
|
override fun iMethod(): Int = 10
|
||||||
|
|
||||||
|
val aProperty: Int = 20
|
||||||
|
fun aMethod(): Int = 30
|
||||||
|
inline fun aInlineMethod(): Int = 40
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val aConst: Int = 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : A() {
|
||||||
|
val bProperty: Int = 60
|
||||||
|
fun bMethod(): Int = 70
|
||||||
|
inline fun bInlineMethod(): Int = 80
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val bConst: Int = 90
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
if (Object.z != 3) error("lib.Object.z is ${Object.z}, but '3' was expected")
|
||||||
|
if (z != 3) error("lib.z is $z, but '3' was expected")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
object Object {
|
||||||
|
val x = 1
|
||||||
|
val y = 2
|
||||||
|
val z = x + y
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
val x = 1
|
||||||
|
val y = 2
|
||||||
|
val z = x + y
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
val a = A.create(10)
|
||||||
|
if (a.x != 20) error("a.x is '${a.x}', but is expected to be '20'")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
class A private constructor(val x: Int) {
|
||||||
|
companion object {
|
||||||
|
fun create(x: Int): A = A(x * 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import lib.*
|
||||||
|
|
||||||
|
fun runAppAndReturnOk(): String {
|
||||||
|
if (prop != 1) error("prop is '$prop', but is expected to be '1'")
|
||||||
|
val funcValue = func()
|
||||||
|
if (funcValue != 2) error("func() is '$funcValue', but is expected to be '2'")
|
||||||
|
val inlineFuncValue = inlineFunc()
|
||||||
|
if (inlineFuncValue != 3) error("inlineFunc() is '$inlineFuncValue', but is expected to be '3'")
|
||||||
|
if (constant != 4) error("constant is '$constant', but is expected to be '4'")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package lib
|
||||||
|
|
||||||
|
val prop: Int = 1
|
||||||
|
fun func(): Int = 2
|
||||||
|
inline fun inlineFunc(): Int = 3
|
||||||
|
const val constant: Int = 4
|
||||||
Reference in New Issue
Block a user