Migrated BuildCacheIT tests to new DSL.

^KT-45745 In Progress
This commit is contained in:
Yahor Berdnikau
2021-08-06 16:39:29 +02:00
parent 20afb268d1
commit b5ea811b9f
7 changed files with 224 additions and 224 deletions
@@ -16,215 +16,208 @@
package org.jetbrains.kotlin.gradle package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.util.modify import org.gradle.util.GradleVersion
import org.junit.Test import org.jetbrains.kotlin.gradle.testbase.*
import java.io.File import org.junit.jupiter.api.DisplayName
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.readText
import kotlin.io.path.writeText
class BuildCacheIT : BaseGradleIT() { @ExperimentalPathApi
override fun defaultBuildOptions(): BuildOptions = @DisplayName("Local build cache")
super.defaultBuildOptions().copy(withBuildCache = true) @SimpleGradlePluginTests
class BuildCacheIT : KGPBaseTest() {
companion object { override val defaultBuildOptions: BuildOptions =
private val GRADLE_VERSION = GradleVersionRequired.None super.defaultBuildOptions.copy(buildCacheEnabled = true)
}
@Test private val localBuildCacheDir get() = workingDir.resolve("custom-jdk-build-cache")
fun testKotlinCachingEnabledFlag() = with(Project("simpleProject", GRADLE_VERSION)) {
prepareLocalBuildCache()
build("assemble") { @DisplayName("kotlin.caching.enabled flag should enable caching for Kotlin tasks")
assertSuccessful() @GradleTest
assertTaskPackedToCache(":compileKotlin") fun testKotlinCachingEnabledFlag(gradleVersion: GradleVersion) {
} project("simpleProject", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
build("clean", "assemble", "-Dkotlin.caching.enabled=false") {
assertSuccessful()
assertNotContains(":compileKotlin FROM-CACHE")
}
}
@Test
fun testCacheHitAfterClean() = with(Project("simpleProject", GRADLE_VERSION)) {
prepareLocalBuildCache()
build("assemble") {
assertSuccessful()
assertTaskPackedToCache(":compileKotlin")
}
build("clean", "assemble") {
assertSuccessful()
assertContains(":compileKotlin FROM-CACHE")
assertContains(":compileJava FROM-CACHE")
}
}
@Test
fun testCacheHitAfterCacheHit() = with(Project("simpleProject", GRADLE_VERSION)) {
prepareLocalBuildCache()
build("assemble") {
assertSuccessful()
// Should store the output into the cache:
assertTaskPackedToCache(":compileKotlin")
}
val sourceFile = File(projectDir, "src/main/kotlin/helloWorld.kt")
val originalSource: String = sourceFile.readText()
val modifiedSource: String = originalSource.replace(" and ", " + ")
sourceFile.writeText(modifiedSource)
build("assemble") {
assertSuccessful()
assertTaskPackedToCache(":compileKotlin")
}
sourceFile.writeText(originalSource)
build("assemble") {
assertSuccessful()
// Should load the output from cache:
assertContains(":compileKotlin FROM-CACHE")
}
sourceFile.writeText(modifiedSource)
build("assemble") {
assertSuccessful()
// And should load the output from cache again, without compilation:
assertContains(":compileKotlin FROM-CACHE")
}
}
@Test
fun testKotlinCompileIncrementalBuildWithoutRelocation() = with(Project("buildCacheSimple", GRADLE_VERSION)) {
prepareLocalBuildCache()
checkKotlinCompileCachingIncrementalBuild(projectDir, this)
}
@Test
fun testKotlinCompileCachingIncrementalBuildWithRelocation() {
with(Project("buildCacheSimple", GRADLE_VERSION)) {
prepareLocalBuildCache()
// Copy the project to a different directory
val copyProjectParentDir = projectDir.resolveSibling("copy_${projectDir.name}").also { it.mkdirs() }
copyRecursively(projectDir, copyProjectParentDir)
checkKotlinCompileCachingIncrementalBuild(copyProjectParentDir.resolve(projectName), this)
}
}
@Test
fun testKaptCachingIncrementalBuildWithoutRelocation() {
with(Project("kaptAvoidance", GRADLE_VERSION, directoryPrefix = "kapt2")) {
prepareLocalBuildCache()
checkKaptCachingIncrementalBuild(projectDir, this)
}
}
@Test
fun testKaptCachingIncrementalBuildWithRelocation() {
with(Project("kaptAvoidance", GRADLE_VERSION, directoryPrefix = "kapt2")) {
prepareLocalBuildCache()
// Copy the project to a different directory
val copyProjectParentDir = projectDir.resolveSibling("copy_${projectDir.name}").also { it.mkdirs() }
copyRecursively(projectDir, copyProjectParentDir)
checkKaptCachingIncrementalBuild(copyProjectParentDir.resolve(projectName), this)
}
}
private fun checkKotlinCompileCachingIncrementalBuild(projectToBeModified: File, project: BaseGradleIT.Project) {
with(project) {
// First build, should be stored into the build cache:
build("assemble") { build("assemble") {
assertSuccessful() assertTasksPackedToCache(":compileKotlin")
assertTaskPackedToCache(":compileKotlin")
} }
// A cache hit: a clean build without any changes to the project build("clean", "assemble", "-Dkotlin.caching.enabled=false") {
build("clean", "assemble", projectDir = projectToBeModified) { assertTasksExecuted(":compileKotlin")
assertSuccessful()
assertContains(":compileKotlin FROM-CACHE")
}
// Change the return type of foo() from Int to String in foo.kt, and check that fooUsage.kt is recompiled as well:
File(projectToBeModified, "src/main/kotlin/foo.kt").modify { it.replace("Int = 1", "String = \"abc\"") }
build("assemble", projectDir = projectToBeModified) {
assertSuccessful()
assertCompiledKotlinSources(relativize(allKotlinFiles))
}
// Revert the change to the return type of foo(), and check if we get a cache hit
File(projectToBeModified, "src/main/kotlin/foo.kt").modify { it.replace("String = \"abc\"", "Int = 1") }
build("clean", "assemble", projectDir = projectToBeModified) {
assertSuccessful()
assertContains(":compileKotlin FROM-CACHE")
} }
} }
} }
private fun checkKaptCachingIncrementalBuild(projectToBeModified: File, project: BaseGradleIT.Project) { @DisplayName("Kotlin JVM task should be taken from cache")
with(project) { @GradleTest
val options = defaultBuildOptions().copy( fun testCacheHitAfterClean(gradleVersion: GradleVersion) {
kaptOptions = KaptOptions( project("simpleProject", gradleVersion) {
verbose = true, enableLocalBuildCache(localBuildCacheDir)
useWorkers = false,
incrementalKapt = true, build("assemble") {
includeCompileClasspath = false assertTasksPackedToCache(":compileKotlin")
) }
build("clean", "assemble") {
assertTasksFromCache(":compileKotlin", ":compileJava")
}
}
}
@DisplayName("Should correctly handle modification/restoration of source file")
@GradleTest
fun testCacheHitAfterCacheHit(gradleVersion: GradleVersion) {
project("simpleProject", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
build("assemble") {
// Should store the output into the cache:
assertTasksPackedToCache(":compileKotlin")
}
val sourceFile = projectPath.resolve("src/main/kotlin/helloWorld.kt")
val originalSource: String = sourceFile.readText()
val modifiedSource: String = originalSource.replace(" and ", " + ")
sourceFile.writeText(modifiedSource)
build("assemble") {
assertTasksPackedToCache(":compileKotlin")
}
sourceFile.writeText(originalSource)
build("assemble") {
// Should load the output from cache:
assertTasksFromCache(":compileKotlin")
}
sourceFile.writeText(modifiedSource)
build("assemble") {
// And should load the output from cache again, without compilation:
assertTasksFromCache(":compileKotlin")
}
}
}
@DisplayName("Incremental compilation works with cache")
@GradleTest
fun testKotlinCompileIncrementalBuildWithoutRelocation(gradleVersion: GradleVersion) {
project("buildCacheSimple", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
checkKotlinCompileCachingIncrementalBuild(this, this)
}
}
// TODO: move it into relocatable build cache tests
@DisplayName("Incremental compilation build cache does not break relocated cache")
@GradleTest
fun testKotlinCompileCachingIncrementalBuildWithRelocation(gradleVersion: GradleVersion) {
val firstProject = project("buildCacheSimple", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
}
val secondProject = project("buildCacheSimple", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
}
checkKotlinCompileCachingIncrementalBuild(firstProject, secondProject)
}
// TODO: move it into relocatable build cache tests
@DisplayName("Kapt incremental compilation works with cache")
@GradleTest
fun testKaptCachingIncrementalBuildWithoutRelocation(gradleVersion: GradleVersion) {
project("kapt2/kaptAvoidance", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
checkKaptCachingIncrementalBuild(this, this)
}
}
// TODO: move it into build cache relocation tests
@DisplayName("Kapt incremental compilation build does not break relocated build cache")
@GradleTest
fun testKaptCachingIncrementalBuildWithRelocation(gradleVersion: GradleVersion) {
val firstProject = project("kapt2/kaptAvoidance", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
}
val secondProject = project("kapt2/kaptAvoidance", gradleVersion) {
enableLocalBuildCache(localBuildCacheDir)
}
checkKaptCachingIncrementalBuild(firstProject, secondProject)
}
private fun checkKotlinCompileCachingIncrementalBuild(
firstProject: TestProject,
secondProject: TestProject
) {
// First build, should be stored into the build cache:
firstProject.build("assemble") {
assertTasksPackedToCache(":compileKotlin")
}
// A cache hit: a clean build without any changes to the project
secondProject.build("clean", "assemble") {
assertTasksFromCache(":compileKotlin")
}
// Change the return type of foo() from Int to String in foo.kt, and check that fooUsage.kt is recompiled as well:
val fooKtSourceFile = secondProject.projectPath.resolve("src/main/kotlin/foo.kt")
fooKtSourceFile.modify { it.replace("Int = 1", "String = \"abc\"") }
secondProject.build("assemble", forceOutput = true) {
assertIncrementalCompilation(modifiedFiles = setOf(fooKtSourceFile))
}
// Revert the change to the return type of foo(), and check if we get a cache hit
fooKtSourceFile.modify { it.replace("String = \"abc\"", "Int = 1") }
secondProject.build("clean", "assemble") {
assertTasksFromCache(":compileKotlin")
}
}
private fun checkKaptCachingIncrementalBuild(
firstProject: TestProject,
secondProject: TestProject
) {
val options = defaultBuildOptions.copy(
kaptOptions = BuildOptions.KaptOptions(
verbose = true,
useWorkers = false,
incrementalKapt = true,
includeCompileClasspath = false
) )
)
// First build, should be stored into the build cache: // First build, should be stored into the build cache:
build(options = options, params = *arrayOf("clean", ":app:build")) { firstProject.build("clean", ":app:build", buildOptions = options) {
assertSuccessful() assertTasksPackedToCache(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
assertTaskPackedToCache(":app:kaptGenerateStubsKotlin") }
assertTaskPackedToCache(":app:kaptKotlin")
}
// A cache hit: a clean build without any changes to the project // A cache hit: a clean build without any changes to the project
build(options = options, params = *arrayOf("clean", ":app:build"), projectDir = projectToBeModified) { secondProject.build("clean", ":app:build", buildOptions = options) {
assertSuccessful() assertTasksFromCache(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
assertContains(":app:kaptGenerateStubsKotlin FROM-CACHE") }
assertContains(":app:kaptKotlin FROM-CACHE")
}
// Make changes to annotated class and check kapt tasks are re-executed // Make changes to annotated class and check kapt tasks are re-executed
File(projectToBeModified, "app/src/main/kotlin/AppClass.kt").modify { val appClassKtSourceFile = secondProject.projectPath.resolve("app/src/main/kotlin/AppClass.kt")
it.replace("val testVal: String = \"text\"", "val testVal: Int = 1") appClassKtSourceFile.modify {
} it.replace("val testVal: String = \"text\"", "val testVal: Int = 1")
build(options = options, params = *arrayOf("build"), projectDir = projectToBeModified) { }
assertSuccessful() secondProject.build("build", buildOptions = options) {
assertContains("':app:kaptGenerateStubsKotlin' is not up-to-date") assertTasksExecuted(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
assertContains("':app:kaptKotlin' is not up-to-date") }
}
// Revert changes and check kapt tasks are from cache // Revert changes and check kapt tasks are from cache
File(projectToBeModified, "app/src/main/kotlin/AppClass.kt").modify { appClassKtSourceFile.modify {
it.replace("val testVal: Int = 1", "val testVal: String = \"text\"") it.replace("val testVal: Int = 1", "val testVal: String = \"text\"")
} }
build(options = options, params = *arrayOf("clean", "build"), projectDir = projectToBeModified) { secondProject.build("clean", "build", buildOptions = options) {
assertSuccessful() assertTasksFromCache(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
assertContains(":app:kaptGenerateStubsKotlin FROM-CACHE")
assertContains(":app:kaptKotlin FROM-CACHE")
}
} }
} }
} }
fun BaseGradleIT.Project.prepareLocalBuildCache(directory: File = File(projectDir.parentFile, "buildCache").apply { mkdir() }): File {
if (!projectDir.exists()) {
setupWorkingDir()
}
File(projectDir, "settings.gradle").appendText("\nbuildCache.local.directory = '${directory.absolutePath.replace("\\", "/")}'")
return directory
}
internal fun BaseGradleIT.CompiledProject.assertTaskPackedToCache(taskPath: String) {
with(project.testCase) {
assertContainsRegex(Regex("(?:Packing|Stored cache entry for) task '${Regex.escape(taskPath)}'"))
}
}
@@ -206,4 +206,18 @@ class BuildCacheRelocationIT : BaseGradleIT() {
.map { it.relativeTo(dir) to it.readBytes().contentHashCode() } .map { it.relativeTo(dir) to it.readBytes().contentHashCode() }
.toList() .toList()
} }
private fun BaseGradleIT.Project.prepareLocalBuildCache(directory: File = File(projectDir.parentFile, "buildCache").apply { mkdir() }): File {
if (!projectDir.exists()) {
setupWorkingDir()
}
File(projectDir, "settings.gradle").appendText("\nbuildCache.local.directory = '${directory.absolutePath.replace("\\", "/")}'")
return directory
}
private fun CompiledProject.assertTaskPackedToCache(taskPath: String) {
with(project.testCase) {
assertContainsRegex(Regex("(?:Packing|Stored cache entry for) task '${Regex.escape(taskPath)}'"))
}
}
} }
@@ -1,21 +1,9 @@
buildscript { plugins {
repositories { id 'org.jetbrains.kotlin.jvm'
mavenLocal() id 'java'
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
} }
apply plugin: "kotlin"
apply plugin: 'java'
repositories { repositories {
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
} }
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
@@ -1,9 +1,10 @@
apply plugin: "kotlin" plugins {
apply plugin: "kotlin-kapt" id "org.jetbrains.kotlin.jvm"
id "org.jetbrains.kotlin.kapt"
}
dependencies { dependencies {
implementation project(":lib") implementation project(":lib")
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" implementation "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version"
kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version" kapt "org.jetbrains.kotlin:annotation-processor-example:$kotlin_version"
@@ -1,14 +1,8 @@
buildscript { plugins {
repositories { id "org.jetbrains.kotlin.jvm" apply false
mavenLocal() id "org.jetbrains.kotlin.kapt" apply false
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
} }
subprojects { subprojects {
repositories { repositories {
mavenLocal() mavenLocal()
@@ -1,5 +1,3 @@
apply plugin: "kotlin" plugins {
id "org.jetbrains.kotlin.jvm"
dependencies { }
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
@@ -1 +1,13 @@
pluginManagement {
repositories {
mavenLocal()
mavenCentral()
}
plugins {
id "org.jetbrains.kotlin.jvm" version "$kotlin_version"
id "org.jetbrains.kotlin.kapt" version "$kotlin_version"
}
}
include ':app', ':lib' include ':app', ':lib'