migrated CommonNativeIT to junit 5 and gradle TestKit

#KT-51553 In Progress

Co-authored-by: Alexander Likhachev <Alexander.Likhachev@jetbrains.com>

Merge-request: KT-MR-9750
Merged-by: Dmitrii Krasnov <Dmitrii.Krasnov@jetbrains.com>
This commit is contained in:
Dmitrii Krasnov
2023-05-08 09:38:13 +00:00
committed by Space Team
parent 530725c6bf
commit 4dd54e4de4
4 changed files with 160 additions and 124 deletions
@@ -1,101 +1,93 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.gradle.native
import org.jetbrains.kotlin.gradle.BaseGradleIT
import org.jetbrains.kotlin.gradle.GradleVersionRequired
import org.jetbrains.kotlin.gradle.transformProjectWithPluginsDsl
import org.jetbrains.kotlin.konan.target.HostManager
import org.junit.Assume
import org.junit.BeforeClass
import org.junit.Test
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.capitalize
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.condition.OS
import java.util.*
class CommonNativeIT : BaseGradleIT() {
@OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
@DisplayName("K/N tests of apple native common libs")
@NativeGradlePluginTests
class CommonNativeIT : KGPBaseTest() {
override val defaultGradleVersion: GradleVersionRequired
get() = GradleVersionRequired.FOR_MPP_SUPPORT
// TODO(Dmitrii Krasnov): remove it, when KT-58104 will be fixed
override val defaultBuildOptions = super.defaultBuildOptions.copy(statisticsForceValidation = false)
private val String.withPrefix get() = "native-apple-devices-common/$this"
@DisplayName("Common ios")
@GradleTest
fun testCommonIos(gradleVersion: GradleVersion) {
doCommonNativeTest(
"common-ios",
libTargets = listOf("iosLibArm64", "iosLibX64"),
appTargets = listOf("iosArm64", "iosX64"),
gradleVersion
)
}
@DisplayName("Common watchos")
@GradleTest
fun testCommonWatchos(gradleVersion: GradleVersion) {
doCommonNativeTest(
"common-watchos",
libTargets = listOf("watchosLibArm32", "watchosLibArm64", "watchosLibX64"),
appTargets = listOf("watchosArm32", "watchosArm64", "watchosX64"),
gradleVersion
)
}
@DisplayName("Common tvos")
@GradleTest
fun testCommonTvos(gradleVersion: GradleVersion) {
doCommonNativeTest(
"common-tvos",
libTargets = listOf("tvosLibArm64", "tvosLibX64"),
appTargets = listOf("tvosArm64", "tvosX64"),
gradleVersion
)
}
private fun doCommonNativeTest(
projectName: String,
libTargets: List<String>,
appTargets: List<String>
) = with(transformProjectWithPluginsDsl(projectName, directoryPrefix = "native-apple-devices-common")) {
gradleProperties().apply {
appTargets: List<String>,
gradleVersion: GradleVersion
) {
nativeProject(projectName.withPrefix, gradleVersion) {
configureJvmMemory()
}
val libCompileTasks = libTargets.map { ":lib:compileKotlin${it.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}" }
val appCompileTasks = appTargets.map { ":app:compileKotlin${it.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}" }
val appLinkFrameworkTasks = appTargets.map {
":app:linkDebugFramework${
it.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(
Locale.getDefault()
) else it.toString()
val libCompileTasks = libTargets.map { ":lib:compileKotlin${it.capitalize()}" }
val appCompileTasks = appTargets.map { ":app:compileKotlin${it.capitalize()}" }
val appLinkFrameworkTasks = appTargets.map { ":app:linkDebugFramework${it.capitalize()}" }
val appLinkTestTasks = appTargets.map { ":app:linkDebugTest${it.capitalize()}" }
build(":lib:publish") {
assertTasksExecuted(libCompileTasks)
libTargets.forEach {
assertOutputContains("Configuring $it")
assertFileInProjectExists("lib/build/classes/kotlin/$it/main/klib/lib.klib")
}
}" }
val appLinkTestTasks = appTargets.map { ":app:linkDebugTest${it.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}" }
build(":lib:publish") {
assertSuccessful()
assertTasksExecuted(libCompileTasks)
libTargets.forEach {
assertContains("Configuring $it")
assertFileExists("lib/build/classes/kotlin/$it/main/klib/lib.klib")
}
}
build(":app:build", *appLinkTestTasks.toTypedArray()) {
assertSuccessful()
assertTasksExecuted(appCompileTasks)
assertTasksExecuted(appLinkFrameworkTasks)
assertTasksExecuted(appLinkTestTasks)
build(":app:build", *appLinkTestTasks.toTypedArray()) {
assertTasksExecuted(appCompileTasks)
assertTasksExecuted(appLinkFrameworkTasks)
assertTasksExecuted(appLinkTestTasks)
appTargets.forEach {
assertFileExists("app/build/classes/kotlin/$it/main/klib/app.klib")
assertFileExists("app/build/bin/$it/debugFramework")
assertFileExists("app/build/bin/$it/debugTest")
appTargets.forEach {
assertFileInProjectExists("app/build/classes/kotlin/$it/main/klib/app.klib")
assertDirectoryInProjectExists("app/build/bin/$it/debugFramework")
assertDirectoryInProjectExists("app/build/bin/$it/debugTest")
}
}
}
}
@Test
fun testCommonIos() {
doCommonNativeTest(
"common-ios",
libTargets = listOf("iosLibArm64", "iosLibX64"),
appTargets = listOf("iosArm64", "iosX64")
)
}
@Test
fun testCommonWatchos() {
doCommonNativeTest(
"common-watchos",
libTargets = listOf("watchosLibArm32", "watchosLibArm64", "watchosLibX64"),
appTargets = listOf("watchosArm32", "watchosArm64", "watchosX64")
)
}
@Test
fun testCommonTvos() {
doCommonNativeTest(
"common-tvos",
libTargets = listOf("tvosLibArm64", "tvosLibX64"),
appTargets = listOf("tvosArm64", "tvosX64")
)
}
companion object {
@BeforeClass
@JvmStatic
fun assumeItsMac() {
Assume.assumeTrue(HostManager.hostIsMac)
}
}
}
}
@@ -47,7 +47,7 @@ class FatFrameworkIT : KGPBaseTest() {
nativeProject(
"native-fat-framework/smoke",
gradleVersion,
// TODO(d.krasnov): return default statisticsForceValidation, when KT-58104 will be fixed
// TODO(Dmitrii Krasnov): return default statisticsForceValidation, when KT-58104 will be fixed
buildOptions = defaultBuildOptions.copy(statisticsForceValidation = false)
) {
buildGradleKts.modify {
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.presetName
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
@@ -56,7 +57,6 @@ fun KGPBaseTest.project(
projectPath.enableCacheRedirector()
projectPath.enableAndroidSdk()
if (addHeapDumpOptions) projectPath.addHeapDumpOptions()
val gradleRunner = GradleRunner
.create()
@@ -74,6 +74,7 @@ fun KGPBaseTest.project(
enableBuildScan = enableBuildScan,
enableGradleDebug = enableGradleDebug,
)
addHeapDumpOptions.ifTrue { testProject.addHeapDumpOptions() }
localRepoDir?.let { testProject.configureLocalRepository(localRepoDir) }
if (buildJdk != null) testProject.setupNonDefaultJdk(buildJdk)
testProject.addKotlinCompilerArgumentsPlugin()
@@ -595,49 +596,14 @@ internal fun Path.enableCacheRedirector() {
}
}
private fun Path.addHeapDumpOptions() {
val propertiesFile = resolve("gradle.properties")
if (!propertiesFile.exists()) propertiesFile.createFile()
val propertiesContent = propertiesFile.readText()
val (existingJvmArgsLine, otherLines) = propertiesContent
.lines()
.partition {
it.trim().startsWith("org.gradle.jvmargs")
}
val heapDumpOutOfErrorStr = "-XX:+HeapDumpOnOutOfMemoryError"
val heapDumpPathStr = "-XX:HeapDumpPath=\"${System.getProperty("user.dir")}${File.separatorChar}build\""
if (existingJvmArgsLine.isEmpty()) {
propertiesFile.writeText(
"""
|# modified in addHeapDumpOptions
|org.gradle.jvmargs=$heapDumpOutOfErrorStr $heapDumpPathStr
|
|$propertiesContent
""".trimMargin()
)
} else {
val argsLine = existingJvmArgsLine.first()
val appendedOptions = buildString {
if (!argsLine.contains("HeapDumpOnOutOfMemoryError")) append(" $heapDumpOutOfErrorStr")
if (!argsLine.contains("HeapDumpPath")) append(" $heapDumpPathStr")
}
if (appendedOptions.isNotEmpty()) {
propertiesFile.writeText(
"""
# modified in addHeapDumpOptions
$argsLine$appendedOptions
${otherLines.joinToString(separator = "\n")}
""".trimIndent()
)
} else {
println("<=== Heap dump options are already exists! ===>")
}
}
private fun GradleProject.addHeapDumpOptions() {
addPropertyToGradleProperties(
propertyName = "org.gradle.jvmargs",
mapOf(
"-XX:+HeapDumpOnOutOfMemoryError" to "-XX:+HeapDumpOnOutOfMemoryError",
"-XX:HeapDumpPath" to "-XX:HeapDumpPath=\"${System.getProperty("user.dir")}${File.separatorChar}build\""
),
)
}
private const val SINGLE_NATIVE_TARGET_PLACEHOLDER = "<SingleNativeTarget>"
@@ -79,3 +79,81 @@ fun TestProject.makeSnapshotTo(destinationPath: String) {
copyTo(dest.resolve(fileName))
}
}
/**
*
* Configures the JVM memory settings for the Gradle project.
* @param memorySizeInGb The amount of memory to allocate to the JVM, in gigabytes.
* Defaults to 1 gigabyte.
*/
fun GradleProject.configureJvmMemory(memorySizeInGb: Number = 1) {
addPropertyToGradleProperties(
propertyName = "org.gradle.jvmargs",
mapOf("-Xmx" to "-Xmx${memorySizeInGb}g")
)
}
/**
* Adds the given options to a Gradle property specified by name, in the project's Gradle properties file.
* If the property does not exist, it is created.
* @param propertyName The name of the Gradle property to modify or create.
* @param propertyValues Map with key = "option prefix", and value = "option value".
* For example, for options: -Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
* Map would be look like: Map.of("-Xmx", "-Xmx2g",
* "-XX:MaxMetaspaceSize","-XX:MaxMetaspaceSize=512m",
* "-XX:+HeapDumpOnOutOfMemoryError", "-XX:+HeapDumpOnOutOfMemoryError" )
*/
fun GradleProject.addPropertyToGradleProperties(
propertyName: String,
propertyValues: Map<String, String>
) {
if (!gradleProperties.exists()) gradleProperties.createFile()
val propertiesContent = gradleProperties.readText()
val (existingPropertyLine, otherLines) = propertiesContent
.lines()
.partition {
it.trim().startsWith(propertyName)
}
if (existingPropertyLine.isEmpty()) {
gradleProperties.writeText(
"""
|${propertyName}=${propertyValues.values.joinToString(" ")}
|
|$propertiesContent
""".trimMargin()
)
} else {
val argsLine = existingPropertyLine.single()
val optionsToRewrite = mutableListOf<String>()
val appendedOptions = buildString {
propertyValues.forEach {
if (argsLine.contains(it.key) &&
!argsLine.contains(it.value)
) optionsToRewrite.add(it.value)
else
if (!argsLine.contains(it.key)) append(" ${it.value}")
}
}
assert(optionsToRewrite.isEmpty()) {
"""
|You are trying to write options: $optionsToRewrite
|for property: $propertyName
|in $gradleProperties
|But these options are already exists with another values.
|Current property value is: $argsLine
""".trimMargin()
}
gradleProperties.writeText(
"""
|$argsLine$appendedOptions
|
|${otherLines.joinToString(separator = "\n")}
""".trimMargin()
)
}
}