From 1c1b6ff92a881d6d6ca96d59cccdc8d15c9688f1 Mon Sep 17 00:00:00 2001 From: Sebastian Sellmair Date: Wed, 1 Feb 2023 11:23:35 +0100 Subject: [PATCH] [Gradle] Implement MppIdeDependencyResolutionIT for platform cinterops and failing cinterops ^KT-56337 Verification Pending --- .../gradle/MppIdeDependencyResolutionIT.kt | 61 +++++++++++++++++++ .../kotlin/gradle/mpp/MppCompositeBuildIT.kt | 4 +- .../util/IdeaKotlinDependencyMatchers.kt | 2 +- .../build.gradle.kts | 27 ++++++++ .../libs/include/dummy.h | 1 + .../libs/include/failing.h | 1 + .../commonMain/kotlin/com.lib/CommonMain.kt | 12 ++++ .../src/nativeInterop/cinterop/dummy.def | 0 .../src/nativeInterop/cinterop/failing.def | 0 9 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/dummy.h create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/failing.h create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/commonMain/kotlin/com.lib/CommonMain.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/dummy.def create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/failing.def diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt index 5ea7a744ade..0178e053805 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/MppIdeDependencyResolutionIT.kt @@ -11,13 +11,19 @@ import org.jetbrains.kotlin.commonizer.identityString import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinBinaryDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinDependency import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinResolvedBinaryDependency +import org.jetbrains.kotlin.gradle.idea.tcs.IdeaKotlinUnresolvedBinaryDependency import org.jetbrains.kotlin.gradle.idea.tcs.extras.* +import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.IdeaKotlinDependencyMatcher import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.assertMatches import org.jetbrains.kotlin.gradle.idea.testFixtures.tcs.binaryCoordinates import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.gradle.util.kotlinNativeDistributionDependencies import org.jetbrains.kotlin.gradle.util.resolveIdeDependencies import org.jetbrains.kotlin.konan.target.KonanTarget.* import org.junit.jupiter.api.DisplayName +import java.nio.ByteBuffer +import java.util.* +import java.util.zip.CRC32 import kotlin.test.assertEquals import kotlin.test.fail @@ -184,4 +190,59 @@ class MppIdeDependencyResolutionIT : KGPBaseTest() { } } } + + @GradleTest + fun `test cinterops - are stored in root gradle folder`(gradleVersion: GradleVersion) { + project(projectName = "cinteropImport", gradleVersion = gradleVersion) { + resolveIdeDependencies("dep-with-cinterop") { dependencies -> + + /* Check behaviour of platform cinterops on linuxX64Main */ + val cinterops = dependencies["linuxX64Main"].filterIsInstance() + .filter { !it.isNativeDistribution && it.klibExtra?.isInterop == true } + .ifEmpty { fail("Expected at least one cinterop on linuxX64Main") } + + cinterops.forEach { cinterop -> + if (cinterop.classpath.isEmpty()) fail("Missing classpath for $cinterop") + cinterop.classpath.forEach { cinteropFile -> + /* Check file was copied into root .gradle folder */ + val expectedParent = projectPath.toFile().resolve(".gradle/kotlin/kotlinCInteropLibraries").canonicalFile + assertEquals(expectedParent, cinteropFile.parentFile.canonicalFile) + + /* Check crc in file name */ + val crc = CRC32() + crc.update(cinteropFile.readBytes()) + val crcValue = crc.value.toInt() + val crcString = Base64.getEncoder().withoutPadding().encodeToString( + ByteBuffer.allocate(4).putInt(crcValue).array() + ) + + if (!cinteropFile.name.endsWith("-$crcString.klib")) { + fail("Expected crc $crcString to be part of cinterop file name. Found ${cinteropFile.name}") + } + } + } + } + } + } + + @GradleTest + fun `test cinterops - with failing cinterop process`(gradleVersion: GradleVersion) { + project( + projectName = "cinterop-withFailingCInteropProcess", gradleVersion = gradleVersion, + /* Adding idea.sync.active to ensure lenient cinterop generation */ + buildOptions = defaultBuildOptions.copy(freeArgs = listOf("-Didea.sync.active=true")) + ) { + resolveIdeDependencies { dependencies -> + dependencies["commonMain"].assertMatches( + kotlinNativeDistributionDependencies, + binaryCoordinates(Regex("com.example:cinterop-.*-dummy:.*:linux_x64")), + IdeaKotlinDependencyMatcher("Unresolved 'failing' cinterop") { dependency -> + dependency is IdeaKotlinUnresolvedBinaryDependency && dependency.cause.orEmpty().contains( + "cinterop-withFailingCInteropProcess-cinterop-failing.klib" + ) + } + ) + } + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/mpp/MppCompositeBuildIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/mpp/MppCompositeBuildIT.kt index 63e6412c7e3..fa7e9e29033 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/mpp/MppCompositeBuildIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/mpp/MppCompositeBuildIT.kt @@ -34,7 +34,7 @@ class MppCompositeBuildIT : KGPBaseTest() { regularSourceDependency("producerBuild::producerA/commonMain"), regularSourceDependency("producerBuild::producerA/nativeMain"), regularSourceDependency("producerBuild::producerA/linuxMain"), - kotilnNativeDistributionDependencies, + kotlinNativeDistributionDependencies, binaryCoordinates(Regex(".*stdlib-common:.*")) /* KT-56278 */ ) @@ -48,7 +48,7 @@ class MppCompositeBuildIT : KGPBaseTest() { dependsOnDependency(":consumerA/nativeMain"), dependsOnDependency(":consumerA/linuxMain"), projectArtifactDependency(Regular, "producerBuild::producerA", FilePathRegex(".*/linuxX64/main/klib/producerA.klib")), - kotilnNativeDistributionDependencies, + kotlinNativeDistributionDependencies, ) } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/IdeaKotlinDependencyMatchers.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/IdeaKotlinDependencyMatchers.kt index 3a4734ca4ee..2dbc2efbdf9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/IdeaKotlinDependencyMatchers.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/util/IdeaKotlinDependencyMatchers.kt @@ -14,6 +14,6 @@ val kotlinStdlibDependencies = binaryCoordinates(Regex(".*kotlin-stdlib.*")) val jetbrainsAnnotationDependencies = binaryCoordinates(Regex("org\\.jetbrains:annotations:.*")) -val kotilnNativeDistributionDependencies = IdeaKotlinDependencyMatcher("native distribution") { dependency -> +val kotlinNativeDistributionDependencies = IdeaKotlinDependencyMatcher("native distribution") { dependency -> dependency is IdeaKotlinResolvedBinaryDependency && dependency.isNativeDistribution } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/build.gradle.kts new file mode 100644 index 00000000000..f6f7d15dd5f --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/build.gradle.kts @@ -0,0 +1,27 @@ +plugins { + kotlin("multiplatform") +} + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin { + linuxX64 { + compilations.getByName("main") { + cinterops { + create("dummy") { + headers("libs/include/dummy.h") + } + + create("failing") { + headers("libs/include/failing.h") + } + } + } + } +} + +group = "com.example" +version = "1.0" \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/dummy.h b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/dummy.h new file mode 100644 index 00000000000..f244c9634b3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/dummy.h @@ -0,0 +1 @@ +int dummyCFunction(); \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/failing.h b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/failing.h new file mode 100644 index 00000000000..de4bab45c82 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/libs/include/failing.h @@ -0,0 +1 @@ +! NOT A VALID HEADER FILE ! \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/commonMain/kotlin/com.lib/CommonMain.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/commonMain/kotlin/com.lib/CommonMain.kt new file mode 100644 index 00000000000..105abf7b214 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/commonMain/kotlin/com.lib/CommonMain.kt @@ -0,0 +1,12 @@ +/* + * 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 com.lib + +import dummy.dummyCFunction + +val helloFromLib = "Hello from Lib" + +val helloFromCInterop = dummyCFunction() \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/dummy.def b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/dummy.def new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/failing.def b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/cinterop-withFailingCInteropProcess/src/nativeInterop/cinterop/failing.def new file mode 100644 index 00000000000..e69de29bb2d