Skip to content

Commit 3a70033

Browse files
committed
Merge branch 'develop'
2 parents 218728f + f8e3ded commit 3a70033

18 files changed

+375
-44
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,15 @@ Binary compatibility validator is a Gradle plugin that can be added to your buil
3535
- in `build.gradle.kts`
3636
```kotlin
3737
plugins {
38-
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.1"
38+
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.2"
3939
}
4040
```
4141

4242
- in `build.gradle`
4343

4444
```groovy
4545
plugins {
46-
id 'org.jetbrains.kotlinx.binary-compatibility-validator' version '0.15.0-Beta.1'
46+
id 'org.jetbrains.kotlinx.binary-compatibility-validator' version '0.15.0-Beta.2'
4747
}
4848
```
4949

src/functionalTest/kotlin/kotlinx/validation/api/Assert.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,20 @@ internal fun BuildResult.assertTaskFailure(task: String) {
2424
assertTaskOutcome(TaskOutcome.FAILED, task)
2525
}
2626

27+
/**
28+
* Helper `fun` for asserting a [TaskOutcome] to be equal to [TaskOutcome.SKIPPED]
29+
*/
30+
internal fun BuildResult.assertTaskSkipped(task: String) {
31+
assertTaskOutcome(TaskOutcome.SKIPPED, task)
32+
}
33+
34+
/**
35+
* Helper `fun` for asserting a [TaskOutcome] to be equal to [TaskOutcome.UP_TO_DATE]
36+
*/
37+
internal fun BuildResult.assertTaskUpToDate(task: String) {
38+
assertTaskOutcome(TaskOutcome.UP_TO_DATE, task)
39+
}
40+
2741
private fun BuildResult.assertTaskOutcome(taskOutcome: TaskOutcome, taskName: String) {
2842
assertEquals(taskOutcome, task(taskName)?.outcome)
2943
}

src/functionalTest/kotlin/kotlinx/validation/api/TestDsl.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ internal fun FileContainer.emptyApiFile(projectName: String) {
148148
apiFile(projectName) {}
149149
}
150150

