diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt index d43d50c4b83..ad792764f41 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/native/NativeXcodeSimulatorTestsIT.kt @@ -7,11 +7,17 @@ package org.jetbrains.kotlin.gradle.native import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.util.runProcess +import org.jetbrains.kotlin.gradle.utils.Xcode +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.condition.EnabledOnOs import org.junit.jupiter.api.condition.OS +import java.io.File +import kotlin.test.assertEquals -@DisplayName("tests for the K/N simulator test infrastructure") +@DisplayName("tests for the K/N XCode simulator test infrastructure") @NativeGradlePluginTests @EnabledOnOs(OS.MAC) class NativeXcodeSimulatorTestsIT : KGPBaseTest() { @@ -25,4 +31,54 @@ class NativeXcodeSimulatorTestsIT : KGPBaseTest() { } } } + + @DisplayName("iOS simulator test with an https request doesn't with the standalone mode disabled") + @GradleTest + fun checkSimulatorTestFailsInNonStandaloneMode(gradleVersion: GradleVersion) { + project("native-test-ios-https-request", gradleVersion) { + val xcode = Xcode ?: error("XCode is expected to be defined") + val device = xcode.getDefaultTestDeviceId(KonanTarget.IOS_SIMULATOR_ARM64) ?: error("No simulator found for iOS ARM64") + bootXcodeSimulator(device) + buildGradleKts.append( + """ + tasks.withType { + device.set("$device") + standalone.set(false) + } + """.trimIndent() + ) + build("check") + } + } + + @AfterAll + fun shutDownSimulators() { + synchronized(bootedXcodeSimulators) { + for (device in bootedXcodeSimulators) { + val command = listOf("/usr/bin/xcrun", "simctl", "shutdown", device) + val processResult = runProcess(command, File(".")) + assertEquals(0, processResult.exitCode) + bootedXcodeSimulators.remove(device) + } + bootedXcodeSimulators.clear() + } + } + + private val bootedXcodeSimulators: MutableSet = HashSet() + + private fun bootXcodeSimulator(device: String) { + synchronized(bootedXcodeSimulators) { + if (device !in bootedXcodeSimulators) { + val command = listOf("/usr/bin/xcrun", "simctl", "boot", device) + val processResult = runProcess(command, File(".")) + assert(processResult.exitCode == 0 || "current state: Booted" in processResult.output) { + "Failed to boot a simulator $device and it wasn't started before, exit code = ${processResult.exitCode}" + } + if (processResult.exitCode == 0) { + // if the simulator was booted not by us, we should not shut it down + bootedXcodeSimulators.add(device) + } + } + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 00d0cc0cf9e..2ec9d514d05 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -574,6 +574,7 @@ class KotlinNativeTargetWithSimulatorTestsConfigurator : } testTask.device.convention(deviceIdProvider).finalizeValueOnRead() } + testTask.standalone.convention(true).finalizeValueOnRead() } override fun createTestRun( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTest.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTest.kt index 0e6be726741..5862a9f5b8d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/tasks/KotlinNativeTest.kt @@ -235,6 +235,9 @@ abstract class KotlinNativeSimulatorTest : KotlinNativeTest() { @Internal var debugMode = false + @get:Input + abstract val standalone: Property // disabled standalone means that xcode won't handle simulator boot/shutdown automatically + @get:Internal override val testCommand: TestCommand = object : TestCommand() { override val executable: String @@ -251,7 +254,7 @@ abstract class KotlinNativeSimulatorTest : KotlinNativeTest() { "simctl", "spawn", "--wait-for-debugger".takeIf { debugMode }, - "--standalone", + "--standalone".takeIf { standalone.get() }, device.get(), this@KotlinNativeSimulatorTest.executable.absolutePath, "--"