Skip to content

Commit 1e26d07

Browse files
fzhinkinshanshin
authored andcommitted
[ABI Validation] Make Klib-related Gradle tasks public
Fixes Kotlin/binary-compatibility-validator#203 Pull request Kotlin/binary-compatibility-validator#204
1 parent 70359a1 commit 1e26d07

18 files changed

+583
-511
lines changed

libraries/tools/abi-validation/api/binary-compatibility-validator.api

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,13 @@ public final class kotlinx/validation/BinaryCompatibilityValidatorPlugin : org/g
3131
}
3232

3333
public abstract class kotlinx/validation/BuildTaskBase : org/gradle/api/DefaultTask {
34-
public field outputApiFile Ljava/io/File;
3534
public fun <init> ()V
36-
public final fun getIgnoredClasses ()Ljava/util/Set;
37-
public final fun getIgnoredPackages ()Ljava/util/Set;
38-
public final fun getNonPublicMarkers ()Ljava/util/Set;
39-
public final fun getOutputApiFile ()Ljava/io/File;
40-
public final fun getPublicClasses ()Ljava/util/Set;
41-
public final fun getPublicMarkers ()Ljava/util/Set;
42-
public final fun getPublicPackages ()Ljava/util/Set;
43-
public final fun setIgnoredClasses (Ljava/util/Set;)V
44-
public final fun setIgnoredPackages (Ljava/util/Set;)V
45-
public final fun setNonPublicMarkers (Ljava/util/Set;)V
46-
public final fun setOutputApiFile (Ljava/io/File;)V
47-
public final fun setPublicClasses (Ljava/util/Set;)V
48-
public final fun setPublicMarkers (Ljava/util/Set;)V
49-
public final fun setPublicPackages (Ljava/util/Set;)V
35+
public final fun getIgnoredClasses ()Lorg/gradle/api/provider/SetProperty;
36+
public final fun getIgnoredPackages ()Lorg/gradle/api/provider/SetProperty;
37+
public final fun getNonPublicMarkers ()Lorg/gradle/api/provider/SetProperty;
38+
public final fun getPublicClasses ()Lorg/gradle/api/provider/SetProperty;
39+
public final fun getPublicMarkers ()Lorg/gradle/api/provider/SetProperty;
40+
public final fun getPublicPackages ()Lorg/gradle/api/provider/SetProperty;
5041
}
5142

