Checking incremental cache dump after make. Comparing it with dump after rebuild.

Original commit: 602642715c
This commit is contained in:
Evgeny Gerashchenko
2015-02-03 19:43:07 +03:00
parent 143ab5dad2
commit 75e5ee2fbf
2 changed files with 108 additions and 27 deletions
@@ -47,6 +47,8 @@ import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.storage.BuildDataPaths import org.jetbrains.jps.builders.storage.BuildDataPaths
import com.intellij.util.io.BooleanDataDescriptor import com.intellij.util.io.BooleanDataDescriptor
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.utils.Printer
val INLINE_ANNOTATION_DESC = "Lkotlin/inline;" val INLINE_ANNOTATION_DESC = "Lkotlin/inline;"
@@ -100,6 +102,11 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
private val cacheFormatVersion = CacheFormatVersion(targetDataRoot) private val cacheFormatVersion = CacheFormatVersion(targetDataRoot)
TestOnly
public fun dump(): String {
return maps.map { it.dump() }.join("\n\n")
}
public fun saveFileToCache(sourceFiles: Collection<File>, classFile: File): RecompilationDecision { public fun saveFileToCache(sourceFiles: Collection<File>, classFile: File): RecompilationDecision {
if (classFile.extension.toLowerCase() != "class") return DO_NOTHING if (classFile.extension.toLowerCase() != "class") return DO_NOTHING
@@ -231,6 +238,26 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
public fun close() { public fun close() {
storage.close() storage.close()
} }
TestOnly
public fun dump(): String {
return with(StringBuilder()) {
with(Printer(this)) {
println(this@BasicMap.javaClass.getSimpleName())
pushIndent()
for (key in storage.getAllKeysWithExistingMapping().sort()) {
println("$key -> ${dumpValue(storage[key])}")
}
popIndent()
}
this
}.toString()
}
protected abstract fun dumpValue(value: V): String
} }
private abstract class ClassFileBasedMap<V> : BasicMap<V>() { private abstract class ClassFileBasedMap<V> : BasicMap<V>() {
@@ -275,6 +302,10 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
public fun get(className: JvmClassName): ByteArray? { public fun get(className: JvmClassName): ByteArray? {
return storage[className.getInternalName()] return storage[className.getInternalName()]
} }
override fun dumpValue(value: ByteArray): String {
return java.lang.Long.toHexString(value.md5())
}
} }
private inner class ConstantsMap : ClassFileBasedMap<Map<String, Any>>() { private inner class ConstantsMap : ClassFileBasedMap<Map<String, Any>>() {
@@ -319,6 +350,19 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
} }
return true return true
} }
override fun dumpValue(value: Map<String, Any>): String {
return StringBuilder {
append("{")
for (key in value.keySet().sort()) {
if (length() != 1) {
append(", ")
}
append("$key -> ${value[key]}")
}
append("}")
}.toString()
}
} }
private object ConstantsMapExternalizer : DataExternalizer<Map<String, Any>> { private object ConstantsMapExternalizer : DataExternalizer<Map<String, Any>> {
@@ -437,6 +481,19 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
} }
return true return true
} }
override fun dumpValue(value: Map<String, Long>): String {
return StringBuilder {
append("{")
for (key in value.keySet().sort()) {
if (length() != 1) {
append(", ")
}
append("$key -> ${java.lang.Long.toHexString(value[key]!!)}")
}
append("}")
}.toString()
}
} }
private object InlineFunctionsMapExternalizer : DataExternalizer<Map<String, Long>> { private object InlineFunctionsMapExternalizer : DataExternalizer<Map<String, Long>> {
@@ -484,6 +541,8 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
public fun get(sourceFile: File): String? { public fun get(sourceFile: File): String? {
return storage[sourceFile.getAbsolutePath()] return storage[sourceFile.getAbsolutePath()]
} }
override fun dumpValue(value: String) = value
} }
private inner class RemovedPackagePartMap : BasicMap<Boolean>() { private inner class RemovedPackagePartMap : BasicMap<Boolean>() {
@@ -504,6 +563,8 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
public fun clear() { public fun clear() {
storage.getAllKeysWithExistingMapping().forEach { storage.remove(it) } storage.getAllKeysWithExistingMapping().forEach { storage.remove(it) }
} }
override fun dumpValue(value: Boolean) = ""
} }
enum class RecompilationDecision { enum class RecompilationDecision {
@@ -36,9 +36,11 @@ import org.jetbrains.jps.incremental.messages.BuildMessage
import kotlin.test.assertFalse import kotlin.test.assertFalse
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.test.assertEquals import kotlin.test.assertEquals
import org.jetbrains.jps.model.java.JpsJavaDependencyExtension
import org.jetbrains.jps.model.JpsModuleRootModificationUtil import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.jps.cmdline.ProjectDescriptor
import junit.framework.TestCase
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
class object { class object {
@@ -65,7 +67,7 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
protected open val customTest: Boolean protected open val customTest: Boolean
get() = false get() = false
fun buildGetLog(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): String { fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): MakeResult {
val workDirPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) val workDirPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath())
val logger = MyLogger(workDirPath) val logger = MyLogger(workDirPath)
val descriptor = createProjectDescriptor(BuildLoggingManager(logger)) val descriptor = createProjectDescriptor(BuildLoggingManager(logger))
@@ -78,10 +80,10 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
.map { it.getMessageText() } .map { it.getMessageText() }
.map { it.replaceAll("^.+:\\d+:\\s+", "").trim() } .map { it.replaceAll("^.+:\\d+:\\s+", "").trim() }
.joinToString("\n") .joinToString("\n")
return logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n" return MakeResult(logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n", true, null)
} }
else { else {
return logger.log return MakeResult(logger.log, false, createMappingsDump(descriptor))
} }
} finally { } finally {
descriptor.release() descriptor.release()
@@ -89,16 +91,16 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
} }
private fun initialMake() { private fun initialMake() {
val log = buildGetLog() val makeResult = build()
assertFalse(COMPILATION_FAILED in log, "Initial make failed:\n$log") assertFalse(makeResult.makeFailed, "Initial make failed:\n$makeResult")
} }
private fun make(): String { private fun make(): MakeResult {
return buildGetLog() return build()
} }
private fun rebuild(): String { private fun rebuild(): MakeResult {
return buildGetLog(CompileScopeTestBuilder.rebuild().allModules()) return build(CompileScopeTestBuilder.rebuild().allModules())
} }
private fun getModificationsToPerform(moduleNames: Collection<String>?): List<List<Modification>> { private fun getModificationsToPerform(moduleNames: Collection<String>?): List<List<Modification>> {
@@ -160,24 +162,28 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
} }
} }
private fun rebuildAndCheckOutput(lastMakeFailed: Boolean) { private fun rebuildAndCheckOutput(makeOverallResult: MakeResult) {
val outDir = File(getAbsolutePath("out")) val outDir = File(getAbsolutePath("out"))
val outAfterMake = File(getAbsolutePath("out-after-make")) val outAfterMake = File(getAbsolutePath("out-after-make"))
FileUtil.copyDir(outDir, outAfterMake) FileUtil.copyDir(outDir, outAfterMake)
val rebuildLog = rebuild() val rebuildResult = rebuild()
val rebuildFailed = rebuildLog.contains(COMPILATION_FAILED) assertEquals(rebuildResult.makeFailed, makeOverallResult.makeFailed,
assertEquals(rebuildFailed, lastMakeFailed, "Rebuild failed: $rebuildFailed, last make failed: $lastMakeFailed. Rebuild log: $rebuildLog") "Rebuild failed: ${rebuildResult.makeFailed}, last make failed: ${makeOverallResult.makeFailed}. Rebuild result: $rebuildResult")
assertEqualDirectories(outDir, outAfterMake, lastMakeFailed) assertEqualDirectories(outDir, outAfterMake, makeOverallResult.makeFailed)
if (!makeOverallResult.makeFailed) {
TestCase.assertEquals(rebuildResult.mappingsDump, makeOverallResult.mappingsDump)
}
FileUtil.delete(outAfterMake) FileUtil.delete(outAfterMake)
} }
private fun clearCachesRebuildAndCheckOutput(lastMakeFailed: Boolean) { private fun clearCachesRebuildAndCheckOutput(makeOverallResult: MakeResult) {
FileUtil.delete(BuildDataPathsImpl(myDataStorageRoot).getDataStorageRoot()!!) FileUtil.delete(BuildDataPathsImpl(myDataStorageRoot).getDataStorageRoot()!!)
rebuildAndCheckOutput(lastMakeFailed) rebuildAndCheckOutput(makeOverallResult)
} }
private fun readModuleDependencies(): Map<String, List<String>>? { private fun readModuleDependencies(): Map<String, List<String>>? {
@@ -207,31 +213,45 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
val moduleNames = configureModules() val moduleNames = configureModules()
initialMake() initialMake()
val (log, lastMakeFailed) = performModificationsAndMake(moduleNames) val makeOverallResult = performModificationsAndMake(moduleNames)
UsefulTestCase.assertSameLinesWithFile(File(testDataDir, "build.log").getAbsolutePath(), log) UsefulTestCase.assertSameLinesWithFile(File(testDataDir, "build.log").getAbsolutePath(), makeOverallResult.log)
rebuildAndCheckOutput(lastMakeFailed) rebuildAndCheckOutput(makeOverallResult)
clearCachesRebuildAndCheckOutput(lastMakeFailed) clearCachesRebuildAndCheckOutput(makeOverallResult)
} }
private fun createMappingsDump(project: ProjectDescriptor) =
createKotlinIncrementalCacheDump(project)
private data class MakeLogAndFailureFlag(val log: String, val makeFailed: Boolean) private fun createKotlinIncrementalCacheDump(project: ProjectDescriptor): String {
return StringBuilder {
for (target in project.getBuildTargetIndex().getAllTargets().sortBy { it.getPresentableName() }) {
append("<target $target>\n")
append(project.dataManager.getKotlinCache(target).dump())
append("</target $target>\n\n\n")
}
}.toString()
}
private fun performModificationsAndMake(moduleNames: Set<String>?): MakeLogAndFailureFlag { private data class MakeResult(val log: String, val makeFailed: Boolean, val mappingsDump: String?)
private fun performModificationsAndMake(moduleNames: Set<String>?): MakeResult {
val logs = ArrayList<String>() val logs = ArrayList<String>()
val modifications = getModificationsToPerform(moduleNames) val modifications = getModificationsToPerform(moduleNames)
var lastCompilationFailed = false var lastCompilationFailed = false
var lastMappingsDump: String? = null
for (step in modifications) { for (step in modifications) {
step.forEach { it.perform(workDir) } step.forEach { it.perform(workDir) }
performAdditionalModifications() performAdditionalModifications()
val log = make() val makeResult = make()
lastCompilationFailed = log.contains(COMPILATION_FAILED) logs.add(makeResult.log)
logs.add(log) lastCompilationFailed = makeResult.makeFailed
lastMappingsDump = makeResult.mappingsDump
} }
return MakeLogAndFailureFlag(logs.join("\n\n"), lastCompilationFailed) return MakeResult(logs.join("\n\n"), lastCompilationFailed, lastMappingsDump)
} }
protected open fun performAdditionalModifications() { protected open fun performAdditionalModifications() {