Skip to content

Commit

Permalink
[ABI Validation] Improve test suite with more use cases
Browse files Browse the repository at this point in the history
Here are some of the new tests:

* tests that api file name matches custom project name (settings.gradle)
* tests that check tasks runs apiCheck
* tests projects hierarchies with plugin applied to root project
Pull request Kotlin/binary-compatibility-validator#40
  • Loading branch information
joffrey-bion authored and shanshin committed Oct 22, 2024
1 parent 9e7a09a commit 1559941
Show file tree
Hide file tree
Showing 19 changed files with 812 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package kotlinx.validation.api
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.TaskOutcome
import kotlin.test.assertEquals
import kotlin.test.assertNull

/**
* Helper `fun` for asserting a [TaskOutcome] to be equal to [TaskOutcome.SUCCESS]
Expand All @@ -25,4 +26,12 @@ internal fun BuildResult.assertTaskFailure(task: String) {

private fun BuildResult.assertTaskOutcome(taskOutcome: TaskOutcome, taskName: String) {
assertEquals(taskOutcome, task(taskName)?.outcome)
}
}

/**
* Helper `fun` for asserting that a task was not run, which also happens if one of its dependencies failed before it
* could be run.
*/
internal fun BuildResult.assertTaskNotRun(taskName: String) {
assertNull(task(taskName), "task $taskName was not expected to be run")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package kotlinx.validation.api

import org.junit.Before
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.io.File
Expand All @@ -14,16 +13,8 @@ internal open class BaseKotlinGradleTest {
@Rule
@JvmField
internal val testProjectDir: TemporaryFolder = TemporaryFolder()
internal lateinit var apiDump: File

@Before
fun setup() {
apiDump = testProjectDir.newFolder("api")
.toPath()
.resolve("${testProjectDir.root.name}.api")
.toFile()
.apply {
createNewFile()
}
}
internal val rootProjectDir: File get() = testProjectDir.root

internal val rootProjectApiDump: File get() = rootProjectDir.resolve("api/${rootProjectDir.name}.api")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

package kotlinx.validation.api

import kotlinx.validation.API_DIR
import org.gradle.testkit.runner.*
import java.io.*

Expand All @@ -13,37 +14,30 @@ internal fun BaseKotlinGradleTest.test(fn: BaseKotlinScope.() -> Unit): GradleRu
fn(baseKotlinScope)

baseKotlinScope.files.forEach { scope ->
val fileWriteTo = testProjectDir.root.resolve(scope.filePath)
val fileWriteTo = rootProjectDir.resolve(scope.filePath)
.apply {
parentFile.mkdirs()
createNewFile()
}

scope.files.forEach {
val fileContent = readFileList(it)
fileWriteTo.appendText("\n" + fileContent)
fileWriteTo.appendText(fileContent)
}
}

return GradleRunner.create() //
.withProjectDir(testProjectDir.root)
.withProjectDir(rootProjectDir)
.withPluginClasspath()
.withArguments(baseKotlinScope.runner.arguments)
// disabled because of: https://github.com/gradle/gradle/issues/6862
// .withDebug(baseKotlinScope.runner.debug)
}

internal fun BaseKotlinScope.file(fileName: String, fn: AppendableScope.() -> Unit) {
val appendableScope = AppendableScope(fileName)
fn(appendableScope)

files.add(appendableScope)
}

/**
* same as [file], but appends "src/main/java" before given `classFileName`
* same as [file][FileContainer.file], but prepends "src/main/java" before given `classFileName`
*/
internal fun BaseKotlinScope.kotlin(classFileName: String, fn: AppendableScope.() -> Unit) {
internal fun FileContainer.kotlin(classFileName: String, fn: AppendableScope.() -> Unit) {
require(classFileName.endsWith(".kt")) {
"ClassFileName must end with '.kt'"
}
Expand All @@ -53,13 +47,49 @@ internal fun BaseKotlinScope.kotlin(classFileName: String, fn: AppendableScope.(
}

/**
* Shortcut for creating a `build.gradle.kts` by using [file]
* Shortcut for creating a `build.gradle.kts` by using [file][FileContainer.file]
*/
internal fun BaseKotlinScope.buildGradleKts(fn: AppendableScope.() -> Unit) {
internal fun FileContainer.buildGradleKts(fn: AppendableScope.() -> Unit) {
val fileName = "build.gradle.kts"
file(fileName, fn)
}

/**
* Shortcut for creating a `settings.gradle.kts` by using [file][FileContainer.file]
*/
internal fun FileContainer.settingsGradleKts(fn: AppendableScope.() -> Unit) {
val fileName = "settings.gradle.kts"
file(fileName, fn)
}

/**
* Declares a directory with the given [dirName] inside the current container.
* All calls creating files within this scope will create the files nested in this directory.
*
* Note that it is valid to call this method multiple times at the same level with the same [dirName].
* Files declared within 2 independent calls to [dir] will be added to the same directory.
*/
internal fun FileContainer.dir(dirName: String, fn: DirectoryScope.() -> Unit) {
DirectoryScope(dirName, this).fn()
}

/**
* Shortcut for creating a `api/<project>.api` descriptor by using [file][FileContainer.file]
*/
internal fun FileContainer.apiFile(projectName: String, fn: AppendableScope.() -> Unit) {
dir(API_DIR) {
file("$projectName.api", fn)
}
}

// not using default argument in apiFile for clarity in tests (explicit "empty" in the name)
/**
* Shortcut for creating an empty `api/<project>.api` descriptor by using [file][FileContainer.file]
*/
internal fun FileContainer.emptyApiFile(projectName: String) {
apiFile(projectName) {}
}

internal fun BaseKotlinScope.runner(fn: Runner.() -> Unit) {
val runner = Runner()
fn(runner)
Expand All @@ -71,9 +101,29 @@ internal fun AppendableScope.resolve(fileName: String) {
this.files.add(fileName)
}

internal class BaseKotlinScope {
internal interface FileContainer {
fun file(fileName: String, fn: AppendableScope.() -> Unit)
}

internal class BaseKotlinScope : FileContainer {
var files: MutableList<AppendableScope> = mutableListOf()
var runner: Runner = Runner()

override fun file(fileName: String, fn: AppendableScope.() -> Unit) {
val appendableScope = AppendableScope(fileName)
fn(appendableScope)
files.add(appendableScope)
}
}

internal class DirectoryScope(
val dirPath: String,
val parent: FileContainer
): FileContainer {

override fun file(fileName: String, fn: AppendableScope.() -> Unit) {
parent.file("$dirPath/$fileName", fn)
}
}

internal class AppendableScope(val filePath: String) {
Expand Down
Loading

0 comments on commit 1559941

Please sign in to comment.