Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
fzhinkin committed Apr 4, 2024
2 parents 218728f + f8e3ded commit 3a70033
Show file tree
Hide file tree
Showing 18 changed files with 375 additions and 44 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -35,15 +35,15 @@ Binary compatibility validator is a Gradle plugin that can be added to your buil
- in `build.gradle.kts`
```kotlin
plugins {
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.1"
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.2"
}
```

- in `build.gradle`

```groovy
plugins {
id 'org.jetbrains.kotlinx.binary-compatibility-validator' version '0.15.0-Beta.1'
id 'org.jetbrains.kotlinx.binary-compatibility-validator' version '0.15.0-Beta.2'
}
```

Expand Down
14 changes: 14 additions & 0 deletions src/functionalTest/kotlin/kotlinx/validation/api/Assert.kt
Expand Up @@ -24,6 +24,20 @@ internal fun BuildResult.assertTaskFailure(task: String) {
assertTaskOutcome(TaskOutcome.FAILED, task)
}

/**
* Helper `fun` for asserting a [TaskOutcome] to be equal to [TaskOutcome.SKIPPED]
*/
internal fun BuildResult.assertTaskSkipped(task: String) {
assertTaskOutcome(TaskOutcome.SKIPPED, task)
}

/**
* Helper `fun` for asserting a [TaskOutcome] to be equal to [TaskOutcome.UP_TO_DATE]
*/
internal fun BuildResult.assertTaskUpToDate(task: String) {
assertTaskOutcome(TaskOutcome.UP_TO_DATE, task)
}

private fun BuildResult.assertTaskOutcome(taskOutcome: TaskOutcome, taskName: String) {
assertEquals(taskOutcome, task(taskName)?.outcome)
}
Expand Down
8 changes: 4 additions & 4 deletions src/functionalTest/kotlin/kotlinx/validation/api/TestDsl.kt
Expand Up @@ -148,8 +148,8 @@ internal fun FileContainer.emptyApiFile(projectName: String) {
apiFile(projectName) {}
}

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

this.runner = runner
Expand Down Expand Up @@ -188,9 +188,9 @@ internal class AppendableScope(val filePath: String) {
val files: MutableList<String> = mutableListOf()
}

