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.AbstractKaptToolIntegrationTest
|
||||
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.AbstractKotlinKaptContextTest
|
||||
import org.jetbrains.kotlin.noarg.AbstractBlackBoxCodegenTestForNoArg
|
||||
@@ -1074,6 +1075,10 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractCompareJvmAbiTest> {
|
||||
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") {
|
||||
|
||||
@@ -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.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.AbstractIncrementalCompilerRunnerTestBase
|
||||
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
|
||||
import java.io.File
|
||||
|
||||
@@ -32,7 +31,11 @@ abstract class BaseJvmAbiTest : TestCase() {
|
||||
private fun abiOption(option: String, value: String): String =
|
||||
"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
|
||||
get() = projectDir.resolve(name)
|
||||
|
||||
@@ -50,11 +53,16 @@ abstract class BaseJvmAbiTest : TestCase() {
|
||||
check(abiPluginJar.exists()) { "Plugin jar '$abiPluginJar' 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 compiler = K2JVMCompiler()
|
||||
val args = compiler.createArguments().apply {
|
||||
freeArgs = listOf(compilation.srcDir.canonicalPath)
|
||||
classpath = kotlinJvmStdlib.canonicalPath
|
||||
classpath = (abiDependencies + kotlinJvmStdlib).joinToString(File.pathSeparator) { it.canonicalPath }
|
||||
pluginClasspaths = arrayOf(abiPluginJar.canonicalPath)
|
||||
pluginOptions = arrayOf(abiOption("outputDir", compilation.abiDir.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)
|
||||
}
|
||||
}
|
||||
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