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()
|
||||
|
||||
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())
|
||||
|
||||
@@ -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>
|
||||
+25
@@ -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>
|
||||
|
||||
|
||||
|
||||
+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.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
|
||||
|
||||
Reference in New Issue
Block a user