5243
public abstract interface annotation class kotlinx/validation/ExperimentalBCVApi : java/lang/annotation/Annotation {
@@ -55,6 +46,12 @@ public abstract interface annotation class kotlinx/validation/ExperimentalBCVApi
5546
public abstract interface annotation class kotlinx/validation/ExternalApi : java/lang/annotation/Annotation {
5647
}
5748

49+
public final class kotlinx/validation/KlibDumpMetadata : java/io/Serializable {
50+
public fun <init> (Lkotlinx/validation/api/klib/KlibTarget;Lorg/gradle/api/file/RegularFileProperty;)V
51+
public final fun getDumpFile ()Lorg/gradle/api/file/RegularFileProperty;
52+
public final fun getTarget ()Lkotlinx/validation/api/klib/KlibTarget;
53+
}
54+
5855
public class kotlinx/validation/KlibValidationSettings {
5956
public fun <init> ()V
6057
public final fun getEnabled ()Z
@@ -65,24 +62,52 @@ public class kotlinx/validation/KlibValidationSettings {
6562
public final fun setStrictValidation (Z)V
6663
}
6764

68-
public class kotlinx/validation/KotlinApiBuildTask : kotlinx/validation/BuildTaskBase {
69-
public field inputDependencies Lorg/gradle/api/file/FileCollection;
65+
public abstract class kotlinx/validation/KotlinApiBuildTask : kotlinx/validation/BuildTaskBase {
7066
public fun <init> ()V
71-
public final fun getInputClassesDirs ()Lorg/gradle/api/file/FileCollection;
72-
public final fun getInputDependencies ()Lorg/gradle/api/file/FileCollection;
73-
public final fun getInputJar ()Lorg/gradle/api/file/RegularFileProperty;
74-
public final fun setInputClassesDirs (Lorg/gradle/api/file/FileCollection;)V
75-
public final fun setInputDependencies (Lorg/gradle/api/file/FileCollection;)V
67+
public abstract fun getInputClassesDirs ()Lorg/gradle/api/file/ConfigurableFileCollection;
68+
public abstract fun getInputDependencies ()Lorg/gradle/api/file/ConfigurableFileCollection;
69+
public abstract fun getInputJar ()Lorg/gradle/api/file/RegularFileProperty;
70+
public abstract fun getOutputApiFile ()Lorg/gradle/api/file/RegularFileProperty;
7671
}
7772

7873
public class kotlinx/validation/KotlinApiCompareTask : org/gradle/api/DefaultTask {
79-
public field generatedApiFile Ljava/io/File;
80-
public field projectApiFile Ljava/io/File;
8174
public fun <init> ()V
82-
public final fun getGeneratedApiFile ()Ljava/io/File;
83-
public final fun getProjectApiFile ()Ljava/io/File;
84-
public final fun setGeneratedApiFile (Ljava/io/File;)V
85-
public final fun setProjectApiFile (Ljava/io/File;)V
75+
public final fun getGeneratedApiFile ()Lorg/gradle/api/file/RegularFileProperty;
76+
public final fun getProjectApiFile ()Lorg/gradle/api/file/RegularFileProperty;
77+
}
78+
79+
public abstract class kotlinx/validation/KotlinKlibAbiBuildTask : kotlinx/validation/BuildTaskBase {
80+
public fun <init> ()V
81+
public abstract fun getKlibFile ()Lorg/gradle/api/file/ConfigurableFileCollection;
82+
public abstract fun getOutputAbiFile ()Lorg/gradle/api/file/RegularFileProperty;
83+
public final fun getSignatureVersion ()Lorg/gradle/api/provider/Property;
84+
public abstract fun getTarget ()Lorg/gradle/api/provider/Property;
85+
}
86+
87+
public abstract class kotlinx/validation/KotlinKlibExtractAbiTask : org/gradle/api/DefaultTask {
88+
public fun <init> ()V
89+
public abstract fun getInputAbiFile ()Lorg/gradle/api/file/RegularFileProperty;
90+
public abstract fun getOutputAbiFile ()Lorg/gradle/api/file/RegularFileProperty;
91+
public abstract fun getRequiredTargets ()Lorg/gradle/api/provider/SetProperty;
92+
public final fun getStrictValidation ()Lorg/gradle/api/provider/Property;
93+
}
94+
95+
public abstract class kotlinx/validation/KotlinKlibInferAbiTask : org/gradle/api/DefaultTask {
96+
public fun <init> ()V
97+
public abstract fun getInputDumps ()Lorg/gradle/api/provider/SetProperty;
98+
public abstract fun getOldMergedKlibDump ()Lorg/gradle/api/file/RegularFileProperty;
99+
public abstract fun getOutputAbiFile ()Lorg/gradle/api/file/RegularFileProperty;
100+
public abstract fun getTarget ()Lorg/gradle/api/provider/Property;
101+
}
102+
103+
public abstract class kotlinx/validation/KotlinKlibMergeAbiTask : org/gradle/api/DefaultTask {
104+
public fun <init> ()V
105+
public abstract fun getDumps ()Lorg/gradle/api/provider/SetProperty;
106+
public abstract fun getMergedApiFile ()Lorg/gradle/api/file/RegularFileProperty;
107+
}
108+
109+
public final class kotlinx/validation/_UtilsKt {
110+
public static final fun toKlibTarget (Lorg/jetbrains/kotlin/gradle/plugin/KotlinTarget;)Lkotlinx/validation/api/klib/KlibTarget;
86111
}
87112

88113
public final class kotlinx/validation/api/ClassBinarySignature {
@@ -162,7 +187,7 @@ public final class kotlinx/validation/api/klib/KlibDumpKt {
162187
public static final fun saveTo (Lkotlinx/validation/api/klib/KlibDump;Ljava/io/File;)V
163188
}
164189

165-
public final class kotlinx/validation/api/klib/KlibSignatureVersion {
190+
public final class kotlinx/validation/api/klib/KlibSignatureVersion : java/io/Serializable {
166191
public static final field Companion Lkotlinx/validation/api/klib/KlibSignatureVersion$Companion;
167192
public fun equals (Ljava/lang/Object;)Z
168193
public fun hashCode ()I
@@ -174,7 +199,7 @@ public final class kotlinx/validation/api/klib/KlibSignatureVersion$Companion {
174199
public final fun of (I)Lkotlinx/validation/api/klib/KlibSignatureVersion;
175200
}
176201

177-
public final class kotlinx/validation/api/klib/KlibTarget {
202+
public final class kotlinx/validation/api/klib/KlibTarget : java/io/Serializable {
178203
public static final field Companion Lkotlinx/validation/api/klib/KlibTarget$Companion;
179204
public fun equals (Ljava/lang/Object;)Z
180205
public final fun getConfigurableName ()Ljava/lang/String;

libraries/tools/abi-validation/src/functionalTest/kotlin/kotlinx/validation/test/DefaultConfigTests.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ internal class DefaultConfigTests : BaseKotlinGradleTest() {
2626
}
2727
}
2828

29+
val projectName = rootProjectDir.name
2930
runner.buildAndFail().apply {
30-
assertTrue { output.contains("Please ensure that ':apiDump' was executed") }
31+
Assertions.assertThat(output).contains(
32+
"Expected file with API declarations 'api/$projectName.api' does not exist."
33+
).contains(
34+
"Please ensure that ':apiDump' was executed in order to get an API dump to compare the build against"
35+
)
3136
assertTaskFailure(":apiCheck")
3237
}
3338
}

libraries/tools/abi-validation/src/functionalTest/kotlin/kotlinx/validation/test/JvmProjectTests.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ class JvmProjectTests : BaseKotlinGradleTest() {
1919
resolve("/examples/gradle/base/withPlugin.gradle.kts")
2020
resolve("/examples/gradle/configuration/generatedSources/generatedJvmSources.gradle.kts")
2121
}
22-
// TODO: enable configuration cache back when we start skipping tasks correctly
23-
runner(withConfigurationCache = false) {
22+
runner {
2423
arguments.add(":apiDump")
2524
}
2625
}
@@ -42,8 +41,7 @@ class JvmProjectTests : BaseKotlinGradleTest() {
4241
apiFile(projectName = rootProjectDir.name) {
4342
resolve("/examples/classes/GeneratedSources.dump")
4443
}
45-
// TODO: enable configuration cache back when we start skipping tasks correctly
46-
runner(withConfigurationCache = false) {
44+
runner {
4745
arguments.add(":apiCheck")
4846
}
4947
}

libraries/tools/abi-validation/src/functionalTest/kotlin/kotlinx/validation/test/KlibVerificationTests.kt

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import org.assertj.core.api.Assertions
1313
import org.gradle.testkit.runner.BuildResult
1414
import org.jetbrains.kotlin.konan.target.HostManager
1515
import org.jetbrains.kotlin.konan.target.KonanTarget
16+
import org.jetbrains.kotlin.utils.addToStdlib.butIf
17+
import org.junit.Assert
1618
import org.junit.Assume
1719
import org.junit.Test
1820
import java.io.File
@@ -48,27 +50,32 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
4850
resolve("/examples/gradle/base/withNativePlugin.gradle.kts")
4951
}
5052
}
53+
5154
private fun BaseKotlinScope.additionalBuildConfig(config: String) {
5255
buildGradleKts {
5356
resolve(config)
5457
}
5558
}
59+
5660
private fun BaseKotlinScope.addToSrcSet(pathTestFile: String, sourceSet: String = "commonMain") {
5761
val fileName = Paths.get(pathTestFile).fileName.toString()
5862
kotlin(fileName, sourceSet) {
5963
resolve(pathTestFile)
6064
}
6165
}
66+
6267
private fun BaseKotlinScope.runApiCheck() {
6368
runner {
6469
arguments.add(":apiCheck")
6570
}
6671
}
72+
6773
private fun BaseKotlinScope.runApiDump() {
6874
runner {
6975
arguments.add(":apiDump")
7076
}
7177
}
78+
7279
private fun assertApiCheckPassed(buildResult: BuildResult) {
7380
buildResult.assertTaskSuccess(":apiCheck")
7481
}
@@ -451,7 +458,7 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
451458
}
452459

453460
@Test
454-
fun `klibCheck if all klib-targets are unavailable`() {
461+
fun `klibCheck should not fail if all klib-targets are unavailable`() {
455462
val runner = test {
456463
baseProjectSetting()
457464
addToSrcSet("/examples/classes/TopLevelDeclarations.kt")
@@ -468,10 +475,32 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
468475
}
469476
}
470477

478+
runner.build().apply {
479+
assertTaskSuccess(":klibApiCheck")
480+
}
481+
}
482+
483+
@Test
484+
fun `klibCheck should fail with strict validation if all klib-targets are unavailable`() {
485+
val runner = test {
486+
baseProjectSetting()
487+
additionalBuildConfig("/examples/gradle/configuration/unsupported/enforce.gradle.kts")
488+
addToSrcSet("/examples/classes/TopLevelDeclarations.kt")
489+
abiFile(projectName = "testproject") {
490+
// note that the regular dump is used, where linuxArm64 is presented
491+
resolve("/examples/classes/TopLevelDeclarations.klib.dump")
492+
}
493+
runner {
494+
arguments.add(
495+
"-P$BANNED_TARGETS_PROPERTY_NAME=linuxArm64,linuxX64,mingwX64," +
496+
"androidNativeArm32,androidNativeArm64,androidNativeX64,androidNativeX86"
497+
)
498+
arguments.add(":klibApiCheck")
499+
}
500+
}
501+
471502
runner.buildAndFail().apply {
472-
Assertions.assertThat(output).contains(
473-
"KLib ABI dump/validation requires at least one enabled klib target, but none were found."
474-
)
503+
assertTaskFailure(":klibApiExtractForValidation")
475504
}
476505
}
477506

@@ -580,8 +609,10 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
580609
checkKlibDump(runner.build(), "/examples/classes/AnotherBuildConfig.klib.dump")
581610

582611
// Update the source file by adding a declaration
583-
val updatedSourceFile = File(this::class.java.getResource(
584-
"/examples/classes/AnotherBuildConfigModified.kt")!!.toURI()
612+
val updatedSourceFile = File(
613+
this::class.java.getResource(
614+
"/examples/classes/AnotherBuildConfigModified.kt"
615+
)!!.toURI()
585616
)
586617
val existingSource = runner.projectDir.resolve(
587618
"src/commonMain/kotlin/AnotherBuildConfig.kt"
@@ -601,8 +632,10 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
601632
checkKlibDump(runner.build(), "/examples/classes/AnotherBuildConfig.klib.dump")
602633

603634
// Update the source file by adding a declaration
604-
val updatedSourceFile = File(this::class.java.getResource(
605-
"/examples/classes/AnotherBuildConfigLinuxArm64.kt")!!.toURI()
635+
val updatedSourceFile = File(
636+
this::class.java.getResource(
637+
"/examples/classes/AnotherBuildConfigLinuxArm64.kt"
638+
)!!.toURI()
606639
)
607640
val existingSource = runner.projectDir.resolve(
608641
"src/linuxArm64Main/kotlin/AnotherBuildConfigLinuxArm64.kt"
@@ -626,8 +659,10 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
626659
assertApiCheckPassed(runner.build())
627660

628661
// Update the source file by adding a declaration
629-
val updatedSourceFile = File(this::class.java.getResource(
630-
"/examples/classes/AnotherBuildConfigModified.kt")!!.toURI()
662+
val updatedSourceFile = File(
663+
this::class.java.getResource(
664+
"/examples/classes/AnotherBuildConfigModified.kt"
665+
)!!.toURI()
631666
)
632667
val existingSource = runner.projectDir.resolve(
633668
"src/commonMain/kotlin/AnotherBuildConfig.kt"
@@ -665,12 +700,29 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
665700
runApiDump()
666701
}
667702

668-
runner.build().apply {
703+
runner.withDebug(true).build().apply {
669704
assertTaskSkipped(":klibApiDump")
670705
}
671706
assertFalse(runner.projectDir.resolve("api").exists())
672707
}
673708

709+
@Test
710+
fun `apiDump should remove dump file if the project does not contain sources anymore`() {
711+
val runner = test {
712+
baseProjectSetting()
713+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
714+
abiFile(projectName = "testproject") {
715+
resolve("/examples/classes/AnotherBuildConfig.klib.dump")
716+
}
717+
runApiDump()
718+
}
719+
720+
runner.build().apply {
721+
assertTaskSuccess(":klibApiDump")
722+
}
723+
assertFalse(runner.projectDir.resolve("api").resolve("testproject.klib.api").exists())
724+
}
725+
674726
@Test
675727
fun `apiDump should not fail if there is only one target`() {
676728
val runner = test {
@@ -683,22 +735,26 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
683735
}
684736

685737
@Test
686-
fun `apiCheck should not fail for empty project`() {
738+
fun `apiCheck should fail for empty project`() {
687739
val runner = test {
688740
baseProjectSetting()
689741
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
690742
runApiCheck()
691743
}
692-
runner.build()
744+
runner.buildAndFail().apply {
745+
assertTaskFailure(":klibApiExtractForValidation")
746+
Assertions.assertThat(output).contains(
747+
"File with project's API declarations 'api/testproject.klib.api' does not exist."
748+
)
749+
}
693750
}
694751

695752
@Test
696753
fun `apiDump for a project with generated sources only`() {
697754
val runner = test {
698755
baseProjectSetting()
699756
additionalBuildConfig("/examples/gradle/configuration/generatedSources/generatedSources.gradle.kts")
700-
// TODO: enable configuration cache back when we start skipping tasks correctly
701-
runner(withConfigurationCache = false) {
757+
runner {
702758
arguments.add(":apiDump")
703759
}
704760
}
@@ -713,11 +769,26 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
713769
abiFile(projectName = "testproject") {
714770
resolve("/examples/classes/GeneratedSources.klib.dump")
715771
}
716-
// TODO: enable configuration cache back when we start skipping tasks correctly
717-
runner(withConfigurationCache = false) {
772+
runner {
718773
arguments.add(":apiCheck")
719774
}
720775
}
721776
assertApiCheckPassed(runner.build())
722777
}
778+
779+
@Test
780+
fun `apiCheck should fail after a source set was removed`() {
781+
val runner = test {
782+
baseProjectSetting()
783+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", "linuxX64Main")
784+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", "linuxArm64Main")
785+
abiFile(projectName = "testproject") {
786+
resolve("/examples/classes/AnotherBuildConfig.klib.dump")
787+
}
788+
runApiCheck()
789+
}
790+
runner.buildAndFail().apply {
791+
assertTaskFailure(":klibApiCheck")
792+
}
793+
}
723794
}

libraries/tools/abi-validation/src/functionalTest/kotlin/kotlinx/validation/test/MultiPlatformSingleJvmTargetTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package kotlinx.validation.test
77

88
import kotlinx.validation.api.*
99
import org.assertj.core.api.Assertions.assertThat
10-
import org.gradle.testkit.runner.TaskOutcome
1110
import org.junit.Test
1211
import java.io.File
1312

0 commit comments

Comments
 (0)