migrated AppleFrameworkIT to junit5 and gradle TestKit

#KT-51553 In Progress

Merge-request: KT-MR-9856
Merged-by: Dmitrii Krasnov <Dmitrii.Krasnov@jetbrains.com>
This commit is contained in:
Dmitrii Krasnov
2023-05-09 07:17:14 +00:00
committed by Space Team
parent b6030b3517
commit 375ff5ed2c
6 changed files with 483 additions and 281 deletions
@@ -18,6 +18,7 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD}) @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@GradleTestVersions @GradleTestVersions
@OsCondition
@AndroidTestVersions @AndroidTestVersions
@ParameterizedTest(name = "AGP {1} with {0}: {displayName}") @ParameterizedTest(name = "AGP {1} with {0}: {displayName}")
@ArgumentsSource(GradleAndAgpArgumentsProvider.class) @ArgumentsSource(GradleAndAgpArgumentsProvider.class)
@@ -18,6 +18,7 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD}) @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@GradleTestVersions @GradleTestVersions
@OsCondition
@JdkVersions @JdkVersions
@ParameterizedTest(name = "{1} with {0}: {displayName}") @ParameterizedTest(name = "{1} with {0}: {displayName}")
@ArgumentsSource(GradleAndJdkArgumentsProvider.class) @ArgumentsSource(GradleAndJdkArgumentsProvider.class)
@@ -1,234 +1,336 @@
/* /*
* Copyright 2010-2021 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. * 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 package org.jetbrains.kotlin.gradle.native
import org.gradle.api.logging.LogLevel import org.gradle.api.JavaVersion
import org.gradle.testkit.runner.BuildResult
import org.gradle.util.GradleVersion import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.testbase.TestVersions import org.junit.jupiter.api.DisplayName
import org.jetbrains.kotlin.gradle.util.AGPVersion import org.junit.jupiter.api.condition.OS
import org.jetbrains.kotlin.gradle.util.modify import kotlin.io.path.absolutePathString
import org.jetbrains.kotlin.konan.target.HostManager import kotlin.io.path.appendText
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.junit.Assume
import org.junit.BeforeClass
import kotlin.test.Test
class AppleFrameworkIT : BaseGradleIT() { @OsCondition(supportedOn = [OS.MAC], enabledOnCI = [OS.MAC])
companion object { @DisplayName("Tests for K/N with Apple Framework")
@BeforeClass @AndroidTestVersions(minVersion = TestVersions.AGP.AGP_70)
@JvmStatic @NativeGradlePluginTests
fun assumeItsMac() { class AppleFrameworkIT : KGPBaseTest() {
Assume.assumeTrue(HostManager.hostIsMac)
}
}
override val defaultGradleVersion = GradleVersionRequired.FOR_MPP_SUPPORT // TODO(Dmitrii Krasnov): remove it, when KT-58104 will be fixed
override fun defaultBuildOptions() = super.defaultBuildOptions().copy( override val defaultBuildOptions = super.defaultBuildOptions.copy(statisticsForceValidation = false)
androidHome = KtTestUtil.findAndroidSdk(),
androidGradlePluginVersion = AGPVersion.v7_4_0,
javaHome = KtTestUtil.getJdk17Home()
)
@Test @DisplayName("Assembling AppleFrameworkForXcode tasks for IosArm64")
fun `assemble AppleFrameworkForXcode tasks for IosArm64`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
val options: BuildOptions = defaultBuildOptions().copy( @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
customEnvironmentVariables = mapOf( fun shouldAssembleAppleFrameworkForXcodeForIosArm64(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
),
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug", "CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123", "SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64", "ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use", "TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use" "FRAMEWORKS_FOLDER_PATH" to "no use"
), )
) )
build("assembleDebugAppleFrameworkForXcodeIosArm64", options = options) {
assertSuccessful() build(
"assembleDebugAppleFrameworkForXcodeIosArm64",
environmentVariables = environmentVariables,
) {
assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeIosArm64") assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeIosArm64")
assertFileExists("/shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework") assertDirectoryInProjectExists("shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework")
assertFileExists("/shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework.dSYM") assertDirectoryInProjectExists("shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework.dSYM")
} }
build("assembleCustomDebugAppleFrameworkForXcodeIosArm64", options = options) { build(
assertSuccessful() "assembleCustomDebugAppleFrameworkForXcodeIosArm64",
environmentVariables = environmentVariables
) {
assertTasksExecuted(":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64") assertTasksExecuted(":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64")
assertFileExists("/shared/build/xcode-frameworks/debug/iphoneos123/lib.framework") assertDirectoryInProjectExists("shared/build/xcode-frameworks/debug/iphoneos123/lib.framework")
assertFileExists("/shared/build/xcode-frameworks/debug/iphoneos123/lib.framework.dSYM") assertDirectoryInProjectExists("shared/build/xcode-frameworks/debug/iphoneos123/lib.framework.dSYM")
} }
} }
} }
@Test @DisplayName("Assembling fat AppleFrameworkForXcode tasks for Arm64 and X64 simulators")
fun `assemble fat AppleFrameworkForXcode tasks for Arm64 and X64 simulators`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
val options: BuildOptions = defaultBuildOptions().copy( @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
customEnvironmentVariables = mapOf( fun shouldAssembleAppleFrameworkForXcodeForArm64AndX64Simulators(
"CONFIGURATION" to "Release", gradleVersion: GradleVersion,
"SDK_NAME" to "iphonesimulator", agpVersion: String,
"ARCHS" to "arm64 x86_64", jdkProvider: JdkVersions.ProvidedJdk
"TARGET_BUILD_DIR" to "no use", ) {
"FRAMEWORKS_FOLDER_PATH" to "no use"
), nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
) )
build("assembleReleaseAppleFrameworkForXcode", options = options) { ) {
assertSuccessful() val environmentVariables = mapOf(
"CONFIGURATION" to "Release",
"SDK_NAME" to "iphonesimulator",
"ARCHS" to "arm64 x86_64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
build("assembleReleaseAppleFrameworkForXcode", environmentVariables = EnvironmentalVariables(environmentVariables)) {
assertTasksExecuted(":shared:linkReleaseFrameworkIosSimulatorArm64") assertTasksExecuted(":shared:linkReleaseFrameworkIosSimulatorArm64")
assertTasksExecuted(":shared:linkReleaseFrameworkIosX64") assertTasksExecuted(":shared:linkReleaseFrameworkIosX64")
assertTasksExecuted(":shared:assembleReleaseAppleFrameworkForXcode") assertTasksExecuted(":shared:assembleReleaseAppleFrameworkForXcode")
assertFileExists("/shared/build/xcode-frameworks/Release/iphonesimulator/sdk.framework") assertDirectoryInProjectExists("shared/build/xcode-frameworks/Release/iphonesimulator/sdk.framework")
assertFileExists("/shared/build/xcode-frameworks/Release/iphonesimulator/sdk.framework.dSYM") assertDirectoryInProjectExists("shared/build/xcode-frameworks/Release/iphonesimulator/sdk.framework.dSYM")
} }
} }
} }
@Test @DisplayName("MacOS framework has symlinks")
fun `check that macOS framework has symlinks`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { // We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
val options: BuildOptions = defaultBuildOptions().copy( @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
customEnvironmentVariables = mapOf( @GradleAndroidTest
"CONFIGURATION" to "debug", fun shouldCheckThatMacOSFrameworkHasSymlinks(
"SDK_NAME" to "macosx", gradleVersion: GradleVersion,
"ARCHS" to "x86_64", agpVersion: String,
"EXPANDED_CODE_SIGN_IDENTITY" to "-", jdkProvider: JdkVersions.ProvidedJdk
"TARGET_BUILD_DIR" to workingDir.absolutePath, ) {
"FRAMEWORKS_FOLDER_PATH" to "${projectName}/build/xcode-derived"
) nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
) )
build(":shared:embedAndSignAppleFrameworkForXcode", options = options) { ) {
assertSuccessful() val environmentVariables = mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "macosx",
"ARCHS" to "x86_64",
"EXPANDED_CODE_SIGN_IDENTITY" to "-",
"TARGET_BUILD_DIR" to projectPath.absolutePathString(),
"FRAMEWORKS_FOLDER_PATH" to "build/xcode-derived"
)
build(":shared:embedAndSignAppleFrameworkForXcode", environmentVariables = EnvironmentalVariables(environmentVariables)) {
assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeMacosX64") assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeMacosX64")
// Verify symlinks in gradle build folder assertSymlinkInProjectExists("shared/build/xcode-frameworks/debug/macosx/sdk.framework/Headers")
assertFileExists("/shared/build/xcode-frameworks/debug/macosx/sdk.framework/Headers") assertSymlinkInProjectExists("build/xcode-derived/sdk.framework/Headers")
assertFileIsSymlink("/shared/build/xcode-frameworks/debug/macosx/sdk.framework/Headers")
// Verify symlinks in xcode derived folder
assertFileExists("/build/xcode-derived/sdk.framework/Headers")
assertFileIsSymlink("/build/xcode-derived/sdk.framework/Headers")
} }
} }
} }
@Test @DisplayName("embedAndSignAppleFrameworkForXcode fail")
fun `check embedAndSignAppleFrameworkForXcode fail`() { @GradleAndroidTest
with(Project("sharedAppleFramework")) { // We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
build(":shared:embedAndSignAppleFrameworkForXcode") { @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
assertTasksFailed(":shared:embedAndSignAppleFrameworkForXcode") fun shouldFailWithExecutingEmbedAndSignAppleFrameworkForXcode(
assertContains("Please run the embedAndSignAppleFrameworkForXcode task from Xcode") gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
nativeProject("sharedAppleFramework", gradleVersion, buildJdk = jdkProvider.location) {
buildAndFail(
":shared:embedAndSignAppleFrameworkForXcode",
buildOptions = defaultBuildOptions.copy(androidVersion = agpVersion)
) {
assertOutputContains("Please run the embedAndSignAppleFrameworkForXcode task from Xcode")
} }
} }
} }
@Test @DisplayName("Registered tasks with Xcode environment for Debug IosArm64 configuration")
fun `check all registered tasks with Xcode environment for Debug IosArm64 configuration`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
val currentGradleVersion = chooseWrapperVersionOrFinishTest() @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
val options: BuildOptions = defaultBuildOptions().copy( fun shouldCheckAllRegisteredTasksWithXcodeEnvironmentForDebugIosArm64(
customEnvironmentVariables = mapOf( gradleVersion: GradleVersion,
"CONFIGURATION" to "Debug", agpVersion: String,
"SDK_NAME" to "iphoneos", jdkProvider: JdkVersions.ProvidedJdk
"ARCHS" to "arm64", ) {
"EXPANDED_CODE_SIGN_IDENTITY" to "-", val buildOptions = defaultBuildOptions.copy(
"TARGET_BUILD_DIR" to "testBuildDir", androidVersion = agpVersion
"FRAMEWORKS_FOLDER_PATH" to "testFrameworksDir" )
) nativeProject(
).suppressDeprecationWarningsOn( "sharedAppleFramework",
"AGP uses deprecated IncrementalTaskInputs (Gradle 7.5)" gradleVersion,
) { options -> buildJdk = jdkProvider.location,
GradleVersion.version(currentGradleVersion) >= GradleVersion.version(TestVersions.Gradle.G_7_5) && options.safeAndroidGradlePluginVersion < AGPVersion.v7_3_0 buildOptions = buildOptions
} ) {
build("tasks", options = options) { val environmentVariables = mapOf(
assertSuccessful() "CONFIGURATION" to "Debug",
assertTasksRegistered( "SDK_NAME" to "iphoneos",
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", "ARCHS" to "arm64",
":shared:embedAndSignAppleFrameworkForXcode", "EXPANDED_CODE_SIGN_IDENTITY" to "-",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64", "TARGET_BUILD_DIR" to "testBuildDir",
":shared:embedAndSignCustomAppleFrameworkForXcode", "FRAMEWORKS_FOLDER_PATH" to "testFrameworksDir"
":shared:assembleDebugAppleFrameworkForXcodeIosX64", )
":shared:assembleReleaseAppleFrameworkForXcodeIosX64", buildAndAssertAllTasks(
":shared:assembleReleaseAppleFrameworkForXcodeIosArm64", registeredTasks = listOf(
":shared:assembleCustomDebugAppleFrameworkForXcodeIosX64", "shared:assembleDebugAppleFrameworkForXcodeIosArm64",
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosX64", "shared:embedAndSignAppleFrameworkForXcode",
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosArm64" "shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64",
) "shared:embedAndSignCustomAppleFrameworkForXcode",
} "shared:assembleDebugAppleFrameworkForXcodeIosX64",
"shared:assembleReleaseAppleFrameworkForXcodeIosX64",
"shared:assembleReleaseAppleFrameworkForXcodeIosArm64",
"shared:assembleCustomDebugAppleFrameworkForXcodeIosX64",
"shared:assembleCustomReleaseAppleFrameworkForXcodeIosX64",
"shared:assembleCustomReleaseAppleFrameworkForXcodeIosArm64"
),
environmentVariables = EnvironmentalVariables(environmentVariables)
)
} }
} }
@Test @DisplayName("embedAndSignAppleFrameworkForXcode was registered without required Xcode environments")
fun `check embedAndSignAppleFrameworkForXcode was registered without required Xcode environments`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
val currentGradleVersion = chooseWrapperVersionOrFinishTest() // We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
val options: BuildOptions = defaultBuildOptions().copy( @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
customEnvironmentVariables = mapOf( fun shouldCheckEmbedAndSignAppleFrameworkForXcodeDoesNotRequireXcodeEnv(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = buildOptions
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "Debug", "CONFIGURATION" to "Debug",
"SDK_NAME" to "iphoneos", "SDK_NAME" to "iphoneos",
"ARCHS" to "arm64" "ARCHS" to "arm64"
) )
) )
build("tasks", options = options.suppressDeprecationWarningsOn("AGP uses deprecated IncrementalTaskInputs (Gradle 7.5)") { buildAndAssertAllTasks(
GradleVersion.version(currentGradleVersion) >= GradleVersion.version(TestVersions.Gradle.G_7_5) && options.safeAndroidGradlePluginVersion < AGPVersion.v7_3_0 registeredTasks = listOf(
}) { "shared:embedAndSignAppleFrameworkForXcode",
assertSuccessful() "shared:embedAndSignCustomAppleFrameworkForXcode"
assertTasksRegistered( ),
":shared:embedAndSignAppleFrameworkForXcode", notRegisteredTasks = listOf(
":shared:embedAndSignCustomAppleFrameworkForXcode" "shared:assembleReleaseAppleFrameworkForXcodeIosX64",
) "shared:assembleDebugAppleFrameworkForXcodeIosX64",
assertTasksNotRegistered( "shared:assembleReleaseAppleFrameworkForXcodeIosArm64",
":shared:assembleReleaseAppleFrameworkForXcodeIosX64", "shared:assembleDebugAppleFrameworkForXcodeIosArm64",
":shared:assembleDebugAppleFrameworkForXcodeIosX64", "shared:assembleCustomDebugAppleFrameworkForXcodeIosX64",
":shared:assembleReleaseAppleFrameworkForXcodeIosArm64", "shared:assembleCustomReleaseAppleFrameworkForXcodeIosX64",
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", "shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64",
":shared:assembleCustomDebugAppleFrameworkForXcodeIosX64", "shared:assembleCustomReleaseAppleFrameworkForXcodeIosArm64"
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosX64", ),
":shared:assembleCustomDebugAppleFrameworkForXcodeIosArm64", environmentVariables = environmentVariables
":shared:assembleCustomReleaseAppleFrameworkForXcodeIosArm64" )
) buildAndFail(
} ":shared:embedAndSignCustomAppleFrameworkForXcode",
build(":shared:embedAndSignCustomAppleFrameworkForXcode", options = options) { environmentVariables = environmentVariables
) {
assertTasksFailed(":shared:embedAndSignCustomAppleFrameworkForXcode") assertTasksFailed(":shared:embedAndSignCustomAppleFrameworkForXcode")
assertContains("Please run the embedAndSignCustomAppleFrameworkForXcode task from Xcode") assertOutputContains("Please run the embedAndSignCustomAppleFrameworkForXcode task from Xcode")
} }
} }
} }
@Test @DisplayName("Static framework for Arm64 is built but is not embedded")
fun `check that static framework for Arm64 is built but is not embedded`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
val options: BuildOptions = defaultBuildOptions().copy( @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_0)
customEnvironmentVariables = mapOf( fun shouldCheckThatStaticFrameworkForArm64IsBuildAndNotEmbedded(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug", "CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123", "SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64", "ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use", "TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use" "FRAMEWORKS_FOLDER_PATH" to "no use"
), )
) )
setupWorkingDir()
projectDir.resolve("shared/build.gradle.kts").modify { subProject("shared").buildGradleKts.modify {
it.replace( it.replace(
"baseName = \"sdk\"", "baseName = \"sdk\"",
"baseName = \"sdk\"\nisStatic = true" "baseName = \"sdk\"\nisStatic = true"
) )
} }
build("embedAndSignAppleFrameworkForXcode", options = options) { build("embedAndSignAppleFrameworkForXcode", environmentVariables = environmentVariables) {
assertSuccessful()
assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeIosArm64") assertTasksExecuted(":shared:assembleDebugAppleFrameworkForXcodeIosArm64")
assertTasksNotExecuted(":shared:embedAndSignAppleFrameworkForXcode") assertTasksSkipped(":shared:embedAndSignAppleFrameworkForXcode")
assertFileExists("/shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework") assertDirectoryInProjectExists("shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework")
assertNoSuchFile("/shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework.dSYM") assertFileInProjectNotExists("shared/build/xcode-frameworks/debug/iphoneos123/sdk.framework.dSYM")
} }
} }
} }
@DisplayName("Configuration errors reported to Xcode when embedAndSign task requested")
@OptIn(EnvironmentalVariablesOverride::class)
// We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
@GradleAndroidTest
fun shouldReportConfErrorsToXcodeWhenRequestedByEmbedAndSign(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildJdk = jdkProvider.location,
buildOptions = buildOptions
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
@Test subProject("shared").buildGradleKts.appendText(
fun `configuration errors reported to Xcode when embedAndSign task requested`() {
with(Project("sharedAppleFramework")) {
setupWorkingDir()
projectDir.resolve("shared/build.gradle.kts").appendText(
""" """
kotlin { kotlin {
sourceSets["commonMain"].dependencies { sourceSets["commonMain"].dependencies {
@@ -238,174 +340,227 @@ class AppleFrameworkIT : BaseGradleIT() {
""".trimIndent() """.trimIndent()
) )
build( buildAndFail(":shared:embedAndSignAppleFrameworkForXcode", environmentVariables = environmentVariables) {
":shared:embedAndSignAppleFrameworkForXcode", assertOutputContains("error: Could not find com.example.unknown:dependency:0.0.1.")
options = defaultBuildOptions().copy(
customEnvironmentVariables = mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
) {
assertFailed()
assertContains("error: Could not find com.example.unknown:dependency:0.0.1.")
} }
} }
} }
@Test @DisplayName("Compilation errors reported to Xcode when embedAndSign task requested")
fun `compilation errors reported to Xcode when embedAndSign task requested`() { @OptIn(EnvironmentalVariablesOverride::class)
with(Project("sharedAppleFramework")) { @GradleAndroidTest
setupWorkingDir() // We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
projectDir.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt") @GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
fun shouldReportCompilationErrorsToXcodeWhenRequestedByEmbedAndSign(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildOptions = buildOptions,
buildJdk = jdkProvider.location
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
projectPath.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
.appendText("this can't be compiled") .appendText("this can't be compiled")
build( buildAndFail(":shared:embedAndSignAppleFrameworkForXcode", environmentVariables = environmentVariables) {
":shared:embedAndSignAppleFrameworkForXcode", assertOutputContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
options = defaultBuildOptions().copy( assertOutputContains("error: Compilation finished with errors")
customEnvironmentVariables = mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
) {
assertFailed()
assertContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
assertContains("error: Compilation finished with errors")
} }
} }
} }
@DisplayName("Compilation errors printed with Gradle-style when any other task requested")
@OptIn(EnvironmentalVariablesOverride::class)
@GradleAndroidTest
// We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
fun shouldPrintCompilationErrorsWithGradleStyle(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildOptions = buildOptions,
buildJdk = jdkProvider.location
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
@Test projectPath.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
fun `compilation errors printed with Gradle-style when any other task requested`() {
with(Project("sharedAppleFramework")) {
setupWorkingDir()
projectDir.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
.appendText("this can't be compiled") .appendText("this can't be compiled")
build( buildAndFail(":shared:assembleDebugAppleFrameworkForXcodeIosArm64", environmentVariables = environmentVariables) {
assertOutputContains("e: file:///")
assertOutputDoesNotContain("error: Compilation finished with errors")
}
}
}
@DisplayName("Compilation errors printed with Xcode-style with explicit option")
@OptIn(EnvironmentalVariablesOverride::class)
@GradleAndroidTest
// We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
fun shouldPrintCompilationErrorsWithXcodeStyle(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildOptions = buildOptions,
buildJdk = jdkProvider.location
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
projectPath.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
.appendText("this can't be compiled")
buildAndFail(
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", ":shared:assembleDebugAppleFrameworkForXcodeIosArm64",
options = defaultBuildOptions().copy( "-Pkotlin.native.useXcodeMessageStyle=true",
customEnvironmentVariables = mapOf( environmentVariables = environmentVariables
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
) { ) {
assertFailed() assertOutputContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
assertContains("e: file:///") assertOutputContains("error: Compilation finished with errors")
assertNotContains("error: Compilation finished with errors")
} }
} }
} }
@DisplayName("Compilation errors reported to Xcode when embedAndSign task requested and compiler runs in a separate process")
@OptIn(EnvironmentalVariablesOverride::class)
@GradleAndroidTest
// We need to use Gradle 7.2 here because of the issue https://github.com/gradle/gradle/issues/13957
@GradleTestVersions(minVersion = TestVersions.Gradle.G_7_2)
fun shouldReportErrorsToXcodeWhenEmbedAndSignRequestedAndDisableCompilerDaemon(
gradleVersion: GradleVersion,
agpVersion: String,
jdkProvider: JdkVersions.ProvidedJdk
) {
val buildOptions = defaultBuildOptions.copy(
androidVersion = agpVersion
)
nativeProject(
"sharedAppleFramework",
gradleVersion,
buildOptions = buildOptions,
buildJdk = jdkProvider.location
) {
val environmentVariables = EnvironmentalVariables(
mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
@Test projectPath.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
fun `compilation errors printed with Xcode-style with explicit option`() {
with(Project("sharedAppleFramework")) {
setupWorkingDir()
projectDir.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
.appendText("this can't be compiled") .appendText("this can't be compiled")
build( buildAndFail(
":shared:assembleDebugAppleFrameworkForXcodeIosArm64", "-Pkotlin.native.useXcodeMessageStyle=true", ":shared:embedAndSignAppleFrameworkForXcode",
options = defaultBuildOptions().copy( "-Pkotlin.native.disableCompilerDaemon=true",
customEnvironmentVariables = mapOf( environmentVariables = environmentVariables
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
) { ) {
assertFailed() assertOutputContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
assertContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
assertContains("error: Compilation finished with errors")
} }
} }
} }
@Test @DisplayName("Frameworks can be consumed from other gradle project")
fun `compilation errors reported to Xcode when embedAndSign task requested and compiler runs in a separate process`() { @GradleTest
with(Project("sharedAppleFramework")) { fun shouldCheckFrameworksCanBeConsumedFromOtherGradleProjects(gradleVersion: GradleVersion) {
setupWorkingDir() nativeProject("consumableAppleFrameworks", gradleVersion) {
projectDir.resolve("shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt")
.appendText("this can't be compiled")
build(
":shared:embedAndSignAppleFrameworkForXcode", "-Pkotlin.native.disableCompilerDaemon=true",
options = defaultBuildOptions().copy(
customEnvironmentVariables = mapOf(
"CONFIGURATION" to "debug",
"SDK_NAME" to "iphoneos123",
"ARCHS" to "arm64",
"TARGET_BUILD_DIR" to "no use",
"FRAMEWORKS_FOLDER_PATH" to "no use"
)
)
) {
assertFailed()
assertContains("/sharedAppleFramework/shared/src/commonMain/kotlin/com/github/jetbrains/myapplication/Greeting.kt:7:2: error: Expecting a top level declaration")
}
}
}
@Test
fun `frameworks can be consumed from other gradle project`() {
with(Project("consumableAppleFrameworks", minLogLevel = LogLevel.INFO)) {
setupWorkingDir()
build(":consumer:help") { build(":consumer:help") {
assertContains("RESOLUTION_SUCCESS") assertOutputContains("RESOLUTION_SUCCESS")
assertNotContains("RESOLUTION_FAILURE") assertOutputDoesNotContain("RESOLUTION_FAILURE")
} }
} }
} }
@Test @DisplayName("Smoke test with apple gradle plugin")
fun `smoke test with apple gradle plugin`() { @GradleWithJdkTest
with(Project("appleGradlePluginConsumesAppleFrameworks", minLogLevel = LogLevel.INFO)) { @JdkVersions(versions = [JavaVersion.VERSION_11])
setupWorkingDir() fun smokeTestWithAppleGradlePlugin(
gradleVersion: GradleVersion,
providedJdk: JdkVersions.ProvidedJdk
) {
nativeProject(
"appleGradlePluginConsumesAppleFrameworks",
gradleVersion,
buildJdk = providedJdk.location
) {
fun dependencyInsight(configuration: String) = arrayOf( fun dependencyInsight(configuration: String) = arrayOf(
":iosApp:dependencyInsight", "--configuration", configuration, "--dependency", "iosLib" ":iosApp:dependencyInsight", "--configuration", configuration, "--dependency", "iosLib"
) )
fun CompiledProject.assertContainsVariant(variantName: String) { fun BuildResult.assertContainsVariant(variantName: String) {
assertContains("Variant $variantName") assertOutputContains(
if (gradleVersion >= GradleVersion.version(TestVersions.Gradle.G_7_5))
"Variant $variantName"
else "variant \"$variantName\""
)
} }
build(*dependencyInsight("iosAppIosX64DebugImplementation")) { build(*dependencyInsight("iosAppIosX64DebugImplementation")) {
assertSuccessful()
assertContainsVariant("mainDynamicDebugFrameworkIos") assertContainsVariant("mainDynamicDebugFrameworkIos")
} }
build(*dependencyInsight("iosAppIosX64ReleaseImplementation")) { build(*dependencyInsight("iosAppIosX64ReleaseImplementation")) {
assertSuccessful()
assertContainsVariant("mainDynamicReleaseFrameworkIos") assertContainsVariant("mainDynamicReleaseFrameworkIos")
} }
// NB: '0' is required at the end since dependency is added with custom attribute and it creates new configuration // NB: '0' is required at the end since dependency is added with custom attribute and it creates new configuration
build(*dependencyInsight("iosAppIosX64DebugImplementation0"), "-PmultipleFrameworks") { build(*dependencyInsight("iosAppIosX64DebugImplementation0"), "-PmultipleFrameworks") {
assertSuccessful()
assertContainsVariant("mainStaticDebugFrameworkIos") assertContainsVariant("mainStaticDebugFrameworkIos")
} }
build(*dependencyInsight("iosAppIosX64ReleaseImplementation0"), "-PmultipleFrameworks") { build(*dependencyInsight("iosAppIosX64ReleaseImplementation0"), "-PmultipleFrameworks") {
assertSuccessful()
assertContainsVariant("mainStaticReleaseFrameworkIos") assertContainsVariant("mainStaticReleaseFrameworkIos")
} }
} }
} }
} }
@@ -97,6 +97,30 @@ fun GradleProject.assertFileNotExistsInTree(
assertFileNotExistsInTree(projectPath.resolve(pathToTreeRoot), fileName) assertFileNotExistsInTree(projectPath.resolve(pathToTreeRoot), fileName)
} }
/**
* Asserts symlink under [path] exists and is a symlink
*/
fun assertSymlinkExists(
path: Path
) {
assert(Files.exists(path)) {
"Symlink '${path}' does not exist!"
}
assert(Files.isSymbolicLink(path)) {
"'${path}' is not a symlink!"
}
}
/**
* Asserts symlink under [pathToFile] relative to the test project exists and is a symlink.
*/
fun TestProject.assertSymlinkInProjectExists(
pathToFile: String
) {
assertSymlinkExists(projectPath.resolve(pathToFile))
}
/** /**
* Asserts directory under [pathToDir] relative to the test project exists and is a directory. * Asserts directory under [pathToDir] relative to the test project exists and is a directory.
*/ */
@@ -105,9 +129,9 @@ fun GradleProject.assertDirectoryInProjectExists(
) = assertDirectoryExists(projectPath.resolve(pathToDir)) ) = assertDirectoryExists(projectPath.resolve(pathToDir))
/** /**
* Asserts directory under [file] exists and is a directory. * Asserts directory under [dirPath] exists and is a directory.
*/ */
fun GradleProject.assertDirectoryExists( fun assertDirectoryExists(
dirPath: Path dirPath: Path
) = assertDirectoriesExist(dirPath) ) = assertDirectoriesExist(dirPath)
@@ -132,7 +156,7 @@ fun assertDirectoriesExist(
} }
/** /**
* Asserts file under [pathToFile] relative to the test project exists and contains all the lines from [expectedLines] * Asserts file under [pathToFile] relative to the test project exists and contains all the lines from [expectedText]
*/ */
fun GradleProject.assertFileInProjectContains( fun GradleProject.assertFileInProjectContains(
pathToFile: String, pathToFile: String,
@@ -160,14 +160,17 @@ fun BuildResult.assertNativeTasksClasspath(
* it could contain task paths as well, but without the first semicolon. * it could contain task paths as well, but without the first semicolon.
* @param notRegisteredTasks An optional list of task names that should not have been registered, * @param notRegisteredTasks An optional list of task names that should not have been registered,
* it could contain task paths as well, but without the first semicolon. * it could contain task paths as well, but without the first semicolon.
* @param environmentVariables environmental variables for build process
* @throws AssertionError if any of the registered tasks do not match the expected task names, * @throws AssertionError if any of the registered tasks do not match the expected task names,
* or if any of the not-registered tasks were actually registered. * or if any of the not-registered tasks were actually registered.
*/ */
@OptIn(EnvironmentalVariablesOverride::class)
fun TestProject.buildAndAssertAllTasks( fun TestProject.buildAndAssertAllTasks(
registeredTasks: List<String> = emptyList(), registeredTasks: List<String> = emptyList(),
notRegisteredTasks: List<String> = emptyList() notRegisteredTasks: List<String> = emptyList(),
environmentVariables: EnvironmentalVariables = EnvironmentalVariables()
) { ) {
build("tasks", "--all") { build("tasks", "--all", environmentVariables = environmentVariables) {
assertTasksInBuildOutput(registeredTasks, notRegisteredTasks) assertTasksInBuildOutput(registeredTasks, notRegisteredTasks)
} }
} }
@@ -33,6 +33,7 @@ import kotlin.test.assertTrue
* @param [buildOptions] common Gradle build options * @param [buildOptions] common Gradle build options
* @param [buildJdk] path to JDK build should run with. *Note* Only append to 'gradle.properties'! * @param [buildJdk] path to JDK build should run with. *Note* Only append to 'gradle.properties'!
*/ */
@OptIn(EnvironmentalVariablesOverride::class)
fun KGPBaseTest.project( fun KGPBaseTest.project(
projectName: String, projectName: String,
gradleVersion: GradleVersion, gradleVersion: GradleVersion,
@@ -44,7 +45,8 @@ fun KGPBaseTest.project(
projectPathAdditionalSuffix: String = "", projectPathAdditionalSuffix: String = "",
buildJdk: File? = null, buildJdk: File? = null,
localRepoDir: Path? = null, localRepoDir: Path? = null,
test: TestProject.() -> Unit = {}, environmentVariables: EnvironmentalVariables = EnvironmentalVariables(),
test: TestProject.() -> Unit = {}
): TestProject { ): TestProject {
val projectPath = setupProjectFromTestResources( val projectPath = setupProjectFromTestResources(
projectName, projectName,
@@ -56,7 +58,6 @@ fun KGPBaseTest.project(
projectPath.enableCacheRedirector() projectPath.enableCacheRedirector()
projectPath.enableAndroidSdk() projectPath.enableAndroidSdk()
val gradleRunner = GradleRunner val gradleRunner = GradleRunner
.create() .create()
.withProjectDir(projectPath.toFile()) .withProjectDir(projectPath.toFile())
@@ -72,6 +73,7 @@ fun KGPBaseTest.project(
forceOutput = forceOutput, forceOutput = forceOutput,
enableBuildScan = enableBuildScan, enableBuildScan = enableBuildScan,
enableGradleDebug = enableGradleDebug, enableGradleDebug = enableGradleDebug,
environmentVariables = environmentVariables
) )
addHeapDumpOptions.ifTrue { testProject.addHeapDumpOptions() } addHeapDumpOptions.ifTrue { testProject.addHeapDumpOptions() }
localRepoDir?.let { testProject.configureLocalRepository(localRepoDir) } localRepoDir?.let { testProject.configureLocalRepository(localRepoDir) }
@@ -93,6 +95,7 @@ fun KGPBaseTest.project(
* @param [buildOptions] common Gradle build options * @param [buildOptions] common Gradle build options
* @param [buildJdk] path to JDK build should run with. *Note* Only append to 'gradle.properties'! * @param [buildJdk] path to JDK build should run with. *Note* Only append to 'gradle.properties'!
*/ */
@OptIn(EnvironmentalVariablesOverride::class)
fun KGPBaseTest.nativeProject( fun KGPBaseTest.nativeProject(
projectName: String, projectName: String,
gradleVersion: GradleVersion, gradleVersion: GradleVersion,
@@ -104,7 +107,8 @@ fun KGPBaseTest.nativeProject(
projectPathAdditionalSuffix: String = "", projectPathAdditionalSuffix: String = "",
buildJdk: File? = null, buildJdk: File? = null,
localRepoDir: Path? = null, localRepoDir: Path? = null,
test: TestProject.() -> Unit = {}, environmentVariables: EnvironmentalVariables = EnvironmentalVariables(),
test: TestProject.() -> Unit = {}
): TestProject { ): TestProject {
val project = project( val project = project(
projectName = projectName, projectName = projectName,
@@ -117,6 +121,7 @@ fun KGPBaseTest.nativeProject(
projectPathAdditionalSuffix = projectPathAdditionalSuffix, projectPathAdditionalSuffix = projectPathAdditionalSuffix,
buildJdk = buildJdk, buildJdk = buildJdk,
localRepoDir = localRepoDir, localRepoDir = localRepoDir,
environmentVariables = environmentVariables,
) )
project.configureSingleNativeTarget() project.configureSingleNativeTarget()
project.test() project.test()
@@ -126,6 +131,7 @@ fun KGPBaseTest.nativeProject(
/** /**
* Trigger test project build with given [buildArguments] and assert build is successful. * Trigger test project build with given [buildArguments] and assert build is successful.
*/ */
@OptIn(EnvironmentalVariablesOverride::class)
fun TestProject.build( fun TestProject.build(
vararg buildArguments: String, vararg buildArguments: String,
forceOutput: Boolean = this.forceOutput, forceOutput: Boolean = this.forceOutput,
@@ -134,7 +140,8 @@ fun TestProject.build(
enableBuildCacheDebug: Boolean = false, enableBuildCacheDebug: Boolean = false,
enableBuildScan: Boolean = this.enableBuildScan, enableBuildScan: Boolean = this.enableBuildScan,
buildOptions: BuildOptions = this.buildOptions, buildOptions: BuildOptions = this.buildOptions,
assertions: BuildResult.() -> Unit = {}, environmentVariables: EnvironmentalVariables = this.environmentVariables,
assertions: BuildResult.() -> Unit = {}
) { ) {
if (enableBuildScan) agreeToBuildScanService() if (enableBuildScan) agreeToBuildScanService()
@@ -148,6 +155,7 @@ fun TestProject.build(
) )
val gradleRunnerForBuild = gradleRunner val gradleRunnerForBuild = gradleRunner
.also { if (forceOutput) it.forwardOutput() } .also { if (forceOutput) it.forwardOutput() }
.also { if (environmentVariables.environmentalVariables.isNotEmpty()) it.withEnvironment(System.getenv() + environmentVariables.environmentalVariables) }
.withDebug(enableGradleDebug) .withDebug(enableGradleDebug)
.withArguments(allBuildArguments) .withArguments(allBuildArguments)
withBuildSummary(allBuildArguments) { withBuildSummary(allBuildArguments) {
@@ -169,7 +177,8 @@ fun TestProject.buildAndFail(
enableBuildCacheDebug: Boolean = false, enableBuildCacheDebug: Boolean = false,
enableBuildScan: Boolean = this.enableBuildScan, enableBuildScan: Boolean = this.enableBuildScan,
buildOptions: BuildOptions = this.buildOptions, buildOptions: BuildOptions = this.buildOptions,
assertions: BuildResult.() -> Unit = {}, environmentVariables: EnvironmentalVariables = this.environmentVariables,
assertions: BuildResult.() -> Unit = {}
) { ) {
if (enableBuildScan) agreeToBuildScanService() if (enableBuildScan) agreeToBuildScanService()
@@ -183,6 +192,7 @@ fun TestProject.buildAndFail(
) )
val gradleRunnerForBuild = gradleRunner val gradleRunnerForBuild = gradleRunner
.also { if (forceOutput) it.forwardOutput() } .also { if (forceOutput) it.forwardOutput() }
.also { if (environmentVariables.environmentalVariables.isNotEmpty()) it.withEnvironment(System.getenv() + environmentVariables.environmentalVariables) }
.withDebug(enableGradleDebug) .withDebug(enableGradleDebug)
.withArguments(allBuildArguments) .withArguments(allBuildArguments)
withBuildSummary(allBuildArguments) { withBuildSummary(allBuildArguments) {
@@ -295,6 +305,13 @@ open class GradleProject(
): List<Path> = files.map { projectPath.relativize(it) } ): List<Path> = files.map { projectPath.relativize(it) }
} }
@JvmInline
value class EnvironmentalVariables @EnvironmentalVariablesOverride constructor(val environmentalVariables: Map<String, String> = emptyMap())
@RequiresOptIn("Environmental variables override may lead to interference of parallel builds and breaks Gradle tests debugging")
annotation class EnvironmentalVariablesOverride
@OptIn(EnvironmentalVariablesOverride::class)
class TestProject( class TestProject(
val gradleRunner: GradleRunner, val gradleRunner: GradleRunner,
projectName: String, projectName: String,
@@ -313,6 +330,7 @@ class TestProject(
* Note that we'll need to let the debugger start listening at this port first *before* the Kotlin daemon is launched. * Note that we'll need to let the debugger start listening at this port first *before* the Kotlin daemon is launched.
*/ */
val kotlinDaemonDebugPort: Int? = null, val kotlinDaemonDebugPort: Int? = null,
val environmentVariables: EnvironmentalVariables = EnvironmentalVariables(),
) : GradleProject(projectName, projectPath) { ) : GradleProject(projectName, projectPath) {
fun subProject(name: String) = GradleProject(name, projectPath.resolve(name)) fun subProject(name: String) = GradleProject(name, projectPath.resolve(name))