Post-review fixes, add errors reporting to test

This commit is contained in:
Simon Ogorodnik
2018-04-03 19:09:27 +03:00
parent 3221900f69
commit c8fbf2d3ac
@@ -22,8 +22,11 @@ import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import java.io.File import java.io.File
import java.io.PrintWriter
import java.io.StringWriter
import kotlin.system.measureNanoTime import kotlin.system.measureNanoTime
class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
@@ -41,11 +44,6 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
rootProjectFile.copyRecursively(tmp) rootProjectFile.copyRecursively(tmp)
tmp.resolve(".idea").deleteRecursively() tmp.resolve(".idea").deleteRecursively()
val inspectionProfilesDir = File(".idea/inspectionProfiles")
rootProjectFile.resolve(inspectionProfilesDir).copyRecursively(
tmp.resolve(inspectionProfilesDir).also { it.parentFile.mkdirs() }
)
(ApplicationManager.getApplication() as ApplicationEx).doNotSave() (ApplicationManager.getApplication() as ApplicationEx).doNotSave()
myProject = ProjectUtil.openOrImport(tmp.path, null, false) myProject = ProjectUtil.openOrImport(tmp.path, null, false)
} }
@@ -65,29 +63,43 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project) profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project)
} }
fun doTest(file: File): Map<String, Long> { data class PerFileTestResult(val perInspection: Map<String, Long>, val totalNs: Long, val errors: List<Throwable>)
class ExceptionWhileInspection(insepctionId: String, cause: Throwable) : RuntimeException(insepctionId, cause)
protected fun doTest(file: File): PerFileTestResult {
val results = mutableMapOf<String, Long>() val results = mutableMapOf<String, Long>()
val vFile = VfsUtil.findFileByIoFile(file, false) ?: return results var totalNs = 0L
val vFile = VfsUtil.findFileByIoFile(file, false) ?: run {
return PerFileTestResult(results, totalNs, listOf(AssertionError("VirtualFile not found for $file")))
}
val psi = PsiManager.getInstance(project) val psi = PsiManager.getInstance(project)
val psiFile = psi.findFile(vFile) ?: return results val psiFile = psi.findFile(vFile) ?: run {
return PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $vFile")))
}
val errors = mutableListOf<Throwable>()
profileTools.forEach { profileTools.forEach {
val tool = it.tool.tool as? LocalInspectionTool ?: return@forEach val localInspectionTool = it.tool.tool as? LocalInspectionTool ?: return@forEach
if (it.tool.language != null && it.tool.language!! !in setOf("kotlin", "UAST")) return@forEach if (it.tool.language !in setOf(null, "kotlin", "UAST")) return@forEach
val result = measureNanoTime { val result = measureNanoTime {
try { try {
tool.analyze(psiFile) localInspectionTool.analyze(psiFile)
} catch (t: Throwable) { } catch (t: Throwable) {
t.printStackTrace() val myEx = ExceptionWhileInspection(it.tool.id, t)
myEx.printStackTrace()
errors += myEx
} }
} }
results[it.tool.id] = result results[it.tool.id] = result
totalNs += result
} }
return results return PerFileTestResult(results, totalNs, errors)
} }
private fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) { private fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) {
@@ -98,9 +110,6 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
} }
fun LocalInspectionTool.analyze(file: PsiFile) { fun LocalInspectionTool.analyze(file: PsiFile) {
file.containingDirectory
if (file.textRange == null) return if (file.textRange == null) return
val holder = ProblemsHolder(InspectionManager.getInstance(file.project), file, false) val holder = ProblemsHolder(InspectionManager.getInstance(file.project), file, false)
@@ -110,18 +119,42 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
} }
inline fun tcSuite(name: String, l: () -> Unit) { inline fun tcSuite(name: String, block: () -> Unit) {
println("##teamcity[testSuiteStarted name='$name']") println("##teamcity[testSuiteStarted name='$name']")
l() block()
println("##teamcity[testSuiteFinished name='$name']") println("##teamcity[testSuiteFinished name='$name']")
} }
inline fun tcTest(name: String, l: () -> Long) { inline fun tcTest(name: String, block: () -> Pair<Long, List<Throwable>>) {
println("##teamcity[testStarted name='$name' captureStandardOutput='true']") println("##teamcity[testStarted name='$name' captureStandardOutput='true']")
val result = l() val (time, errors) = block()
println("##teamcity[testFinished name='$name' duration='$result']") if (errors.isNotEmpty()) {
val detailsWriter = StringWriter()
val errorDetailsPrintWriter = PrintWriter(detailsWriter)
errors.forEach {
it.printStackTrace(errorDetailsPrintWriter)
errorDetailsPrintWriter.println()
}
errorDetailsPrintWriter.close()
val details = detailsWriter.toString()
println("##teamcity[testFailed name='$name' message='Exceptions reported' details='${details.tcEscape()}']")
} else {
println("##teamcity[testFinished name='$name' duration='$time']")
}
} }
fun String.tcEscape(): String {
return this
.replace("|", "||")
.replace("[", "|[")
.replace("]", "|]")
.replace("\r", "|r")
.replace("\n", "|n")
.replace("'", "|'")
}
fun testWholeProjectPerformance() { fun testWholeProjectPerformance() {
val totals = mutableMapOf<String, Long>() val totals = mutableMapOf<String, Long>()
@@ -131,8 +164,6 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
statsOutput.appendln("File, InspectionID, Time") statsOutput.appendln("File, InspectionID, Time")
fun appendInspectionResult(file: String, id: String, nanoTime: Long) { fun appendInspectionResult(file: String, id: String, nanoTime: Long) {
totals.merge(id, nanoTime) { a, b -> a + b }
statsOutput.appendln(buildString { statsOutput.appendln(buildString {
append(file) append(file)
append(", ") append(", ")
@@ -148,12 +179,11 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
}.forEach { }.forEach {
val filePath = it.relativeTo(tmp).path.replace(File.separatorChar, '/') val filePath = it.relativeTo(tmp).path.replace(File.separatorChar, '/')
tcTest(filePath) { tcTest(filePath) {
val resultPerInspection = doTest(it) val result = doTest(it)
resultPerInspection.forEach { (k, v) -> result.perInspection.forEach { (k, v) ->
appendInspectionResult(filePath, k, v) appendInspectionResult(filePath, k, v)
} }
val result = (resultPerInspection.values.sum() * 1e-6).toLong() (result.totalNs * 1e-6).toLong() to result.errors
result
} }
} }
} }
@@ -165,7 +195,7 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
tcSuite("Total") { tcSuite("Total") {
totals.forEach { (k, v) -> totals.forEach { (k, v) ->
tcTest(k) { tcTest(k) {
(v * 1e-6).toLong() (v * 1e-6).toLong() to emptyList()
} }
} }
} }