Extract AllKotlinTest from AllKotlinInspectionTest

(cherry picked from commit 7cb31ee)
This commit is contained in:
Mikhail Glukhikh
2018-04-19 15:35:41 +03:00
committed by Simon Ogorodnik
parent a57a40b5a9
commit 3e2563ad73
2 changed files with 146 additions and 134 deletions
@@ -12,46 +12,17 @@ import com.intellij.codeInspection.LocalInspectionToolSession
import com.intellij.codeInspection.ProblemsHolder import com.intellij.codeInspection.ProblemsHolder
import com.intellij.codeInspection.ex.InspectionToolRegistrar import com.intellij.codeInspection.ex.InspectionToolRegistrar
import com.intellij.codeInspection.ex.Tools import com.intellij.codeInspection.ex.Tools
import com.intellij.ide.impl.ProjectUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationEx
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.profile.codeInspection.ProjectInspectionProfileManager import com.intellij.profile.codeInspection.ProjectInspectionProfileManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager import org.jetbrains.kotlin.idea.refactoring.toPsiFile
import java.io.File import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.io.StringWriter import java.io.StringWriter
import kotlin.system.measureNanoTime import kotlin.system.measureNanoTime
class AllKotlinInspectionTest : AllKotlinTest() {
class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { private lateinit var profileTools: List<Tools>
companion object {
private val rootProjectFile = File(".").absoluteFile
private val statsFile = File("build/stats.csv").absoluteFile
private inline val Long.nsToMs get() = (this / 1e6.toLong())
}
private val tmp by lazy { createTempDirectory() }
override fun setUpProject() {
println("Copying project to $tmp")
rootProjectFile.copyRecursively(tmp)
tmp.resolve(".idea").deleteRecursively()
(ApplicationManager.getApplication() as ApplicationEx).doNotSave()
myProject = ProjectUtil.openOrImport(tmp.path, null, false)
}
lateinit var profileTools: List<Tools>
override fun setUp() { override fun setUp() {
@@ -64,21 +35,15 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project) profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project)
} }
data class PerFileTestResult(val perInspection: Map<String, Long>, val totalNs: Long, val errors: List<Throwable>) class ExceptionWhileInspection(inspectionId: String, cause: Throwable) : RuntimeException(inspectionId, cause)
class ExceptionWhileInspection(insepctionId: String, cause: Throwable) : RuntimeException(insepctionId, cause) override fun doTest(file: File): PerFileTestResult {
protected fun doTest(file: File): PerFileTestResult {
val results = mutableMapOf<String, Long>() val results = mutableMapOf<String, Long>()
var totalNs = 0L 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 psiFile = file.toPsiFile() ?: run {
val psiFile = psi.findFile(vFile) ?: run { return PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $file")))
return PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $vFile")))
} }
val errors = mutableListOf<Throwable>() val errors = mutableListOf<Throwable>()
@@ -103,14 +68,7 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
return PerFileTestResult(results, totalNs, errors) return PerFileTestResult(results, totalNs, errors)
} }
private fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) { private fun LocalInspectionTool.analyze(file: PsiFile) {
this.accept(visitor)
for (child in this.children) {
child.acceptRecursively(visitor)
}
}
fun LocalInspectionTool.analyze(file: PsiFile) {
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)
@@ -119,88 +77,4 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
file.acceptRecursively(visitor) file.acceptRecursively(visitor)
} }
inline fun tcSuite(name: String, block: () -> Unit) {
println("##teamcity[testSuiteStarted name='$name']")
block()
println("##teamcity[testSuiteFinished name='$name']")
}
inline fun tcTest(name: String, block: () -> Pair<Long, List<Throwable>>) {
println("##teamcity[testStarted name='$name' captureStandardOutput='true']")
val (time, errors) = block()
if (errors.isNotEmpty()) {
val detailsWriter = StringWriter()
PrintWriter(detailsWriter).use { errorDetailsPrintWriter ->
errors.forEach {
it.printStackTrace(errorDetailsPrintWriter)
errorDetailsPrintWriter.println()
}
}
val details = detailsWriter.toString()
println("##teamcity[testFailed name='$name' message='Exceptions reported' details='${details.tcEscape()}']")
}
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() {
val totals = mutableMapOf<String, Long>()
val statsOutput = statsFile.bufferedWriter()
statsOutput.appendln("File, InspectionID, Time")
fun appendInspectionResult(file: String, id: String, nanoTime: Long) {
totals.merge(id, nanoTime) { a, b -> a + b }
statsOutput.appendln(buildString {
append(file)
append(", ")
append(id)
append(", ")
append(nanoTime.nsToMs)
})
}
tcSuite("SumPerFile") {
tmp.walkTopDown().filter {
it.extension == "kt" && "testdata" !in it.path.toLowerCase() && "resources" !in it.path
}.forEach {
val filePath = it.relativeTo(tmp).path.replace(File.separatorChar, '/')
tcTest(filePath) {
val result = doTest(it)
result.perInspection.forEach { (k, v) ->
appendInspectionResult(filePath, k, v)
}
result.totalNs.nsToMs to result.errors
}
}
}
statsOutput.flush()
statsOutput.close()
tcSuite("Total") {
totals.forEach { (k, v) ->
tcTest(k) {
v.nsToMs to emptyList()
}
}
}
}
} }
@@ -0,0 +1,138 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.perf
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase
import com.intellij.ide.impl.ProjectUtil
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationEx
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import java.io.File
import java.io.PrintWriter
import java.io.StringWriter
abstract class AllKotlinTest : DaemonAnalyzerTestCase() {
private val rootProjectFile: File = File(".").absoluteFile
private val statsFile: File = File("build/stats.csv").absoluteFile
private val tmp by lazy { createTempDirectory() }
override fun setUpProject() {
println("Copying project to $tmp")
rootProjectFile.copyRecursively(tmp)
tmp.resolve(".idea").deleteRecursively()
(ApplicationManager.getApplication() as ApplicationEx).doNotSave()
myProject = ProjectUtil.openOrImport(tmp.path, null, false)
}
data class PerFileTestResult(val perProcess: Map<String, Long>, val totalNs: Long, val errors: List<Throwable>)
protected abstract fun doTest(file: File): PerFileTestResult
protected fun File.toPsiFile(): PsiFile? {
val vFile = VfsUtil.findFileByIoFile(this, false) ?: return null
val psi = PsiManager.getInstance(project)
return psi.findFile(vFile)
}
fun testWholeProjectPerformance() {
val totals = mutableMapOf<String, Long>()
val statsOutput = statsFile.bufferedWriter()
statsOutput.appendln("File, InspectionID, Time")
fun appendInspectionResult(file: String, id: String, nanoTime: Long) {
totals.merge(id, nanoTime) { a, b -> a + b }
statsOutput.appendln(buildString {
append(file)
append(", ")
append(id)
append(", ")
append((nanoTime * 1e-6).toLong())
})
}
tcSuite("SumPerFile") {
tmp.walkTopDown().filter {
it.extension == "kt" && "testdata" !in it.path.toLowerCase() && "resources" !in it.path
}.forEach {
val filePath = it.relativeTo(tmp).path.replace(File.separatorChar, '/')
tcTest(filePath) {
val result = doTest(it)
result.perProcess.forEach { (k, v) ->
appendInspectionResult(filePath, k, v)
}
(result.totalNs * 1e-6).toLong() to result.errors
}
}
}
statsOutput.flush()
statsOutput.close()
tcSuite("Total") {
totals.forEach { (k, v) ->
tcTest(k) {
(v * 1e-6).toLong() to emptyList()
}
}
}
}
private inline fun tcSuite(name: String, block: () -> Unit) {
println("##teamcity[testSuiteStarted name='$name']")
block()
println("##teamcity[testSuiteFinished name='$name']")
}
private inline fun tcTest(name: String, block: () -> Pair<Long, List<Throwable>>) {
println("##teamcity[testStarted name='$name' captureStandardOutput='true']")
val (time, errors) = block()
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()}']")
}
println("##teamcity[testFinished name='$name' duration='$time']")
}
private fun String.tcEscape(): String {
return this
.replace("|", "||")
.replace("[", "|[")
.replace("]", "|]")
.replace("\r", "|r")
.replace("\n", "|n")
.replace("'", "|'")
}
protected fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) {
this.accept(visitor)
for (child in this.children) {
child.acceptRecursively(visitor)
}
}
}