Rebuild and compare output class files in gradle incremental tests
KT-8487
This commit is contained in:
+5
-3
@@ -82,13 +82,15 @@ private fun getDirectoryString(dir: File, interestingPaths: List<String>): Strin
|
|||||||
p.pushIndent()
|
p.pushIndent()
|
||||||
|
|
||||||
val listFiles = dir.listFiles()
|
val listFiles = dir.listFiles()
|
||||||
assertNotNull(listFiles)
|
assertNotNull("$dir does not exist", listFiles)
|
||||||
|
|
||||||
val children = listFiles!!.sortedWith(compareBy({ it.isDirectory }, { it.name }))
|
val children = listFiles!!.sortedWith(compareBy({ it.isDirectory }, { it.name }))
|
||||||
for (child in children) {
|
for (child in children) {
|
||||||
if (child.isDirectory) {
|
if (child.isDirectory) {
|
||||||
p.println(child.name)
|
if ((child.list()?.isNotEmpty() ?: false)) {
|
||||||
addDirContent(child)
|
p.println(child.name)
|
||||||
|
addDirContent(child)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.println(child.name, " ", child.hash())
|
p.println(child.name, " ", child.hash())
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
<module>tools/kotlin-compiler</module>
|
<module>tools/kotlin-compiler</module>
|
||||||
<module>tools/kotlin-compiler-embeddable</module>
|
<module>tools/kotlin-compiler-embeddable</module>
|
||||||
<module>tools/kotlin-build-common</module>
|
<module>tools/kotlin-build-common</module>
|
||||||
|
<module>tools/kotlin-build-common-test</module>
|
||||||
<module>tools/kotlin-maven-plugin</module>
|
<module>tools/kotlin-maven-plugin</module>
|
||||||
|
|
||||||
<module>tools/runtime</module>
|
<module>tools/runtime</module>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<properties>
|
||||||
|
<maven-plugin-anno.version>1.4.1</maven-plugin-anno.version>
|
||||||
|
<maven.version>3.0.4</maven.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-project</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>kotlin-build-common-test</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>Testing utils (for incremental compilation mostly)</description>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-jar</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<configuration>
|
||||||
|
<tasks>
|
||||||
|
<copy file="${kotlin-dist}/kotlinc/lib/kotlin-build-common-test.jar"
|
||||||
|
tofile="${basedir}/target/${project.artifactId}-${project.version}.jar"
|
||||||
|
overwrite="true" verbose="true"/>
|
||||||
|
</tasks>
|
||||||
|
</configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
+25
@@ -55,6 +55,8 @@ val ANNOTATIONS_PLUGIN_NAME = "org.jetbrains.kotlin.kapt"
|
|||||||
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCompile() {
|
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCompile() {
|
||||||
abstract protected val compiler: CLICompiler<T>
|
abstract protected val compiler: CLICompiler<T>
|
||||||
abstract protected fun createBlankArgs(): T
|
abstract protected fun createBlankArgs(): T
|
||||||
|
open protected fun beforeCompileHook(args: T) {
|
||||||
|
}
|
||||||
open protected fun afterCompileHook(args: T) {
|
open protected fun afterCompileHook(args: T) {
|
||||||
}
|
}
|
||||||
abstract protected fun populateTargetSpecificArgs(args: T)
|
abstract protected fun populateTargetSpecificArgs(args: T)
|
||||||
@@ -98,6 +100,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
|
|||||||
populateTargetSpecificArgs(args)
|
populateTargetSpecificArgs(args)
|
||||||
compilerCalled = true
|
compilerCalled = true
|
||||||
val cachesDir = File(project.buildDir, "kotlin-caches")
|
val cachesDir = File(project.buildDir, "kotlin-caches")
|
||||||
|
beforeCompileHook(args)
|
||||||
callCompiler(args, sources, inputs.isIncremental, modified, removed, cachesDir)
|
callCompiler(args, sources, inputs.isIncremental, modified, removed, cachesDir)
|
||||||
afterCompileHook(args)
|
afterCompileHook(args)
|
||||||
}
|
}
|
||||||
@@ -138,6 +141,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
|
|||||||
open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
||||||
override val compiler = K2JVMCompiler()
|
override val compiler = K2JVMCompiler()
|
||||||
override fun createBlankArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
override fun createBlankArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
||||||
|
private val kotlinClassFiles = HashSet<File>()
|
||||||
|
|
||||||
// Should be SourceDirectorySet or File
|
// Should be SourceDirectorySet or File
|
||||||
val srcDirsSources = HashSet<Any>()
|
val srcDirsSources = HashSet<Any>()
|
||||||
@@ -500,6 +504,10 @@ open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
|||||||
|
|
||||||
private fun File.isJavaFile() = extension.equals(JavaFileType.INSTANCE.defaultExtension, ignoreCase = true)
|
private fun File.isJavaFile() = extension.equals(JavaFileType.INSTANCE.defaultExtension, ignoreCase = true)
|
||||||
|
|
||||||
|
override fun beforeCompileHook(args: K2JVMCompilerArguments) {
|
||||||
|
kotlinClassFiles.addAll(listClassFiles(compilerDestinationDir))
|
||||||
|
}
|
||||||
|
|
||||||
override fun afterCompileHook(args: K2JVMCompilerArguments) {
|
override fun afterCompileHook(args: K2JVMCompilerArguments) {
|
||||||
logger.debug("Copying resulting files to classes")
|
logger.debug("Copying resulting files to classes")
|
||||||
|
|
||||||
@@ -508,6 +516,20 @@ open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
|
|||||||
if (outputDirFile.exists()) {
|
if (outputDirFile.exists()) {
|
||||||
FileUtils.copyDirectory(outputDirFile, destinationDir)
|
FileUtils.copyDirectory(outputDirFile, destinationDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinClassFiles.removeAll(listClassFiles(outputDirPath))
|
||||||
|
if (kotlinClassFiles.isNotEmpty()) {
|
||||||
|
// some classes were removed during compilation
|
||||||
|
val filesToRemove = kotlinClassFiles.map {
|
||||||
|
val relativePath = it.relativeTo(outputDirFile).path
|
||||||
|
File(destinationDir, relativePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
val notRemoved = filesToRemove.filter { !it.delete() }
|
||||||
|
if (notRemoved.isNotEmpty()) {
|
||||||
|
logger.kotlinDebug("Could not delete classfiles: $notRemoved")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// override setSource to track source directory sets and files (for generated android folders)
|
// override setSource to track source directory sets and files (for generated android folders)
|
||||||
@@ -679,3 +701,6 @@ internal fun Logger.kotlinInfo(message: String) {
|
|||||||
internal fun Logger.kotlinDebug(message: String) {
|
internal fun Logger.kotlinDebug(message: String) {
|
||||||
this.debug("[KOTLIN] $message")
|
this.debug("[KOTLIN] $message")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun listClassFiles(path: String): Sequence<File> =
|
||||||
|
File(path).walk().filter { it.isFile && it.extension.toLowerCase() == "class" }
|
||||||
|
|||||||
@@ -58,6 +58,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-build-common-test</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -4,10 +4,12 @@ import org.gradle.api.logging.LogLevel
|
|||||||
import org.jetbrains.kotlin.gradle.incremental.BuildStep
|
import org.jetbrains.kotlin.gradle.incremental.BuildStep
|
||||||
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
|
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
|
||||||
import org.jetbrains.kotlin.incremental.testingUtils.TouchPolicy
|
import org.jetbrains.kotlin.incremental.testingUtils.TouchPolicy
|
||||||
|
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
|
||||||
import org.jetbrains.kotlin.incremental.testingUtils.copyTestSources
|
import org.jetbrains.kotlin.incremental.testingUtils.copyTestSources
|
||||||
import org.jetbrains.kotlin.incremental.testingUtils.getModificationsToPerform
|
import org.jetbrains.kotlin.incremental.testingUtils.getModificationsToPerform
|
||||||
import org.junit.Assume
|
import org.junit.Assume
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
|
|
||||||
abstract class BaseIncrementalGradleIT : BaseGradleIT() {
|
abstract class BaseIncrementalGradleIT : BaseGradleIT() {
|
||||||
@@ -55,14 +57,15 @@ abstract class BaseIncrementalGradleIT : BaseGradleIT() {
|
|||||||
println("<--- Expected build log stage: ${if (it.compileSucceeded) "succeeded" else "failed"}: kotlin: ${it.compiledKotlinFiles} java: ${it.compiledJavaFiles}")
|
println("<--- Expected build log stage: ${if (it.compileSucceeded) "succeeded" else "failed"}: kotlin: ${it.compiledKotlinFiles} java: ${it.compiledJavaFiles}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for ((modificationStep, buildLogStep) in modifications.zip(buildLogSteps)) {
|
for ((modificationStep, buildLogStep) in modifications.zip(buildLogSteps)) {
|
||||||
modificationStep.forEach { it.perform(projectDir, mapWorkingToOriginalFile) }
|
modificationStep.forEach { it.perform(projectDir, mapWorkingToOriginalFile) }
|
||||||
buildAndAssertStageResults(buildLogStep, weakTesting = weakTesting)
|
buildAndAssertStageResults(buildLogStep, weakTesting = weakTesting)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rebuildAndCompareOutput(rebuildSucceedExpected = buildLogSteps.last().compileSucceeded)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JpsTestProject.buildAndAssertStageResults(expected: BuildStep, options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
|
private fun JpsTestProject.buildAndAssertStageResults(expected: BuildStep, options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
|
||||||
build("build", options = options) {
|
build("build", options = options) {
|
||||||
if (expected.compileSucceeded) {
|
if (expected.compileSucceeded) {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
@@ -74,6 +77,20 @@ abstract class BaseIncrementalGradleIT : BaseGradleIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun JpsTestProject.rebuildAndCompareOutput(rebuildSucceedExpected: Boolean) {
|
||||||
|
val outDir = File(File(projectDir, "build"), "classes")
|
||||||
|
val incrementalOutDir = File(workingDir, "kotlin-classes-incremental")
|
||||||
|
incrementalOutDir.mkdirs()
|
||||||
|
copyDirRecursively(outDir, incrementalOutDir)
|
||||||
|
|
||||||
|
build("clean", "build") {
|
||||||
|
val rebuildSucceed = resultCode == 0
|
||||||
|
assertEquals(rebuildSucceed, rebuildSucceedExpected, "Rebuild exit code differs from incremental exit code")
|
||||||
|
outDir.mkdirs()
|
||||||
|
assertEqualDirectories(outDir, incrementalOutDir, forgiveExtraFiles = !rebuildSucceed)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isJpsTestProject(projectRoot: File): Boolean = projectRoot.listFiles { f: File -> f.name.endsWith("build.log") }?.any() ?: false
|
fun isJpsTestProject(projectRoot: File): Boolean = projectRoot.listFiles { f: File -> f.name.endsWith("build.log") }?.any() ?: false
|
||||||
|
|||||||
Reference in New Issue
Block a user