Reuse incremental test modification utils from build-common

KT-8487
This commit is contained in:
Alexey Tsvetkov
2016-02-11 16:19:42 +03:00
parent 8df209b436
commit df157f9db3
2 changed files with 27 additions and 203 deletions
@@ -1,80 +1,37 @@
package org.jetbrains.kotlin.gradle
import com.google.common.io.Files
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.copyTestSources
import org.jetbrains.kotlin.incremental.testingUtils.getModificationsToPerform
import org.junit.Assume
import java.io.File
import java.util.*
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
abstract class BaseIncrementalGradleIT : BaseGradleIT() {
open inner class IncrementalTestProject(name: String, wrapperVersion: String = "2.4", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(name, wrapperVersion, minLogLevel) {
var modificationStage: Int = 1
}
inner class JpsTestProject(val resourcesBase: File, val relPath: String, wrapperVersion: String = "1.6", minLogLevel: LogLevel = LogLevel.DEBUG) : IncrementalTestProject(File(relPath).name, wrapperVersion, minLogLevel) {
inner class JpsTestProject(val resourcesBase: File, val relPath: String, wrapperVersion: String = "1.6", minLogLevel: LogLevel = LogLevel.DEBUG) : Project(File(relPath).name, wrapperVersion, minLogLevel) {
override val resourcesRoot = File(resourcesBase, relPath)
val mapWorkingToOriginalFile = hashMapOf<File, File>()
override fun setupWorkingDir() {
val srcDir = File(projectDir, "src")
srcDir.mkdirs()
resourcesRoot.walk()
.filter { it.isFile && (it.name.endsWith(".kt") || it.name.endsWith(".java")) }
.forEach { Files.copy(it, File(srcDir, it.name)) }
val sourceMapping = copyTestSources(resourcesRoot, srcDir, filePrefix = "")
mapWorkingToOriginalFile.putAll(sourceMapping)
copyDirRecursively(File(resourcesRootFile, "GradleWrapper-$wrapperVersion"), projectDir)
copyDirRecursively(File(resourcesRootFile, "incrementalGradleProject"), projectDir)
}
}
fun IncrementalTestProject.modify(runStage: Int? = null) {
// TODO: multimodule support
val projectSrcDir = File(File(workingDir, projectName), "src")
assertTrue(projectSrcDir.exists())
val actualStage = runStage ?: modificationStage
println("<--- Modify stage: ${runStage?.toString() ?: "single"}")
fun resource2project(f: File) = File(projectSrcDir, f.toRelativeString(resourcesRoot))
resourcesRoot.walk().filter { it.isFile }.forEach {
val nameParts = it.name.split(".")
if (nameParts.size > 2) {
val (fileStage, hasStage) = nameParts.last().toIntOr(0)
if (!hasStage || fileStage == actualStage) {
val orig = File(resource2project(it.parentFile), nameParts.dropLast(if (hasStage) 2 else 1).joinToString("."))
when (if (hasStage) nameParts[nameParts.size - 2] else nameParts.last()) {
"touch" -> {
assert(orig.exists())
orig.setLastModified(Date().time)
println("<--- Modify: touch $orig")
}
"new" -> {
it.copyTo(orig, overwrite = true)
orig.setLastModified(Date().time)
println("<--- Modify: new $orig from $it")
}
"delete" -> {
assert(orig.exists())
orig.delete()
println("<--- Modify: delete $orig")
}
}
}
}
fun JpsTestProject.performAndAssertBuildStages(options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
// TODO: support multimodule tests
if (resourcesRoot.walk().filter { it.name.equals("dependencies.txt", ignoreCase = true) }.any()) {
Assume.assumeTrue("multimodule tests are not supported yet", false)
}
modificationStage = actualStage + 1
}
fun IncrementalTestProject.performAndAssertBuildStages(options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
val checkKnown = testIsKnownJpsTestProject(resourcesRoot)
Assume.assumeTrue(checkKnown.second ?: "", checkKnown.first)
build("build", options = options) {
assertSuccessful()
assertReportExists()
@@ -83,27 +40,29 @@ abstract class BaseIncrementalGradleIT : BaseGradleIT() {
val buildLogFile = resourcesRoot.listFiles { f: File -> f.name.endsWith("build.log") }?.sortedBy { it.length() }?.firstOrNull()
assertNotNull(buildLogFile, "*build.log file not found" )
val buildLog = parseTestBuildLog(buildLogFile!!)
assertTrue(buildLog.any())
val buildLogSteps = parseTestBuildLog(buildLogFile!!)
val modifications = getModificationsToPerform(resourcesRoot,
moduleNames = null,
allowNoFilesWithSuffixInTestData = false,
touchPolicy = TouchPolicy.CHECKSUM)
println("<--- Build log size: ${buildLog.size}")
buildLog.forEach {
println("<--- Build log stage: ${if (it.compileSucceeded) "succeeded" else "failed"}: kotlin: ${it.compiledKotlinFiles} java: ${it.compiledJavaFiles}")
assert(modifications.size == buildLogSteps.size) {
"Modifications count (${modifications.size}) != expected build log steps count (${buildLogSteps.size})"
}
if (buildLog.size == 1) {
modify()
buildAndAssertStageResults(buildLog.first(), weakTesting = weakTesting)
println("<--- Expected build log size: ${buildLogSteps.size}")
buildLogSteps.forEach {
println("<--- Expected build log stage: ${if (it.compileSucceeded) "succeeded" else "failed"}: kotlin: ${it.compiledKotlinFiles} java: ${it.compiledJavaFiles}")
}
else {
buildLog.forEachIndexed { stage, stageResults ->
modify(stage + 1)
buildAndAssertStageResults(stageResults, weakTesting = weakTesting)
}
for ((modificationStep, buildLogStep) in modifications.zip(buildLogSteps)) {
modificationStep.forEach { it.perform(projectDir, mapWorkingToOriginalFile) }
buildAndAssertStageResults(buildLogStep, weakTesting = weakTesting)
}
}
fun IncrementalTestProject.buildAndAssertStageResults(expected: BuildStep, options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
fun JpsTestProject.buildAndAssertStageResults(expected: BuildStep, options: BuildOptions = defaultBuildOptions(), weakTesting: Boolean = false) {
build("build", options = options) {
if (expected.compileSucceeded) {
assertSuccessful()
@@ -117,43 +76,6 @@ abstract class BaseIncrementalGradleIT : BaseGradleIT() {
}
}
private val supportedSourceExtensions = arrayListOf("kt", "java")
private val supportedModifyExtensions = arrayListOf("new", "delete")
private val unsupportedModifyExtensions = arrayListOf("touch")
private fun String.toIntOr(defaultVal: Int): Pair<Int, Boolean> {
try {
return Pair(toInt(), true)
}
catch (e: NumberFormatException) {
return Pair(defaultVal, false)
}
}
fun isJpsTestProject(projectRoot: File): Boolean = projectRoot.listFiles { f: File -> f.name.endsWith("build.log") }?.any() ?: false
fun testIsKnownJpsTestProject(projectRoot: File): Pair<Boolean, String?> {
var hasKnownSources = false
projectRoot.walk().filter { it.isFile }.forEach {
if (it.name.equals("dependencies.txt", ignoreCase = true))
return@testIsKnownJpsTestProject Pair(false, "multimodule tests are not supported yet")
val nameParts = it.name.split(".")
if (nameParts.size > 1) {
val (fileStage, hasStage) = nameParts.last().toIntOr(0)
val modifyExt = nameParts[nameParts.size - (if (hasStage) 2 else 1)]
val ext = nameParts[nameParts.size - (if (hasStage) 3 else 2)]
if (modifyExt in unsupportedModifyExtensions)
return@testIsKnownJpsTestProject Pair(false, "unsupported modification extension ${it.name}")
if (modifyExt in supportedModifyExtensions && ext !in supportedSourceExtensions)
return@testIsKnownJpsTestProject Pair(false, "unknown staged file ${it.name}")
}
if (!hasKnownSources && it.extension in supportedSourceExtensions) {
hasKnownSources = true
}
}
return if (hasKnownSources) Pair(true, null)
else Pair(false, "no known sources found")
}
@@ -1,98 +0,0 @@
package org.jetbrains.kotlin.gradle
import org.junit.Test
import java.io.File
class KotlinGradleIncrementalFromJpsIT(): BaseIncrementalGradleIT() {
companion object {
val jpsResourcesPath = File("../../../jps-plugin/testData/incremental")
}
override fun defaultBuildOptions(): BuildOptions = BuildOptions(withDaemon = true)
@Test
fun testClassSignatureChanged() {
val project = JpsTestProject(jpsResourcesPath, "pureKotlin/classSignatureChanged", "2.4")
project.build("build") {
assertSuccessful()
assertReportExists()
assertCompiledKotlinSources("src/class.kt", "src/usage.kt")
}
project.modify()
project.build("build") {
assertSuccessful()
assertCompiledKotlinSources("src/class.kt", "src/usage.kt")
}
}
@Test
fun testKotlinInJavaFunRenamed() {
val project = JpsTestProject(jpsResourcesPath, "withJava/kotlinUsedInJava/funRenamed", "2.4")
project.build("build") {
assertSuccessful()
assertReportExists()
assertCompiledKotlinSources("src/fun.kt")
assertCompiledJavaSources("src/WillBeUnresolved.java")
}
project.modify()
project.build("build") {
assertCompiledKotlinSources("src/fun.kt")
assertFailed()
}
}
@Test
fun testJavaInKotlinChangeSignature() {
val project = JpsTestProject(jpsResourcesPath, "withJava/javaUsedInKotlin/changeSignature", "2.4")
project.build("build") {
assertSuccessful()
assertReportExists()
assertCompiledKotlinSources("src/usage.kt")
assertCompiledJavaSources("src/JavaClass.java")
}
project.modify()
project.build("build") {
assertSuccessful()
assertCompiledKotlinSources("src/usage.kt")
assertCompiledJavaSources("src/JavaClass.java")
}
}
@Test
fun testClassSignatureChangedAuto() {
val project = JpsTestProject(jpsResourcesPath, "pureKotlin/classSignatureChanged", "2.4")
project.performAndAssertBuildStages()
}
@Test
fun testAnnotationListChanged() {
val project = JpsTestProject(jpsResourcesPath, "classHierarchyAffected/annotationListChanged", "2.4")
project.performAndAssertBuildStages()
}
@Test
fun testClassBecameFinal() {
val project = JpsTestProject(jpsResourcesPath, "classHierarchyAffected/classBecameFinal", "2.4")
project.performAndAssertBuildStages()
}
@Test
fun testSupertypesListChanged() {
val project = JpsTestProject(jpsResourcesPath, "classHierarchyAffected/supertypesListChanged", "2.4")
project.performAndAssertBuildStages()
}
}