internal class Runner {
internal class Runner(withConfigurationCache: Boolean = true) {
val arguments: MutableList<String> = mutableListOf<String>().apply {
if (!koverEnabled) {
if (!koverEnabled && withConfigurationCache) {
// Configuration cache is incompatible with javaagents being enabled for Gradle
// See https://github.com/gradle/gradle/issues/25979
add("--configuration-cache")
Expand Down
@@ -0,0 +1,54 @@
/*
* Copyright 2016-2024 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package kotlinx.validation.test

import kotlinx.validation.api.*
import kotlinx.validation.api.resolve
import kotlinx.validation.api.test
import org.assertj.core.api.Assertions
import org.junit.Test

class JvmProjectTests : BaseKotlinGradleTest() {
@Test
fun `apiDump for a project with generated sources only`() {
val runner = test {
buildGradleKts {
resolve("/examples/gradle/base/withPlugin.gradle.kts")
resolve("/examples/gradle/configuration/generatedSources/generatedJvmSources.gradle.kts")
}
// TODO: enable configuration cache back when we start skipping tasks correctly
runner(withConfigurationCache = false) {
arguments.add(":apiDump")
}
}
runner.build().apply {
assertTaskSuccess(":apiDump")

val expectedApi = readFileList("/examples/classes/GeneratedSources.dump")
Assertions.assertThat(rootProjectApiDump.readText()).isEqualToIgnoringNewLines(expectedApi)
}
}

@Test
fun `apiCheck for a project with generated sources only`() {
val runner = test {
buildGradleKts {
resolve("/examples/gradle/base/withPlugin.gradle.kts")
resolve("/examples/gradle/configuration/generatedSources/generatedJvmSources.gradle.kts")
}
apiFile(projectName = rootProjectDir.name) {
resolve("/examples/classes/GeneratedSources.dump")
}
// TODO: enable configuration cache back when we start skipping tasks correctly
runner(withConfigurationCache = false) {
arguments.add(":apiCheck")
}
}
runner.build().apply {
assertTaskSuccess(":apiCheck")
}
}
}
Expand Up @@ -18,6 +18,7 @@ import org.junit.Test
import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.test.assertFalse
import kotlin.test.assertTrue

internal const val BANNED_TARGETS_PROPERTY_NAME = "binary.compatibility.validator.klib.targets.disabled.for.testing"
Expand Down Expand Up @@ -633,4 +634,68 @@ internal class KlibVerificationTests : BaseKotlinGradleTest() {
)
}
}

@Test
fun `apiDump should not fail for empty project`() {
val runner = test {
baseProjectSetting()
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
runApiDump()
}

runner.build().apply {
assertTaskSkipped(":klibApiDump")
}
assertFalse(runner.projectDir.resolve("api").exists())
}

@Test
fun `apiDump should not fail if there is only one target`() {
val runner = test {
baseProjectSetting()
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "linuxX64Main")
runApiDump()
}
checkKlibDump(runner.build(), "/examples/classes/AnotherBuildConfig.klib.linuxX64Only.dump")
}

@Test
fun `apiCheck should not fail for empty project`() {
val runner = test {
baseProjectSetting()
addToSrcSet("/examples/classes/AnotherBuildConfig.kt", sourceSet = "commonTest")
runApiCheck()
}
runner.build()
}

@Test
fun `apiDump for a project with generated sources only`() {
val runner = test {
baseProjectSetting()
additionalBuildConfig("/examples/gradle/configuration/generatedSources/generatedSources.gradle.kts")
// TODO: enable configuration cache back when we start skipping tasks correctly
runner(withConfigurationCache = false) {
arguments.add(":apiDump")
}
}
checkKlibDump(runner.build(), "/examples/classes/GeneratedSources.klib.dump")
}

@Test
fun `apiCheck for a project with generated sources only`() {
val runner = test {
baseProjectSetting()
additionalBuildConfig("/examples/gradle/configuration/generatedSources/generatedSources.gradle.kts")
abiFile(projectName = "testproject") {
resolve("/examples/classes/GeneratedSources.klib.dump")
}
// TODO: enable configuration cache back when we start skipping tasks correctly
runner(withConfigurationCache = false) {
arguments.add(":apiCheck")
}
}
assertApiCheckPassed(runner.build())
}
}
@@ -1,16 +1,17 @@
/*
* Copyright 2016-2021 JetBrains s.r.o.
* Copyright 2016-2024 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/

package kotlinx.validation.test

import kotlinx.validation.api.*
import org.assertj.core.api.Assertions.assertThat
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Test
import java.io.File

internal class MultiPlatformSingleJvmKlibTargetTest : BaseKotlinGradleTest() {
internal class MultiPlatformSingleJvmTargetTest : BaseKotlinGradleTest() {
private fun BaseKotlinScope.createProjectHierarchyWithPluginOnRoot() {
settingsGradleKts {
resolve("/examples/gradle/settings/settings-name-testproject.gradle.kts")
Expand Down Expand Up @@ -116,6 +117,45 @@ internal class MultiPlatformSingleJvmKlibTargetTest : BaseKotlinGradleTest() {
}
}

@Test
fun testApiDumpPassesForEmptyProject() {
val runner = test {
buildGradleKts {
resolve("/examples/gradle/base/multiplatformWithSingleJvmTarget.gradle.kts")
}

runner {
arguments.add(":apiDump")
}
}

runner.build().apply {
assertTaskSkipped(":jvmApiDump")
assertTaskUpToDate(":apiDump")
}
}

@Test
fun testApiCheckPassesForEmptyProject() {
val runner = test {
buildGradleKts {
resolve("/examples/gradle/base/multiplatformWithSingleJvmTarget.gradle.kts")
}

emptyApiFile(projectName = rootProjectDir.name)

runner {
arguments.add(":apiCheck")
}
}

runner.build().apply {
assertTaskSkipped(":jvmApiCheck")
assertTaskUpToDate(":apiCheck")

}
}

private val jvmApiDump: File get() = rootProjectDir.resolve("$API_DIR/testproject.api")

}
@@ -0,0 +1,14 @@
// Klib ABI Dump
// Targets: [linuxX64]
// Rendering settings:
// - Signature version: 2
// - Show manifest properties: true
// - Show declarations: true

// Library unique name: <testproject>
final class org.different.pack/BuildConfig { // org.different.pack/BuildConfig|null[0]
constructor <init>() // org.different.pack/BuildConfig.<init>|<init>(){}[0]
final fun f1(): kotlin/Int // org.different.pack/BuildConfig.f1|f1(){}[0]
final val p1 // org.different.pack/BuildConfig.p1|{}p1[0]
final fun <get-p1>(): kotlin/Int // org.different.pack/BuildConfig.p1.<get-p1>|<get-p1>(){}[0]
}
@@ -0,0 +1,5 @@
public final class Generated {
public fun <init> ()V
public final fun helloCreator ()I
}

@@ -0,0 +1,12 @@
// Klib ABI Dump
// Targets: [androidNativeArm32, androidNativeArm64, androidNativeX64, androidNativeX86, linuxArm64, linuxX64, mingwX64]
// Rendering settings:
// - Signature version: 2
// - Show manifest properties: true
// - Show declarations: true

// Library unique name: <testproject>
final class /Generated { // /Generated|null[0]
constructor <init>() // /Generated.<init>|<init>(){}[0]
final fun helloCreator(): kotlin/Int // /Generated.helloCreator|helloCreator(){}[0]
}
@@ -0,0 +1,21 @@
abstract class GenerateSourcesTask : org.gradle.api.DefaultTask() {
@get:org.gradle.api.tasks.OutputDirectory
abstract val outputDirectory: org.gradle.api.file.DirectoryProperty

@org.gradle.api.tasks.TaskAction
fun generate() {
outputDirectory.asFile.get().mkdirs()
outputDirectory.file("Generated.kt").get().asFile.writeText("""
public class Generated { public fun helloCreator(): Int = 42 }
""".trimIndent())
}
}

val srcgen = project.tasks.register("generateSources", GenerateSourcesTask::class.java)
srcgen.configure {
outputDirectory.set(project.layout.buildDirectory.get().dir("generated").dir("kotlin"))
}

project.sourceSets.getByName("main") {
kotlin.srcDir(srcgen)
}
@@ -0,0 +1,22 @@
abstract class GenerateSourcesTask : org.gradle.api.DefaultTask() {
@get:org.gradle.api.tasks.OutputDirectory
abstract val outputDirectory: org.gradle.api.file.DirectoryProperty

@org.gradle.api.tasks.TaskAction
fun generate() {
outputDirectory.asFile.get().mkdirs()
outputDirectory.file("Generated.kt").get().asFile.writeText("""
public class Generated { public fun helloCreator(): Int = 42 }
""".trimIndent())
}
}

val srcgen = project.tasks.register("generateSources", GenerateSourcesTask::class.java)
srcgen.configure {
outputDirectory.set(project.layout.buildDirectory.get().dir("generated").dir("kotlin"))
}

val kotlin = project.extensions.getByType(org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension::class.java)
kotlin.sourceSets.getByName("commonMain") {
kotlin.srcDir(srcgen)
}

0 comments on commit 3a70033

Please sign in to comment.