Rebuild and compare output class files in gradle incremental tests

KT-8487
This commit is contained in:
Alexey Tsvetkov
2016-02-16 22:50:16 +03:00
parent 9e3284ff2a
commit be44db7bd3
6 changed files with 105 additions and 5 deletions
@@ -82,13 +82,15 @@ private fun getDirectoryString(dir: File, interestingPaths: List<String>): Strin
p.pushIndent()
val listFiles = dir.listFiles()
assertNotNull(listFiles)
assertNotNull("$dir does not exist", listFiles)
val children = listFiles!!.sortedWith(compareBy({ it.isDirectory }, { it.name }))
for (child in children) {
if (child.isDirectory) {
p.println(child.name)
addDirContent(child)
if ((child.list()?.isNotEmpty() ?: false)) {
p.println(child.name)
addDirContent(child)
}
}
else {
p.println(child.name, " ", child.hash())
+1
View File
@@ -74,6 +74,7 @@
<module>tools/kotlin-compiler</module>
<module>tools/kotlin-compiler-embeddable</module>
<module>tools/kotlin-build-common</module>
<module>tools/kotlin-build-common-test</module>
<module>tools/kotlin-maven-plugin</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>
@@ -55,6 +55,8 @@ val ANNOTATIONS_PLUGIN_NAME = "org.jetbrains.kotlin.kapt"
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCompile() {
abstract protected val compiler: CLICompiler<T>
abstract protected fun createBlankArgs(): T
open protected fun beforeCompileHook(args: T) {
}
open protected fun afterCompileHook(args: T) {
}
abstract protected fun populateTargetSpecificArgs(args: T)
@@ -98,6 +100,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
populateTargetSpecificArgs(args)
compilerCalled = true
val cachesDir = File(project.buildDir, "kotlin-caches")
beforeCompileHook(args)
callCompiler(args, sources, inputs.isIncremental, modified, removed, cachesDir)
afterCompileHook(args)
}
@@ -138,6 +141,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractCo
open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
override val compiler = K2JVMCompiler()
override fun createBlankArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
private val kotlinClassFiles = HashSet<File>()
// Should be SourceDirectorySet or File
val srcDirsSources = HashSet<Any>()
@@ -500,6 +504,10 @@ open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
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) {
logger.debug("Copying resulting files to classes")
@@ -508,6 +516,20 @@ open class KotlinCompile() : AbstractKotlinCompile<K2JVMCompilerArguments>() {
if (outputDirFile.exists()) {
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)
@@ -679,3 +701,6 @@ internal fun Logger.kotlinInfo(message: String) {
internal fun Logger.kotlinDebug(message: String) {
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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-build-common-test</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -4,10 +4,12 @@ import org.gradle.api.logging.LogLevel
import org.jetbrains.kotlin.gradle.incremental.BuildStep
import org.jetbrains.kotlin.gradle.incremental.parseTestBuildLog
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.getModificationsToPerform
import org.junit.Assume
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
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}")
}
for ((modificationStep, buildLogStep) in modifications.zip(buildLogSteps)) {
modificationStep.forEach { it.perform(projectDir, mapWorkingToOriginalFile) }
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) {
if (expected.compileSucceeded) {
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