151-
internal fun BaseKotlinScope.runner(fn: Runner.() -> Unit) {
152-
val runner = Runner()
151+
internal fun BaseKotlinScope.runner(withConfigurationCache: Boolean = true, fn: Runner.() -> Unit) {
152+
val runner = Runner(withConfigurationCache)
153153
fn(runner)
154154

155155
this.runner = runner
@@ -188,9 +188,9 @@ internal class AppendableScope(val filePath: String) {
188188
val files: MutableList<String> = mutableListOf()
189189
}
190190

191-
internal class Runner {
191+
internal class Runner(withConfigurationCache: Boolean = true) {
192192
val arguments: MutableList<String> = mutableListOf<String>().apply {
193-
if (!koverEnabled) {
193+
if (!koverEnabled && withConfigurationCache) {
194194
// Configuration cache is incompatible with javaagents being enabled for Gradle
195195
// See https://github.com/gradle/gradle/issues/25979
196196
add("--configuration-cache")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2016-2024 JetBrains s.r.o.
3+
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
4+
*/
5+
6+
package kotlinx.validation.test
7+
8+
import kotlinx.validation.api.*
9+
import kotlinx.validation.api.resolve
10+
import kotlinx.validation.api.test
11+
import org.assertj.core.api.Assertions
12+
import org.junit.Test
13+
14+
class JvmProjectTests : BaseKotlinGradleTest() {
15+
@Test
16+
fun `apiDump for a project with generated sources only`() {
17+
val runner = test {
18+
buildGradleKts {
19+
resolve("/examples/gradle/base/withPlugin.gradle.kts")
20+
resolve("/examples/gradle/configuration/generatedSources/generatedJvmSources.gradle.kts")
21+
}
22+
// TODO: enable configuration cache back when we start skipping tasks correctly
23+
runner(withConfigurationCache = false) {
24+
arguments.add(":apiDump")
25+
}
26+
}
27+
runner.build().apply {
28+
assertTaskSuccess(":apiDump")
29+
30+
val expectedApi = readFileList("/examples/classes/GeneratedSources.dump")
31+
Assertions.assertThat(rootProjectApiDump.readText()).isEqualToIgnoringNewLines(expectedApi)
32+
}
33+
}
34+
35+
@Test
36+
fun `apiCheck for a project with generated sources only`() {
37+
val runner = test {
38+
buildGradleKts {
39+
resolve("/examples/gradle/base/withPlugin.gradle.kts")
40+
resolve("/examples/gradle/configuration/generatedSources/generatedJvmSources.gradle.kts")
41+
}
42+
apiFile(projectName = rootProjectDir.name) {
43+
resolve("/examples/classes/GeneratedSources.dump")
44+
}
45+
// TODO: enable configuration cache back when we start skipping tasks correctly
46+
runner(withConfigurationCache = false) {
47+
arguments.add(":apiCheck")
48+
}
49+
}
50+
runner.build().apply {
51+
assertTaskSuccess(":apiCheck")
52+
}
53+
}
54+
}

src/functionalTest/kotlin/kotlinx/validation/test/KlibVerificationTests.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.junit.Test
1818
import java.io.File
1919
import java.nio.file.Files
2020
import java.nio.file.Paths
21+
import kotlin.test.assertFalse
2122
import kotlin.test.assertTrue
2223

2324
internal const val BANNED_TARGETS_PROPERTY_NAME = "binary.compatibility.validator.klib.targets.disabled.for.testing"
@@ -633,4 +634,68 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
633634
)
634635
}
635636
}
637+
638+
@Test
639+
fun `apiDump should not fail for empty project`() {
640+
val runner = test {
641+
baseProjectSetting()
642+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
643+
runApiDump()
644+
}
645+
646+
runner.build().apply {
647+
assertTaskSkipped(":klibApiDump")
648+
}
649+
assertFalse(runner.projectDir.resolve("api").exists())
650+
}
651+
652+
@Test
653+
fun `apiDump should not fail if there is only one target`() {
654+
val runner = test {
655+
baseProjectSetting()
656+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
657+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "linuxX64Main")
658+
runApiDump()
659+
}
660+
checkKlibDump(runner.build(), "/examples/classes/AnotherBuildConfig.klib.linuxX64Only.dump")
661+
}
662+
663+
@Test
664+
fun `apiCheck should not fail for empty project`() {
665+
val runner = test {
666+
baseProjectSetting()
667+
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
668+
runApiCheck()
669+
}
670+
runner.build()
671+
}
672+
673+
@Test
674+
fun `apiDump for a project with generated sources only`() {
675+
val runner = test {
676+
baseProjectSetting()
677+
additionalBuildConfig("/examples/gradle/configuration/generatedSources/generatedSources.gradle.kts")
678+
// TODO: enable configuration cache back when we start skipping tasks correctly
679+
runner(withConfigurationCache = false) {
680+
arguments.add(":apiDump")
681+
}
682+
}
683+
checkKlibDump(runner.build(), "/examples/classes/GeneratedSources.klib.dump")
684+
}
685+
686+
@Test
687+
fun `apiCheck for a project with generated sources only`() {
688+
val runner = test {
689+
baseProjectSetting()
690+
additionalBuildConfig("/examples/gradle/configuration/generatedSources/generatedSources.gradle.kts")
691+
abiFile(projectName = "testproject") {
692+
resolve("/examples/classes/GeneratedSources.klib.dump")
693+
}
694+
// TODO: enable configuration cache back when we start skipping tasks correctly
695+
runner(withConfigurationCache = false) {
696+
arguments.add(":apiCheck")
697+
}
698+
}
699+
assertApiCheckPassed(runner.build())
700+
}
636701
}

src/functionalTest/kotlin/kotlinx/validation/test/MultiPlatformSingleJvmKlibTargetTest.kt renamed to src/functionalTest/kotlin/kotlinx/validation/test/MultiPlatformSingleJvmTargetTest.kt

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
/*
2-
* Copyright 2016-2021 JetBrains s.r.o.
2+
* Copyright 2016-2024 JetBrains s.r.o.
33
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
44
*/
55

66
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
1011
import org.junit.Test
1112
import java.io.File
1213

13-
internal class MultiPlatformSingleJvmKlibTargetTest : BaseKotlinGradleTest() {
14+
internal class MultiPlatformSingleJvmTargetTest : BaseKotlinGradleTest() {
1415
private fun BaseKotlinScope.createProjectHierarchyWithPluginOnRoot() {
1516
settingsGradleKts {
1617
resolve("/examples/gradle/settings/settings-name-testproject.gradle.kts")
@@ -116,6 +117,45 @@ internal class MultiPlatformSingleJvmKlibTargetTest : BaseKotlinGradleTest() {
116117
}
117118
}
118119

120+
@Test
121+
fun testApiDumpPassesForEmptyProject() {
122+
val runner = test {
123+
buildGradleKts {
124+
resolve("/examples/gradle/base/multiplatformWithSingleJvmTarget.gradle.kts")
125+
}
126+
127+
runner {
128+
arguments.add(":apiDump")
129+
}
130+
}
131+
132+
runner.build().apply {
133+
assertTaskSkipped(":jvmApiDump")
134+
assertTaskUpToDate(":apiDump")
135+
}
136+
}
137+
138+
@Test
139+
fun testApiCheckPassesForEmptyProject() {
140+
val runner = test {
141+
buildGradleKts {
142+
resolve("/examples/gradle/base/multiplatformWithSingleJvmTarget.gradle.kts")
143+
}
144+
145+
emptyApiFile(projectName = rootProjectDir.name)
146+
147+
runner {
148+
arguments.add(":apiCheck")
149+
}
150+
}
151+
152+
runner.build().apply {
153+
assertTaskSkipped(":jvmApiCheck")
154+
assertTaskUpToDate(":apiCheck")
155+
156+
}
157+
}
158+
119159
private val jvmApiDump: File get() = rootProjectDir.resolve("$API_DIR/testproject.api")
120160

121161
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Klib ABI Dump
2+
// Targets: [linuxX64]
3+
// Rendering settings:
4+
// - Signature version: 2
5+
// - Show manifest properties: true
6+
// - Show declarations: true
7+
8+
// Library unique name: <testproject>
9+
final class org.different.pack/BuildConfig { // org.different.pack/BuildConfig|null[0]
10+
constructor <init>() // org.different.pack/BuildConfig.<init>|<init>(){}[0]
11+
final fun f1(): kotlin/Int // org.different.pack/BuildConfig.f1|f1(){}[0]
12+
final val p1 // org.different.pack/BuildConfig.p1|{}p1[0]
13+
final fun <get-p1>(): kotlin/Int // org.different.pack/BuildConfig.p1.<get-p1>|<get-p1>(){}[0]
14+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public final class Generated {
2+
public fun <init> ()V
3+
public final fun helloCreator ()I
4+
}
5+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Klib ABI Dump
2+
// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, linuxArm64, linuxX64, mingwX64]
3+
// Rendering settings:
4+
// - Signature version: 2
5+
// - Show manifest properties: true
6+
// - Show declarations: true
7+
8+
// Library unique name: <testproject>
9+
final class /Generated { // /Generated|null[0]
10+
constructor <init>() // /Generated.<init>|<init>(){}[0]
11+
final fun helloCreator(): kotlin/Int // /Generated.helloCreator|helloCreator(){}[0]
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
abstract class GenerateSourcesTask : org.gradle.api.DefaultTask() {
2+
@get:org.gradle.api.tasks.OutputDirectory
3+
abstract val outputDirectory: org.gradle.api.file.DirectoryProperty
4+
5+
@org.gradle.api.tasks.TaskAction
6+
fun generate() {
7+
outputDirectory.asFile.get().mkdirs()
8+
outputDirectory.file("Generated.kt").get().asFile.writeText("""
9+
public class Generated { public fun helloCreator(): Int = 42 }
10+
""".trimIndent())
11+
}
12+
}
13+
14+
val srcgen = project.tasks.register("generateSources", GenerateSourcesTask::class.java)
15+
srcgen.configure {
16+
outputDirectory.set(project.layout.buildDirectory.get().dir("generated").dir("kotlin"))
17+
}
18+
19+
project.sourceSets.getByName("main") {
20+
kotlin.srcDir(srcgen)
21+
}

0 commit comments

Comments
 (0)