From 3e2563ad73e3c968eb902379fedc41eada95f0c0 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 19 Apr 2018 15:35:41 +0300 Subject: [PATCH] Extract AllKotlinTest from AllKotlinInspectionTest (cherry picked from commit 7cb31ee) --- .../idea/perf/AllKotlinInspectionTest.kt | 142 +----------------- .../kotlin/idea/perf/AllKotlinTest.kt | 138 +++++++++++++++++ 2 files changed, 146 insertions(+), 134 deletions(-) create mode 100644 idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinTest.kt diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinInspectionTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinInspectionTest.kt index 47b39ba8c90..fcbe960f3f0 100644 --- a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinInspectionTest.kt +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinInspectionTest.kt @@ -12,46 +12,17 @@ import com.intellij.codeInspection.LocalInspectionToolSession import com.intellij.codeInspection.ProblemsHolder 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 org.jetbrains.kotlin.idea.refactoring.toPsiFile import java.io.File import java.io.PrintWriter import java.io.StringWriter import kotlin.system.measureNanoTime +class AllKotlinInspectionTest : AllKotlinTest() { -class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { - - - 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 - + private lateinit var profileTools: List override fun setUp() { @@ -64,21 +35,15 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { profileTools = ProjectInspectionProfileManager.getInstance(project).currentProfile.getAllEnabledInspectionTools(project) } - data class PerFileTestResult(val perInspection: Map, val totalNs: Long, val errors: List) + class ExceptionWhileInspection(inspectionId: String, cause: Throwable) : RuntimeException(inspectionId, cause) - class ExceptionWhileInspection(insepctionId: String, cause: Throwable) : RuntimeException(insepctionId, cause) - - protected fun doTest(file: File): PerFileTestResult { + override fun doTest(file: File): PerFileTestResult { val results = mutableMapOf() 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 = psi.findFile(vFile) ?: run { - return PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $vFile"))) + val psiFile = file.toPsiFile() ?: run { + return PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $file"))) } val errors = mutableListOf() @@ -103,14 +68,7 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { return PerFileTestResult(results, totalNs, errors) } - private fun PsiElement.acceptRecursively(visitor: PsiElementVisitor) { - this.accept(visitor) - for (child in this.children) { - child.acceptRecursively(visitor) - } - } - - fun LocalInspectionTool.analyze(file: PsiFile) { + private fun LocalInspectionTool.analyze(file: PsiFile) { if (file.textRange == null) return val holder = ProblemsHolder(InspectionManager.getInstance(file.project), file, false) @@ -119,88 +77,4 @@ class AllKotlinInspectionTest : DaemonAnalyzerTestCase() { 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>) { - 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() - - 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() - } - } - } - - } - } \ No newline at end of file diff --git a/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinTest.kt b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinTest.kt new file mode 100644 index 00000000000..88c7c7c6acc --- /dev/null +++ b/idea/performanceTests/org/jetbrains/kotlin/idea/perf/AllKotlinTest.kt @@ -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, val totalNs: Long, val errors: List) + + 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() + + 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>) { + 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) + } + } + +} \ No newline at end of file