Create performance test for all inspections

This commit is contained in:
Simon Ogorodnik
2018-03-28 19:08:25 +02:00
parent de9aea6e98
commit 740e6fde35
2 changed files with 166 additions and 5 deletions
+43 -5
View File
@@ -42,6 +42,7 @@ dependencies {
compileOnly(project(":kotlin-daemon-client"))
compileOnly(intellijDep())
compileOnly(commonDep("com.google.code.findbugs", "jsr305"))
compileOnly(intellijPluginDep("IntelliLang"))
@@ -102,24 +103,61 @@ dependencies {
sourceSets {
"main" {
projectDefault()
java.srcDirs("idea-completion/src",
"idea-live-templates/src",
"idea-repl/src")
java.srcDirs(
"idea-completion/src",
"idea-live-templates/src",
"idea-repl/src"
)
resources.srcDirs("idea-repl/src").apply { include("META-INF/**") }
}
"test" {
projectDefault()
java.srcDirs(
"idea-completion/tests",
"idea-live-templates/tests")
"idea-completion/tests",
"idea-live-templates/tests"
)
}
}
val performanceTestCompile by configurations.creating {
extendsFrom(configurations["testCompile"])
}
val performanceTestRuntime by configurations.creating {
extendsFrom(configurations["testRuntime"])
}
val performanceTest by run {
val sourceSets = the<JavaPluginConvention>().sourceSets
sourceSets.creating {
compileClasspath += sourceSets["test"].output
compileClasspath += sourceSets["main"].output
runtimeClasspath += sourceSets["test"].output
runtimeClasspath += sourceSets["main"].output
java.srcDirs("performanceTests")
}
}
projectTest {
dependsOn(":dist")
dependsOn("performanceTest")
workingDir = rootDir
}
projectTest(taskName = "performanceTest") {
dependsOn(":dist")
dependsOn(performanceTest.output)
testClassesDirs = performanceTest.output.classesDirs
classpath = performanceTest.runtimeClasspath
workingDir = rootDir
doFirst {
systemProperty("idea.home.path", intellijRootDir().canonicalPath)
}
}
testsJar {}
classesDirsArtifact()
@@ -0,0 +1,123 @@
/*
* 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.codeInspection.*
import com.intellij.codeInspection.ex.InspectionToolRegistrar
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.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import java.io.File
import kotlin.system.measureNanoTime
class AllKotlinInspectionTest : DaemonAnalyzerTestCase() {
companion object {
private val rootProjectFile = File(".").absoluteFile
}
private val tmp by lazy { createTempDirectory() }
override fun setUpProject() {
println("Copying project to $tmp")
rootProjectFile.copyRecursively(tmp)
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()
myProject = ProjectUtil.openOrImport(tmp.path, null, false)
}
lateinit var profileTools: List<Tools>
override fun setUp() {
super.setUp()
val wrappers = InspectionToolRegistrar.getInstance().createTools().map { it.tool }
enableInspectionTools(*wrappers.toTypedArray())
profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project)
}
fun doTest(file: File): Map<String, Long> {
val results = mutableMapOf<String, Long>()
val vFile = VfsUtil.findFileByIoFile(file, false) ?: return results
val psi = PsiManager.getInstance(project)
val psiFile = psi.findFile(vFile) ?: return results
profileTools.forEach {
val tool = it.tool.tool as? LocalInspectionTool ?: return@forEach
if (it.tool.language != null && it.tool.language!! !in setOf("kotlin", "UAST")) return@forEach
println("##teamcity[testStarted name='${it.tool.id}' captureStandardOutput='true']")
val result = measureNanoTime {
tool.analyze(psiFile)
}
results[it.tool.id] = result
println("##teamcity[testFinished name='${it.tool.id}' duration='${(result * 1e-6).toLong()}']")
}
return results
}
private fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) {
this.accept(visitor)
for (child in this.children) {
child.acceptRecursively(visitor)
}
}
fun LocalInspectionTool.analyze(file: PsiFile) {
if (file.textRange == null) return
val holder = ProblemsHolder(InspectionManager.getInstance(file.project), file, false)
val session = LocalInspectionToolSession(file, file.textRange.startOffset, file.textRange.endOffset)
val visitor = this.buildVisitor(holder, false, session)
file.acceptRecursively(visitor)
}
fun testWholeProjectPerformance() {
val totals = mutableMapOf<String, Long>()
tmp.walkTopDown().filter {
it.extension == "kt" && "testData" !in it.path && "resources" !in it.path
}.forEach {
println("##teamcity[testSuiteStarted name='${it.relativeTo(tmp)}']")
doTest(it).forEach { (k, v) -> totals.merge(k, v) { a, b -> a + b } }
println("##teamcity[testSuiteFinished name='${it.relativeTo(tmp)}']")
}
totals.forEach { (k, v) ->
println("##teamcity[testStarted name='total_$k' captureStandardOutput='true']")
println("##teamcity[testFinished name='total_$k' duration='${(v * 1e-6).toLong()}']")
}
}
}