[IC] Smoke tests for KMP IC, part 1.5

Refactorings: rework testData to better reflect usages of declarations,
clean up internal test methods.

Merge-request: KT-MR-13232
Merged-by: Evgenii Mazhukin <evgenii.mazhukin@jetbrains.com>
This commit is contained in:
Evgenii Mazhukin
2023-11-29 13:28:26 +00:00
committed by Space Team
parent 35cf9cb0c4
commit 3f8505a090
59 changed files with 120 additions and 81 deletions
@@ -11,8 +11,14 @@ import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.testbase.relativizeTo import org.jetbrains.kotlin.gradle.testbase.relativizeTo
import java.nio.file.Path import java.nio.file.Path
import java.util.concurrent.atomic.AtomicInteger
import kotlin.io.path.appendText import kotlin.io.path.appendText
/**
* KmpIncrementalITBase is used as a "limited scope" for experimental test utils.
* If some of them can be reused widely, consider moving them to KGPBaseTest
* or the appropriate util package. //TODO: KT-63876
*/
abstract class KmpIncrementalITBase : KGPBaseTest() { abstract class KmpIncrementalITBase : KGPBaseTest() {
override val defaultBuildOptions: BuildOptions override val defaultBuildOptions: BuildOptions
@@ -38,10 +44,13 @@ abstract class KmpIncrementalITBase : KGPBaseTest() {
) )
} }
protected open fun TestProject.touchAndGet(subproject: String, srcDir: String, name: String): Path { protected fun TestProject.resolvePath(subproject: String, srcDir: String, name: String): Path {
val path = subProject(subproject).kotlinSourcesDir(srcDir).resolve(name) return subProject(subproject).kotlinSourcesDir(srcDir).resolve(name)
path.appendText("private val nothingMuch = 24") }
return path
protected fun Path.addPrivateVal(): Path {
this@addPrivateVal.appendText("private val nothingMuch${changeCounter.incrementAndGet()} = 24")
return this@addPrivateVal
} }
protected open fun BuildResult.assertSuccessOrUTD(allTasks: Set<String>, executedTasks: Set<String>) { protected open fun BuildResult.assertSuccessOrUTD(allTasks: Set<String>, executedTasks: Set<String>) {
@@ -61,4 +70,8 @@ abstract class KmpIncrementalITBase : KGPBaseTest() {
assertions() assertions()
} }
} }
companion object {
private val changeCounter = AtomicInteger(0)
}
} }
@@ -10,6 +10,9 @@ import org.jetbrains.kotlin.gradle.mpp.KmpIncrementalITBase
import org.jetbrains.kotlin.gradle.testbase.* import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
/**
* Basic smoke tests assert that the baseline IC is reasonable: if we do a local change, only a local rebuild is performed.
*/
@DisplayName("Basic incremental scenarios with KMP - K2") @DisplayName("Basic incremental scenarios with KMP - K2")
@MppGradlePluginTests @MppGradlePluginTests
open class BasicIncrementalCompilationIT : KmpIncrementalITBase() { open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
@@ -24,7 +27,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("app", "commonMain", "PlainPublicClass.kt"), incrementalPath = resolvePath("app", "commonMain", "Unused.kt").addPrivateVal(),
executedTasks = setOf( executedTasks = setOf(
":app:compileKotlinJvm", ":app:compileKotlinJvm",
":app:compileKotlinJs", ":app:compileKotlinJs",
@@ -36,7 +39,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 2: touch app:jvm, no abi change * Step 2: touch app:jvm, no abi change
*/ */
val appJvmClassKt = touchAndGet("app", "jvmMain", "PlainPublicClassJvm.kt") val appJvmClassKt = resolvePath("app", "jvmMain", "UnusedJvm.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, //TODO: it just doesn't print "Incremental compilation completed", why? (KT-63476) incrementalPath = null, //TODO: it just doesn't print "Incremental compilation completed", why? (KT-63476)
executedTasks = setOf(":app:compileKotlinJvm") executedTasks = setOf(":app:compileKotlinJvm")
@@ -49,7 +52,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("app", "jsMain", "PlainPublicClassJs.kt"), incrementalPath = resolvePath("app", "jsMain", "UnusedJs.kt").addPrivateVal(),
executedTasks = setOf(":app:compileKotlinJs"), executedTasks = setOf(":app:compileKotlinJs"),
) )
@@ -57,7 +60,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 4: touch app:native, no abi change * Step 4: touch app:native, no abi change
*/ */
touchAndGet("app", "nativeMain", "PlainPublicClassNative.kt") resolvePath("app", "nativeMain", "UnusedNative.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, // no native incremental compilation - see KT-62824 incrementalPath = null, // no native incremental compilation - see KT-62824
executedTasks = setOf(":app:compileKotlinNative"), executedTasks = setOf(":app:compileKotlinNative"),
@@ -68,7 +71,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("lib", "commonMain", "CommonUtil.kt"), incrementalPath = resolvePath("lib", "commonMain", "UsedInLibPlatformTests.kt").addPrivateVal(),
executedTasks = mainCompileTasks // TODO: KT-62642 - bad compile avoidance here executedTasks = mainCompileTasks // TODO: KT-62642 - bad compile avoidance here
) )
@@ -76,7 +79,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 6: touch lib:jvm, no abi change * Step 6: touch lib:jvm, no abi change
*/ */
val libJvmUtilKt = touchAndGet("lib", "jvmMain", "libJvmPlatformUtil.kt") val libJvmUtilKt = resolvePath("lib", "jvmMain", "UsedInAppJvmAndLibTests.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, //TODO: it just doesn't print "Incremental compilation completed", why? (KT-63476) incrementalPath = null, //TODO: it just doesn't print "Incremental compilation completed", why? (KT-63476)
executedTasks = setOf(":app:compileKotlinJvm", ":lib:compileKotlinJvm"), executedTasks = setOf(":app:compileKotlinJvm", ":lib:compileKotlinJvm"),
@@ -89,7 +92,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("lib", "jsMain", "libJsPlatformUtil.kt"), incrementalPath = resolvePath("lib", "jsMain", "UsedInAppJsAndLibTests.kt").addPrivateVal(),
executedTasks = setOf(":app:compileKotlinJs", ":lib:compileKotlinJs"), executedTasks = setOf(":app:compileKotlinJs", ":lib:compileKotlinJs"),
) )
@@ -97,7 +100,7 @@ open class BasicIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 8: touch lib:native, no abi change * Step 8: touch lib:native, no abi change
*/ */
touchAndGet("lib", "nativeMain", "libNativePlatformUtil.kt") resolvePath("lib", "nativeMain", "UsedInAppNativeAndLibTests.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, incrementalPath = null,
executedTasks = setOf(":app:compileKotlinNative", ":lib:compileKotlinNative"), executedTasks = setOf(":app:compileKotlinNative", ":lib:compileKotlinNative"),
@@ -46,7 +46,7 @@ open class BasicTestIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("lib", "commonMain", "CommonUtil.kt"), incrementalPath = resolvePath("lib", "commonMain", "UsedInLibPlatformTests.kt").addPrivateVal(),
executedTasks = mainCompileTasks, executedTasks = mainCompileTasks,
) )
@@ -55,7 +55,7 @@ open class BasicTestIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("app", "commonMain", "PlainPublicClass.kt"), incrementalPath = resolvePath("app", "commonMain", "Unused.kt").addPrivateVal(),
executedTasks = setOf( executedTasks = setOf(
":app:compileTestKotlinJvm", ":app:compileTestKotlinJvm",
":app:compileTestKotlinNative", ":app:compileTestKotlinNative",
@@ -70,7 +70,7 @@ open class BasicTestIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 3 - touch app/jvm, affect jvm tests in app * Step 3 - touch app/jvm, affect jvm tests in app
*/ */
val touchedAppJvm = touchAndGet("app", "jvmMain", "PlainPublicClassJvm.kt") val touchedAppJvm = resolvePath("app", "jvmMain", "UnusedJvm.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, incrementalPath = null,
executedTasks = setOf( executedTasks = setOf(
@@ -86,7 +86,7 @@ open class BasicTestIncrementalCompilationIT : KmpIncrementalITBase() {
*/ */
testCase( testCase(
incrementalPath = touchAndGet("app", "jsMain", "PlainPublicClassJs.kt"), incrementalPath = resolvePath("app", "jsMain", "UnusedJs.kt").addPrivateVal(),
executedTasks = setOf( executedTasks = setOf(
":app:compileTestKotlinJs", ":app:compileTestKotlinJs",
":app:jsTest", ":app:jsTest",
@@ -97,7 +97,7 @@ open class BasicTestIncrementalCompilationIT : KmpIncrementalITBase() {
* Step 5 - touch app/native, affect native tests in app * Step 5 - touch app/native, affect native tests in app
*/ */
touchAndGet("app", "nativeMain", "PlainPublicClassNative.kt") resolvePath("app", "nativeMain", "UnusedNative.kt").addPrivateVal()
testCase( testCase(
incrementalPath = null, incrementalPath = null,
executedTasks = setOf( executedTasks = setOf(
@@ -33,9 +33,9 @@ open class ExpectActualIncrementalCompilationIT : KGPBaseTest() {
build("assemble") build("assemble")
listOf( listOf(
kotlinSourcesDir("jvmMain").resolve("FooJvm.kt"), kotlinSourcesDir("jvmMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("nativeMain").resolve("FooNative.kt"), kotlinSourcesDir("nativeMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("jsMain").resolve("FooJs.kt") kotlinSourcesDir("jsMain").resolve("ActualFunFoo.kt")
).forEach { ).forEach {
it.replaceFirst("\"foo", "\"bar") it.replaceFirst("\"foo", "\"bar")
} }
@@ -44,9 +44,9 @@ open class ExpectActualIncrementalCompilationIT : KGPBaseTest() {
assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative") assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative")
assertIncrementalCompilation( assertIncrementalCompilation(
listOf( listOf(
kotlinSourcesDir("jvmMain").resolve("FooJvm.kt"), kotlinSourcesDir("jvmMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("jsMain").resolve("FooJs.kt"), kotlinSourcesDir("jsMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("commonMain").resolve("Foo.kt") kotlinSourcesDir("commonMain").resolve("ExpectFunFoo.kt")
).relativizeTo(projectPath) ).relativizeTo(projectPath)
) )
} }
@@ -59,8 +59,8 @@ open class ExpectActualIncrementalCompilationIT : KGPBaseTest() {
nativeProject("expect-actual-fun-or-class-ic", gradleVersion) { nativeProject("expect-actual-fun-or-class-ic", gradleVersion) {
build("assemble") build("assemble")
val valueKtPath = kotlinSourcesDir("commonMain").resolve("Value.kt") val unusedKtPath = kotlinSourcesDir("commonMain").resolve("Unused.kt")
valueKtPath.replaceFirst( unusedKtPath.replaceFirst(
"val secret = 1", "val secret = 1",
"val secret = \"k2\"" "val secret = \"k2\""
) )
@@ -69,10 +69,10 @@ open class ExpectActualIncrementalCompilationIT : KGPBaseTest() {
assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative") assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative")
assertIncrementalCompilation( assertIncrementalCompilation(
listOf( listOf(
kotlinSourcesDir("jvmMain").resolve("FooJvm.kt"), kotlinSourcesDir("jvmMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("jsMain").resolve("FooJs.kt"), kotlinSourcesDir("jsMain").resolve("ActualFunFoo.kt"),
kotlinSourcesDir("commonMain").resolve("Foo.kt"), kotlinSourcesDir("commonMain").resolve("ExpectFunFoo.kt"),
valueKtPath unusedKtPath
).relativizeTo(projectPath) ).relativizeTo(projectPath)
) )
} }
@@ -85,13 +85,17 @@ open class ExpectActualIncrementalCompilationIT : KGPBaseTest() {
nativeProject("expect-actual-fun-or-class-ic", gradleVersion) { nativeProject("expect-actual-fun-or-class-ic", gradleVersion) {
build("assemble") build("assemble")
kotlinSourcesDir("commonMain").resolve("Bar.kt").appendText("val irrelevant = 2") kotlinSourcesDir("commonMain").resolve("ExpectClassBar.kt").appendText("val irrelevant = 2")
build("assemble", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) { build("assemble", buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) {
assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative") assertTasksExecuted(":compileKotlinJvm", ":compileKotlinJs", ":compileKotlinNative")
assertIncrementalCompilation(listOf("commonMain", "jvmMain", "jsMain").map { sourceSet -> assertIncrementalCompilation(
kotlinSourcesDir(sourceSet).resolve("Bar.kt") listOf(
}.relativizeTo(projectPath)) kotlinSourcesDir("jvmMain").resolve("ActualClassBar.kt"),
kotlinSourcesDir("jsMain").resolve("ActualClassBar.kt"),
kotlinSourcesDir("commonMain").resolve("ExpectClassBar.kt")
).relativizeTo(projectPath)
)
} }
} }
} }
@@ -4,14 +4,10 @@ plugins {
kotlin { kotlin {
jvm() jvm()
js() js() {
<SingleNativeTarget>("native")
}
kotlin {
js {
nodejs() nodejs()
} }
<SingleNativeTarget>("native")
sourceSets { sourceSets {
val commonMain by getting { val commonMain by getting {
@@ -0,0 +1,3 @@
fun appCommonFunDependingOnLibCommon() {
println("you're ${libCommonFunForAppCommon()} years old!")
}
@@ -1,10 +1,10 @@
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class TrivialTest { class AppCommonTest {
@Test @Test
fun sayYesSaysYes() { fun sayYesSaysYes() {
assertEquals("Yes", sayYes()) assertEquals("Yes", appCommonFunForAppPlatformAndAppCommonTest())
} }
} }
@@ -0,0 +1,3 @@
class AppJsUnusedClassWithDependencies {
val line = appCommonFunForAppPlatformAndAppCommonTest()
}
@@ -0,0 +1,3 @@
class AppJsUnusedChildClass(length: Int, builder: String) : LibCommonClassForAppPlatform(length, builder) {
fun price() = length * builder.length * 300
}
@@ -0,0 +1,3 @@
class AppJvmUnusedClassWithDependencies {
val line = appCommonFunForAppPlatformAndAppCommonTest()
}
@@ -0,0 +1,3 @@
class AppJvmUnusedChildClass(length: Int, builder: String) : LibCommonClassForAppPlatform(length, builder) {
fun price() = length * builder.length * 300
}
@@ -0,0 +1,3 @@
class AppNativeUnusedClassWithDependencies {
val line = appCommonFunForAppPlatformAndAppCommonTest()
}
@@ -0,0 +1,3 @@
class AppNativeUnusedChildClass(length: Int, builder: String) : LibCommonClassForAppPlatform(length, builder) {
fun price() = length * builder.length * 300
}
@@ -4,14 +4,10 @@ plugins {
kotlin { kotlin {
jvm() jvm()
js() js() {
<SingleNativeTarget>("native")
}
kotlin {
js {
nodejs() nodejs()
} }
<SingleNativeTarget>("native")
sourceSets { sourceSets {
val commonTest by getting { val commonTest by getting {
@@ -1 +1 @@
expect fun calc(expression: String): Double expect fun expectActualCalc(expression: String): Double
@@ -0,0 +1,5 @@
open class LibCommonClassForAppPlatform(
val length: Int,
val builder: String,
) {
}
@@ -1,3 +1,3 @@
actual fun calc(expression: String): Double { actual fun expectActualCalc(expression: String): Double {
return Double.NaN return Double.NaN
} }
@@ -1,7 +1,7 @@
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class AdvancedTest { class LibJsTest {
@Test @Test
fun jsUtilReturns0() { fun jsUtilReturns0() {
@@ -10,6 +10,6 @@ class AdvancedTest {
@Test @Test
fun commonUtilTest() { fun commonUtilTest() {
assertEquals(2, multiplyByTwo(1)) assertEquals(2, libCommonFunForLibPlatformTests(1))
} }
} }
@@ -1,3 +1,3 @@
actual fun calc(expression: String): Double { actual fun expectActualCalc(expression: String): Double {
return expression.toDoubleOrNull()?.let { it * 2 } ?: 0.0 return expression.toDoubleOrNull()?.let { it * 2 } ?: 0.0
} }
@@ -1,7 +1,7 @@
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class AdvancedTest { class LibJvmTest {
@Test @Test
fun jvmUtilReturns400() { fun jvmUtilReturns400() {
@@ -10,6 +10,6 @@ class AdvancedTest {
@Test @Test
fun commonUtilTest() { fun commonUtilTest() {
assertEquals(2, multiplyByTwo(1)) assertEquals(2, libCommonFunForLibPlatformTests(1))
} }
} }
@@ -1,3 +1,3 @@
actual fun calc(expression: String): Double { actual fun expectActualCalc(expression: String): Double {
return 15.0 return 15.0
} }
@@ -1,7 +1,7 @@
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class AdvancedTest { class LibNativeTest {
@Test @Test
fun nativeUtilReturns800() { fun nativeUtilReturns800() {
@@ -10,6 +10,6 @@ class AdvancedTest {
@Test @Test
fun commonUtilTest() { fun commonUtilTest() {
assertEquals(2, multiplyByTwo(1)) assertEquals(2, libCommonFunForLibPlatformTests(1))
} }
} }