Gradle, native: Support simulator tests
This commit is contained in:
+1
-1
@@ -149,7 +149,7 @@ fun generateAbstractKotlinNativeBinaryContainer() {
|
||||
|
||||
val classProperties = listOf(
|
||||
"abstract val project: Project",
|
||||
"abstract val target: ${typeName(KOTLIN_NATIVE_TARGET_CLASS_FQNAME).shortName()}"
|
||||
"abstract val target: ${typeName(NativeFQNames.Targets.base).shortName()}"
|
||||
).joinToString(separator = "\n") { it.indented(4) }
|
||||
|
||||
val nativeBinary = nativeBinaryBaseClass.renderShort()
|
||||
|
||||
+34
-20
@@ -5,6 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.generators.gradle.dsl
|
||||
|
||||
import org.jetbrains.kotlin.generators.gradle.dsl.NativeFQNames.Presets
|
||||
import org.jetbrains.kotlin.generators.gradle.dsl.NativeFQNames.Targets
|
||||
import org.jetbrains.kotlin.generators.gradle.dsl.NativeFQNames.TestRuns
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.presetName
|
||||
@@ -19,11 +22,25 @@ internal fun KotlinPresetEntry.typeNames(): Set<TypeName> = setOf(presetType, ta
|
||||
|
||||
internal const val MPP_PACKAGE = "org.jetbrains.kotlin.gradle.plugin.mpp"
|
||||
|
||||
internal const val KOTLIN_NATIVE_TARGET_PRESET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTargetPreset"
|
||||
internal const val KOTLIN_NATIVE_TARGET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTarget"
|
||||
internal object NativeFQNames {
|
||||
const val nativePackage = "org.jetbrains.kotlin.gradle.targets.native"
|
||||
|
||||
internal const val KOTLIN_NATIVE_TARGET_WITH_TESTS_PRESET_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTargetWithTestsPreset"
|
||||
internal const val KOTLIN_NATIVE_TARGET_WITH_TESTS_CLASS_FQNAME = "$MPP_PACKAGE.KotlinNativeTargetWithTests"
|
||||
object Targets {
|
||||
const val base = "$MPP_PACKAGE.KotlinNativeTarget"
|
||||
const val withTests = "$MPP_PACKAGE.KotlinNativeTargetWithTests"
|
||||
}
|
||||
|
||||
object Presets {
|
||||
const val simple = "$MPP_PACKAGE.KotlinNativeTargetPreset"
|
||||
const val withHostTests = "$MPP_PACKAGE.KotlinNativeTargetWithHostTestsPreset"
|
||||
const val withSimulatorTests = "$MPP_PACKAGE.KotlinNativeTargetWithSimulatorTestsPreset"
|
||||
}
|
||||
|
||||
object TestRuns {
|
||||
const val host = "$nativePackage.KotlinNativeHostTestRun"
|
||||
const val simulator = "$nativePackage.KotlinNativeSimulatorTestRun"
|
||||
}
|
||||
}
|
||||
|
||||
internal val jvmPresetEntry = KotlinPresetEntry(
|
||||
"jvm",
|
||||
@@ -44,27 +61,24 @@ internal val androidPresetEntry = KotlinPresetEntry(
|
||||
)
|
||||
|
||||
// Note: modifying these sets should also be reflected in the MPP plugin code, see 'setupDefaultPresets'
|
||||
private val testableNativeTargets = setOf(KonanTarget.LINUX_X64, KonanTarget.MACOS_X64, KonanTarget.MINGW_X64)
|
||||
private val nativeTargetsWithHostTests = setOf(KonanTarget.LINUX_X64, KonanTarget.MACOS_X64, KonanTarget.MINGW_X64)
|
||||
private val nativeTargetsWithSimulatorTests = setOf(KonanTarget.IOS_X64, KonanTarget.WATCHOS_X86, KonanTarget.TVOS_X64)
|
||||
private val disabledNativeTargets = setOf(KonanTarget.WATCHOS_X64)
|
||||
|
||||
internal val nativePresetEntries = HostManager().targets
|
||||
.filter { (_, target) -> target !in disabledNativeTargets }
|
||||
.map { (_, target) ->
|
||||
KotlinPresetEntry(
|
||||
target.presetName,
|
||||
typeName(
|
||||
if (target in testableNativeTargets)
|
||||
KOTLIN_NATIVE_TARGET_WITH_TESTS_PRESET_CLASS_FQNAME
|
||||
else
|
||||
KOTLIN_NATIVE_TARGET_PRESET_CLASS_FQNAME
|
||||
),
|
||||
typeName(
|
||||
if (target in testableNativeTargets)
|
||||
KOTLIN_NATIVE_TARGET_WITH_TESTS_CLASS_FQNAME
|
||||
else
|
||||
KOTLIN_NATIVE_TARGET_CLASS_FQNAME
|
||||
)
|
||||
)
|
||||
|
||||
val (presetType, targetType) = when (target) {
|
||||
in nativeTargetsWithHostTests ->
|
||||
typeName(Presets.withHostTests) to typeName(Targets.withTests, TestRuns.host)
|
||||
in nativeTargetsWithSimulatorTests ->
|
||||
typeName(Presets.withSimulatorTests) to typeName(Targets.withTests, TestRuns.simulator)
|
||||
else ->
|
||||
typeName(Presets.simple) to typeName(Targets.base)
|
||||
}
|
||||
|
||||
KotlinPresetEntry(target.presetName, presetType, targetType)
|
||||
}
|
||||
|
||||
internal val allPresetEntries = listOf(
|
||||
|
||||
+20
-9
@@ -1280,7 +1280,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
|
||||
@Test
|
||||
fun testNativeTests() = with(Project("new-mpp-native-tests", gradleVersion)) {
|
||||
val testTasks = listOf("macos64Test", "linux64Test", "mingw64Test")
|
||||
val testTasks = listOf("macos64Test", "linux64Test", "mingw64Test", "iosTest")
|
||||
val hostTestTask = "${nativeHostTargetName}Test"
|
||||
|
||||
val suffix = if (isWindows) "exe" else "kexe"
|
||||
@@ -1305,7 +1305,16 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
|
||||
build("check") {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(":$hostTestTask")
|
||||
|
||||
val testsToExecute = mutableListOf(":$hostTestTask")
|
||||
if (HostManager.hostIsMac) {
|
||||
testsToExecute.add(":iosTest")
|
||||
}
|
||||
val testsToSkip = testTasks.map { ":$it" } - testsToExecute
|
||||
|
||||
assertTasksExecuted(*testsToExecute.toTypedArray())
|
||||
assertTasksSkipped(*testsToSkip.toTypedArray())
|
||||
|
||||
assertFileExists(defaultOutputFile)
|
||||
assertTestResults("testProject/new-mpp-native-tests/TEST-TestKt.xml", hostTestTask)
|
||||
}
|
||||
@@ -2122,8 +2131,8 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
gradleBuildScript().modify(::transformBuildScriptWithPluginsDsl)
|
||||
|
||||
// TOOD: add Kotlin/JS tests once they can be tested without much performance overhead
|
||||
val testTasks =
|
||||
arrayOf(":jvmTest", ":${nativeHostTargetName}Test", ":jvmIntegrationTest", ":${nativeHostTargetName}IntegrationTest")
|
||||
val targetsToTest = listOf("jvm", nativeHostTargetName) + listOf("ios").takeIf { HostManager.hostIsMac }.orEmpty()
|
||||
val testTasks = targetsToTest.flatMap { listOf(":${it}Test", ":${it}IntegrationTest") }.toTypedArray()
|
||||
|
||||
build(*testTasks) {
|
||||
assertSuccessful()
|
||||
@@ -2139,11 +2148,12 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
.resolve("build/reports/tests/${targetName}Test/classes/com.example.HelloTest.html")
|
||||
.readText()
|
||||
|
||||
if (targetName != nativeHostTargetName) // TODO: fix exclude patterns for the Kotlin/Native test tasks
|
||||
if (targetName != nativeHostTargetName && targetName != "ios") // TODO: fix exclude patterns for the Kotlin/Native test tasks
|
||||
assertTrue("secondTest" !in classReportHtml, "Test report should not contain 'secondTest':\n$classReportHtml")
|
||||
}
|
||||
checkUnitTestOutput("jvm")
|
||||
checkUnitTestOutput(nativeHostTargetName)
|
||||
targetsToTest.forEach {
|
||||
checkUnitTestOutput(it)
|
||||
}
|
||||
|
||||
fun checkIntegrationTestOutput(targetName: String) {
|
||||
val classReportHtml = projectDir
|
||||
@@ -2154,8 +2164,9 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
assertTrue("secondTest" !in classReportHtml, "Test report should not contain 'secondTest':\n$classReportHtml")
|
||||
assertTrue("thirdTest" !in classReportHtml, "Test report should not contain 'thirdTest':\n$classReportHtml")
|
||||
}
|
||||
checkIntegrationTestOutput("jvm")
|
||||
checkIntegrationTestOutput(nativeHostTargetName)
|
||||
targetsToTest.forEach {
|
||||
checkIntegrationTestOutput(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -49,6 +49,7 @@ kotlin {
|
||||
mingwX64("mingw64") {}
|
||||
linuxX64("linux64") {}
|
||||
macosX64("macos64") {}
|
||||
iosX64("ios") {}
|
||||
|
||||
targets.matching { it.name != "metadata" }.all {
|
||||
compilations.create("integrationTest") {
|
||||
@@ -89,7 +90,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
targets.matching { it.name == "mingw64" || it.name == "linux64" || it.name == "macos64" }.all {
|
||||
targets.matching { it.name == "mingw64" || it.name == "linux64" || it.name == "macos64" || it.name == "ios" }.all {
|
||||
testRuns {
|
||||
getByName("test").filter { excludeTestsMatching("*.secondTest") }
|
||||
|
||||
|
||||
+2
@@ -25,6 +25,8 @@ kotlin {
|
||||
fromPreset(presets.linuxX64, 'linux64')
|
||||
fromPreset(presets.mingwX64, 'mingw64')
|
||||
|
||||
fromPreset(presets.iosX64, 'ios')
|
||||
|
||||
// Test creating and accessing test binaries for cross-targets
|
||||
fromPreset(presets.wasm32, 'wasm')
|
||||
|
||||
|
||||
+22
-19
@@ -9,10 +9,13 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTestsPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithSimulatorTestsPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTestsPreset
|
||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
|
||||
import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeHostTestRun
|
||||
import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeSimulatorTestRun
|
||||
|
||||
// DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppPresetFunctionsCodegenKt
|
||||
|
||||
@@ -155,11 +158,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun iosX64(
|
||||
name: String = "iosX64",
|
||||
configure: KotlinNativeTarget.() -> Unit = { }
|
||||
): KotlinNativeTarget =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("iosX64") as KotlinNativeTargetPreset,
|
||||
presets.getByName("iosX64") as KotlinNativeTargetWithSimulatorTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
@@ -200,11 +203,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun watchosX86(
|
||||
name: String = "watchosX86",
|
||||
configure: KotlinNativeTarget.() -> Unit = { }
|
||||
): KotlinNativeTarget =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("watchosX86") as KotlinNativeTargetPreset,
|
||||
presets.getByName("watchosX86") as KotlinNativeTargetWithSimulatorTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
@@ -230,11 +233,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun tvosX64(
|
||||
name: String = "tvosX64",
|
||||
configure: KotlinNativeTarget.() -> Unit = { }
|
||||
): KotlinNativeTarget =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("tvosX64") as KotlinNativeTargetPreset,
|
||||
presets.getByName("tvosX64") as KotlinNativeTargetWithSimulatorTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
@@ -245,11 +248,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun linuxX64(
|
||||
name: String = "linuxX64",
|
||||
configure: KotlinNativeTargetWithTests.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeHostTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeHostTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("linuxX64") as KotlinNativeTargetWithTestsPreset,
|
||||
presets.getByName("linuxX64") as KotlinNativeTargetWithHostTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
@@ -320,11 +323,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun mingwX64(
|
||||
name: String = "mingwX64",
|
||||
configure: KotlinNativeTargetWithTests.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeHostTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeHostTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("mingwX64") as KotlinNativeTargetWithTestsPreset,
|
||||
presets.getByName("mingwX64") as KotlinNativeTargetWithHostTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
@@ -350,11 +353,11 @@ interface KotlinTargetContainerWithPresetFunctions : KotlinTargetsContainerWithP
|
||||
|
||||
fun macosX64(
|
||||
name: String = "macosX64",
|
||||
configure: KotlinNativeTargetWithTests.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests =
|
||||
configure: KotlinNativeTargetWithTests<KotlinNativeHostTestRun>.() -> Unit = { }
|
||||
): KotlinNativeTargetWithTests<KotlinNativeHostTestRun> =
|
||||
configureOrCreate(
|
||||
name,
|
||||
presets.getByName("macosX64") as KotlinNativeTargetWithTestsPreset,
|
||||
presets.getByName("macosX64") as KotlinNativeTargetWithHostTestsPreset,
|
||||
configure
|
||||
)
|
||||
|
||||
|
||||
+15
-11
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget.*
|
||||
import org.jetbrains.kotlin.konan.target.presetName
|
||||
|
||||
class KotlinMultiplatformPlugin(
|
||||
@@ -139,18 +139,22 @@ class KotlinMultiplatformPlugin(
|
||||
add(KotlinJvmWithJavaTargetPreset(project, kotlinPluginVersion))
|
||||
|
||||
// Note: modifying these sets should also be reflected in the DSL code generator, see 'presetEntries.kt'
|
||||
val testableNativeTargets = setOf(KonanTarget.LINUX_X64, KonanTarget.MACOS_X64, KonanTarget.MINGW_X64)
|
||||
val disabledNativeTargets = setOf(KonanTarget.WATCHOS_X64)
|
||||
val nativeTargetsWithHostTests = setOf(LINUX_X64, MACOS_X64, MINGW_X64)
|
||||
val nativeTargetsWithSimulatorTests = setOf(IOS_X64, WATCHOS_X86, TVOS_X64)
|
||||
val disabledNativeTargets = setOf(WATCHOS_X64)
|
||||
|
||||
HostManager().targets
|
||||
.filter { (_, target) -> target !in disabledNativeTargets }
|
||||
.forEach { (_, target) ->
|
||||
add(
|
||||
if (target in testableNativeTargets)
|
||||
KotlinNativeTargetWithTestsPreset(target.presetName, project, target, kotlinPluginVersion)
|
||||
else
|
||||
KotlinNativeTargetPreset(target.presetName, project, target, kotlinPluginVersion)
|
||||
)
|
||||
.filter { (_, konanTarget) -> konanTarget !in disabledNativeTargets }
|
||||
.forEach { (_, konanTarget) ->
|
||||
val targetToAdd = when (konanTarget) {
|
||||
in nativeTargetsWithHostTests ->
|
||||
KotlinNativeTargetWithHostTestsPreset(konanTarget.presetName, project, konanTarget, kotlinPluginVersion)
|
||||
in nativeTargetsWithSimulatorTests ->
|
||||
KotlinNativeTargetWithSimulatorTestsPreset(konanTarget.presetName, project, konanTarget, kotlinPluginVersion)
|
||||
else -> KotlinNativeTargetPreset(konanTarget.presetName, project, konanTarget, kotlinPluginVersion)
|
||||
}
|
||||
|
||||
add(targetToAdd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-3
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTargetTestRun
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
||||
import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun
|
||||
|
||||
@@ -29,8 +31,18 @@ interface KotlinNativeBinaryTestRun : KotlinTargetTestRun<NativeBinaryTestRunSou
|
||||
fun setExecutionSourceFrom(testExecutable: TestExecutable)
|
||||
}
|
||||
|
||||
open class DefaultKotlinNativeTestRun(testRunName: String, target: KotlinNativeTarget) :
|
||||
KotlinTaskTestRun<NativeBinaryTestRunSource, KotlinNativeTest>(testRunName, target),
|
||||
interface KotlinNativeHostTestRun : KotlinNativeBinaryTestRun
|
||||
|
||||
interface KotlinNativeSimulatorTestRun : KotlinNativeBinaryTestRun {
|
||||
/**
|
||||
* Determines which simulated device will be used to execute the test run.
|
||||
* To get list of all available devices, run `xcrun simctl list`.
|
||||
*/
|
||||
var deviceId: String
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinNativeTestRun<T : KotlinNativeTest>(testRunName: String, target: KotlinNativeTarget) :
|
||||
KotlinTaskTestRun<NativeBinaryTestRunSource, T>(testRunName, target),
|
||||
KotlinNativeBinaryTestRun {
|
||||
|
||||
private lateinit var _executionSource: NativeBinaryTestRunSource
|
||||
@@ -46,10 +58,25 @@ open class DefaultKotlinNativeTestRun(testRunName: String, target: KotlinNativeT
|
||||
|
||||
override fun setExecutionSourceFrom(testExecutable: TestExecutable) {
|
||||
require(testExecutable.target === target) {
|
||||
"Expected a test fbinary of target ${target.name}, " +
|
||||
"Expected a test binary of target ${target.name}, " +
|
||||
"got the binary ${testExecutable.name} of target ${testExecutable.target.name}"
|
||||
}
|
||||
|
||||
executionSource = NativeBinaryTestRunSource(testExecutable)
|
||||
}
|
||||
}
|
||||
|
||||
open class DefaultHostTestRun(testRunName: String, target: KotlinNativeTarget) :
|
||||
AbstractKotlinNativeTestRun<KotlinNativeHostTest>(testRunName, target),
|
||||
KotlinNativeHostTestRun
|
||||
|
||||
open class DefaultSimulatorTestRun(testRunName: String, target: KotlinNativeTarget) :
|
||||
AbstractKotlinNativeTestRun<KotlinNativeSimulatorTest>(testRunName, target),
|
||||
KotlinNativeSimulatorTestRun {
|
||||
|
||||
override var deviceId: String
|
||||
get() = executionTask.get().deviceId
|
||||
set(value) {
|
||||
executionTask.get().deviceId = value
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -65,11 +65,12 @@ open class KotlinNativeTarget @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
open class KotlinNativeTargetWithTests @Inject constructor(
|
||||
// TODO: Add separate classes for corresponding targets?
|
||||
open class KotlinNativeTargetWithTests<T : KotlinNativeBinaryTestRun> @Inject constructor(
|
||||
project: Project,
|
||||
konanTarget: KonanTarget
|
||||
) : KotlinNativeTarget(project, konanTarget), KotlinTargetWithTests<NativeBinaryTestRunSource, KotlinNativeBinaryTestRun> {
|
||||
) : KotlinNativeTarget(project, konanTarget), KotlinTargetWithTests<NativeBinaryTestRunSource, T> {
|
||||
|
||||
override lateinit var testRuns: NamedDomainObjectContainer<KotlinNativeBinaryTestRun>
|
||||
override lateinit var testRuns: NamedDomainObjectContainer<T>
|
||||
internal set
|
||||
}
|
||||
+83
-21
@@ -21,13 +21,16 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.targets.native.DefaultKotlinNativeTestRun
|
||||
import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeBinaryTestRun
|
||||
import org.jetbrains.kotlin.gradle.targets.native.*
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeHostTest
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest
|
||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeTest
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.testing.internal.configureConventions
|
||||
import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry
|
||||
import org.jetbrains.kotlin.gradle.testing.testTaskName
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
@@ -279,7 +282,10 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget>(
|
||||
}
|
||||
|
||||
/**
|
||||
* We create test binaries for all platforms but test runs only for host platforms, see [KotlinNativeTargetWithTestsConfigurator]
|
||||
* We create test binaries for all platforms but test runs only for:
|
||||
* - host platforms: macosX64, linuxX64, mingwX64;
|
||||
* - simulated platforms: iosX64, tvosX64, watchosX64.
|
||||
* See more in [KotlinNativeTargetWithTestsConfigurator] and its subclasses.
|
||||
*/
|
||||
target.binaries.test(listOf(NativeBuildType.DEBUG)) { }
|
||||
}
|
||||
@@ -381,34 +387,40 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget>(
|
||||
usesPlatformOf(target)
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
|
||||
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
|
||||
description = "Dependencies for cinterop '${cinterop.name}' (compilation '${compilation.name}')."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinNativeTargetWithTestsConfigurator(kotlinPluginVersion: String) :
|
||||
KotlinNativeTargetConfigurator<KotlinNativeTargetWithTests>(kotlinPluginVersion),
|
||||
KotlinTargetWithTestsConfigurator<KotlinNativeBinaryTestRun, KotlinNativeTargetWithTests> {
|
||||
abstract class KotlinNativeTargetWithTestsConfigurator<TaskType : KotlinNativeTest, TestRunType : KotlinNativeBinaryTestRun>(
|
||||
kotlinPluginVersion: String
|
||||
) : KotlinNativeTargetConfigurator<KotlinNativeTargetWithTests<TestRunType>>(kotlinPluginVersion),
|
||||
KotlinTargetWithTestsConfigurator<TestRunType, KotlinNativeTargetWithTests<TestRunType>> {
|
||||
|
||||
override val testRunClass: Class<KotlinNativeBinaryTestRun>
|
||||
get() = KotlinNativeBinaryTestRun::class.java
|
||||
abstract val testTaskClass: Class<TaskType>
|
||||
|
||||
override fun createTestRun(name: String, target: KotlinNativeTargetWithTests): KotlinNativeBinaryTestRun =
|
||||
DefaultKotlinNativeTestRun(name, target).apply {
|
||||
abstract fun isTestTaskEnabled(target: KotlinNativeTargetWithTests<*>): Boolean
|
||||
|
||||
protected open fun configureTestTask(target: KotlinNativeTargetWithTests<*>, testTask: TaskType) {
|
||||
testTask.group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
testTask.description = "Executes Kotlin/Native unit tests for target ${target.name}."
|
||||
testTask.targetName = target.name
|
||||
|
||||
testTask.enabled = isTestTaskEnabled(target)
|
||||
|
||||
testTask.workingDir = target.project.projectDir.absolutePath
|
||||
|
||||
testTask.configureConventions()
|
||||
}
|
||||
|
||||
protected open fun configureTestRun(target: KotlinNativeTargetWithTests<*>, testRun: AbstractKotlinNativeTestRun<TaskType>) {
|
||||
with(testRun) {
|
||||
val project = target.project
|
||||
|
||||
val testTaskOrProvider = project.registerTask<KotlinNativeTest>(testTaskName) { testTask ->
|
||||
testTask.group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||
testTask.description = "Executes Kotlin/Native unit tests for target ${target.name}."
|
||||
testTask.targetName = target.name
|
||||
|
||||
testTask.enabled = target.konanTarget.isCurrentHost
|
||||
|
||||
testTask.workingDir = project.projectDir.absolutePath
|
||||
|
||||
testTask.configureConventions()
|
||||
val testTaskOrProvider = project.registerTask(testTaskName, testTaskClass) { testTask ->
|
||||
configureTestTask(target, testTask)
|
||||
}
|
||||
|
||||
executionTask = testTaskOrProvider
|
||||
@@ -417,4 +429,54 @@ class KotlinNativeTargetWithTestsConfigurator(kotlinPluginVersion: String) :
|
||||
|
||||
project.kotlinTestRegistry.registerTestTask(testTaskOrProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinNativeTargetWithHostTestsConfigurator(kotlinPluginVersion: String) :
|
||||
KotlinNativeTargetWithTestsConfigurator<KotlinNativeHostTest, KotlinNativeHostTestRun>(kotlinPluginVersion) {
|
||||
|
||||
override val testTaskClass: Class<KotlinNativeHostTest>
|
||||
get() = KotlinNativeHostTest::class.java
|
||||
|
||||
override val testRunClass: Class<KotlinNativeHostTestRun>
|
||||
get() = KotlinNativeHostTestRun::class.java
|
||||
|
||||
override fun isTestTaskEnabled(target: KotlinNativeTargetWithTests<*>): Boolean =
|
||||
target.konanTarget.isCurrentHost
|
||||
|
||||
override fun createTestRun(
|
||||
name: String,
|
||||
target: KotlinNativeTargetWithTests<KotlinNativeHostTestRun>
|
||||
): KotlinNativeHostTestRun =
|
||||
DefaultHostTestRun(name, target).apply { configureTestRun(target, this) }
|
||||
}
|
||||
|
||||
class KotlinNativeTargetWithSimulatorTestsConfigurator(kotlinPluginVersion: String) :
|
||||
KotlinNativeTargetWithTestsConfigurator<KotlinNativeSimulatorTest, KotlinNativeSimulatorTestRun>(kotlinPluginVersion) {
|
||||
|
||||
override val testTaskClass: Class<KotlinNativeSimulatorTest>
|
||||
get() = KotlinNativeSimulatorTest::class.java
|
||||
|
||||
override val testRunClass: Class<KotlinNativeSimulatorTestRun>
|
||||
get() = KotlinNativeSimulatorTestRun::class.java
|
||||
|
||||
override fun isTestTaskEnabled(target: KotlinNativeTargetWithTests<*>): Boolean =
|
||||
HostManager.hostIsMac
|
||||
|
||||
override fun configureTestTask(target: KotlinNativeTargetWithTests<*>, testTask: KotlinNativeSimulatorTest) {
|
||||
super.configureTestTask(target, testTask)
|
||||
|
||||
testTask.deviceId = when (target.konanTarget) {
|
||||
KonanTarget.IOS_X64 -> "iPhone 8"
|
||||
KonanTarget.WATCHOS_X86 -> "Apple Watch Series 5 - 44mm"
|
||||
KonanTarget.TVOS_X64 -> "Apple TV"
|
||||
else -> error("Simulator tests are not supported for platform ${target.konanTarget.name}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun createTestRun(
|
||||
name: String,
|
||||
target: KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>
|
||||
): KotlinNativeSimulatorTestRun =
|
||||
DefaultSimulatorTestRun(name, target).apply { configureTestRun(target, this) }
|
||||
}
|
||||
|
||||
+22
-7
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||
import org.jetbrains.kotlin.gradle.targets.native.DisabledNativeTargetsReporter
|
||||
import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeHostTestRun
|
||||
import org.jetbrains.kotlin.gradle.targets.native.KotlinNativeSimulatorTestRun
|
||||
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
@@ -181,15 +183,28 @@ open class KotlinNativeTargetPreset(name: String, project: Project, konanTarget:
|
||||
}
|
||||
}
|
||||
|
||||
open class KotlinNativeTargetWithTestsPreset(name: String, project: Project, konanTarget: KonanTarget, kotlinPluginVersion: String) :
|
||||
AbstractKotlinNativeTargetPreset<KotlinNativeTargetWithTests>(name, project, konanTarget, kotlinPluginVersion) {
|
||||
open class KotlinNativeTargetWithHostTestsPreset(name: String, project: Project, konanTarget: KonanTarget, kotlinPluginVersion: String) :
|
||||
AbstractKotlinNativeTargetPreset<KotlinNativeTargetWithTests<KotlinNativeHostTestRun>>(name, project, konanTarget, kotlinPluginVersion) {
|
||||
|
||||
override fun createTargetConfigurator(): KotlinTargetConfigurator<KotlinNativeTargetWithTests> =
|
||||
KotlinNativeTargetWithTestsConfigurator(kotlinPluginVersion)
|
||||
override fun createTargetConfigurator(): KotlinTargetConfigurator<KotlinNativeTargetWithTests<KotlinNativeHostTestRun>> =
|
||||
KotlinNativeTargetWithHostTestsConfigurator(kotlinPluginVersion)
|
||||
|
||||
override fun instantiateTarget(name: String): KotlinNativeTargetWithTests {
|
||||
return project.objects.newInstance(KotlinNativeTargetWithTests::class.java, project, konanTarget)
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun instantiateTarget(name: String): KotlinNativeTargetWithTests<KotlinNativeHostTestRun> =
|
||||
project.objects.newInstance(KotlinNativeTargetWithTests::class.java, project, konanTarget)
|
||||
as KotlinNativeTargetWithTests<KotlinNativeHostTestRun>
|
||||
}
|
||||
|
||||
open class KotlinNativeTargetWithSimulatorTestsPreset(name: String, project: Project, konanTarget: KonanTarget, kotlinPluginVersion: String) :
|
||||
AbstractKotlinNativeTargetPreset<KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>>(name, project, konanTarget, kotlinPluginVersion) {
|
||||
|
||||
override fun createTargetConfigurator(): KotlinTargetConfigurator<KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>> =
|
||||
KotlinNativeTargetWithSimulatorTestsConfigurator(kotlinPluginVersion)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun instantiateTarget(name: String): KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun> =
|
||||
project.objects.newInstance(KotlinNativeTargetWithTests::class.java, project, konanTarget)
|
||||
as KotlinNativeTargetWithTests<KotlinNativeSimulatorTestRun>
|
||||
}
|
||||
|
||||
internal val KonanTarget.isCurrentHost: Boolean
|
||||
|
||||
+70
-17
@@ -11,6 +11,7 @@ import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.options.Option
|
||||
import org.gradle.process.ProcessForkOptions
|
||||
import org.gradle.process.internal.DefaultProcessForkOptions
|
||||
import org.jetbrains.kotlin.compilerRunner.konanVersion
|
||||
@@ -22,7 +23,7 @@ import org.jetbrains.kotlin.konan.CompilerVersion
|
||||
import java.io.File
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
open class KotlinNativeTest : KotlinTest() {
|
||||
abstract class KotlinNativeTest : KotlinTest() {
|
||||
@Suppress("LeakingThis")
|
||||
private val processOptions: ProcessForkOptions = DefaultProcessForkOptions(fileResolver)
|
||||
|
||||
@@ -97,6 +98,9 @@ open class KotlinNativeTest : KotlinTest() {
|
||||
processOptions.environment(name, value)
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
protected abstract val testCommand: TestCommand
|
||||
|
||||
// KonanVersion doesn't provide an API to compare versions,
|
||||
// so we have to transform it to KotlinVersion first.
|
||||
// Note: this check doesn't take into account the meta version (release, eap, dev).
|
||||
@@ -106,7 +110,7 @@ open class KotlinNativeTest : KotlinTest() {
|
||||
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
|
||||
val extendedForkOptions = DefaultProcessForkOptions(fileResolver)
|
||||
processOptions.copyTo(extendedForkOptions)
|
||||
extendedForkOptions.executable = executable.absolutePath
|
||||
extendedForkOptions.executable = testCommand.executable
|
||||
|
||||
val clientSettings = TCServiceMessagesClientSettings(
|
||||
name,
|
||||
@@ -122,24 +126,28 @@ open class KotlinNativeTest : KotlinTest() {
|
||||
// Thus we check the exit code only for newer versions.
|
||||
val checkExitCode = project.konanVersion.isAtLeast(1, 3, 0)
|
||||
|
||||
val cliArgs = CliArgs("TEAMCITY", checkExitCode, includePatterns, excludePatterns, args)
|
||||
val cliArgs = testCommand.cliArgs("TEAMCITY", checkExitCode, includePatterns, excludePatterns, args)
|
||||
|
||||
return TCServiceMessagesTestExecutionSpec(
|
||||
extendedForkOptions,
|
||||
cliArgs.toList(),
|
||||
checkExitCode,
|
||||
clientSettings
|
||||
)
|
||||
return TCServiceMessagesTestExecutionSpec(extendedForkOptions, cliArgs, checkExitCode, clientSettings)
|
||||
}
|
||||
|
||||
private class CliArgs(
|
||||
val testLogger: String? = null,
|
||||
val checkExitCode: Boolean = true,
|
||||
val testGradleFilter: Set<String> = setOf(),
|
||||
val testNegativeGradleFilter: Set<String> = setOf(),
|
||||
val userArgs: List<String> = emptyList()
|
||||
) {
|
||||
fun toList() = mutableListOf<String>().also {
|
||||
protected abstract class TestCommand() {
|
||||
abstract val executable: String
|
||||
abstract fun cliArgs(
|
||||
testLogger: String?,
|
||||
checkExitCode: Boolean,
|
||||
testGradleFilter: Set<String>,
|
||||
testNegativeGradleFilter: Set<String>,
|
||||
userArgs: List<String>
|
||||
): List<String>
|
||||
|
||||
protected fun testArgs(
|
||||
testLogger: String?,
|
||||
checkExitCode: Boolean,
|
||||
testGradleFilter: Set<String>,
|
||||
testNegativeGradleFilter: Set<String>,
|
||||
userArgs: List<String>
|
||||
): List<String> = mutableListOf<String>().also {
|
||||
|
||||
if (checkExitCode) {
|
||||
// Avoid returning a non-zero exit code in case of failed tests.
|
||||
@@ -162,3 +170,48 @@ open class KotlinNativeTest : KotlinTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A task running Kotlin/Native tests on a host machine.
|
||||
*/
|
||||
open class KotlinNativeHostTest : KotlinNativeTest() {
|
||||
@get:Internal
|
||||
override val testCommand: TestCommand = object : TestCommand() {
|
||||
override val executable: String
|
||||
get() = this@KotlinNativeHostTest.executable.absolutePath
|
||||
|
||||
override fun cliArgs(
|
||||
testLogger: String?,
|
||||
checkExitCode: Boolean,
|
||||
testGradleFilter: Set<String>,
|
||||
testNegativeGradleFilter: Set<String>,
|
||||
userArgs: List<String>
|
||||
): List<String> = testArgs(testLogger, checkExitCode, testGradleFilter, testNegativeGradleFilter, userArgs)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A task running Kotlin/Native tests on a simulator (iOS/watchOS/tvOS).
|
||||
*/
|
||||
// TODO: Support debugging.
|
||||
open class KotlinNativeSimulatorTest : KotlinNativeTest() {
|
||||
@Input
|
||||
@Option(option = "device", description = "Sets a simulated device used to execute tests.")
|
||||
lateinit var deviceId: String
|
||||
|
||||
@get:Internal
|
||||
override val testCommand: TestCommand = object : TestCommand() {
|
||||
override val executable: String
|
||||
get() = "/usr/bin/xcrun"
|
||||
|
||||
override fun cliArgs(
|
||||
testLogger: String?,
|
||||
checkExitCode: Boolean,
|
||||
testGradleFilter: Set<String>,
|
||||
testNegativeGradleFilter: Set<String>,
|
||||
userArgs: List<String>
|
||||
): List<String> =
|
||||
listOf("simctl", "spawn", "--standalone", deviceId, this@KotlinNativeSimulatorTest.executable.absolutePath, "--") +
|
||||
testArgs(testLogger, checkExitCode, testGradleFilter, testNegativeGradleFilter, userArgs)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user