(UnusedSymbolInspection) Added support for typing per inspection tests

relates to #KT-38653
This commit is contained in:
Vladimir Ilmov
2020-05-17 16:31:46 +02:00
parent 1f1790d60e
commit de790a3e3b
9 changed files with 111 additions and 25 deletions
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.impl.HighlightInfo
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.kotlin.idea.perf.util.ExternalProject
import org.jetbrains.kotlin.idea.perf.util.lastPathSegment
import org.jetbrains.kotlin.idea.perf.util.suite
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
import org.junit.runner.RunWith
/**
* Run the only specified exceptions on the selected files in Kotling project.
* Used for 'The Kotlin sources: kt files heavy inspections' graph.
* @TODO Should be run before typing tests as the testing project becomes unusable afterwards.
*/
@RunWith(JUnit3RunnerWithInners::class)
class AHeavyInspectionsPerformanceTest : UsefulTestCase() {
val listOfFiles = arrayOf(
"libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt",
"idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/PsiPrecedences.kt",
"compiler/psi/src/org/jetbrains/kotlin/psi/KtElement.kt",
"compiler/psi/src/org/jetbrains/kotlin/psi/KtFile.kt",
"compiler/psi/src/org/jetbrains/kotlin/psi/KtImportInfo.kt"
)
val listOfInspections = arrayOf(
"UnusedSymbol",
"MemberVisibilityCanBePrivate"
)
fun testLocalInspection() {
suite {
app {
project(ExternalProject.KOTLIN_GRADLE) {
for (inspection in listOfInspections) {
enableSingleInspection(inspection)
for (file in listOfFiles) {
val editorFile = editor(file)
measure<List<HighlightInfo>>(inspection, file.lastPathSegment()) {
test = {
highlight(editorFile)
}
}
}
}
}
}
}
}
}
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.idea.perf
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerConfig
class PerfTestBuilder<SV, TV> {
private lateinit var stats: Stats
private lateinit var name: String
@@ -15,6 +17,7 @@ class PerfTestBuilder<SV, TV> {
private var tearDown: (TestData<SV, TV>) -> Unit = { }
private var profilerEnabled: Boolean = false
private var checkStability: Boolean = true
private var profilerConfig: ProfilerConfig = ProfilerConfig()
internal fun run() {
stats.perfTest(
@@ -61,6 +64,10 @@ class PerfTestBuilder<SV, TV> {
this.profilerEnabled = profilerEnabled
}
fun profilerConfig(profilerConfig: ProfilerConfig) {
this.profilerConfig = profilerConfig
}
fun checkStability(checkStability: Boolean) {
this.checkStability = checkStability
}
@@ -22,6 +22,7 @@ typealias StatInfos = Map<String, Any>?
class Stats(
val name: String = "",
private val profilerConfig: ProfilerConfig = ProfilerConfig(),
private val header: Array<String> = arrayOf("Name", "ValueMS", "StdDev"),
private val acceptanceStabilityLevel: Int = 25
) : Closeable {
@@ -266,7 +267,7 @@ class Stats(
testData.reset()
triggerGC(attempt)
val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt)
val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt, profilerConfig)
val setUpMillis = measureTimeMillis { phaseData.setUp(testData) }
val attemptName = "${phaseData.testName} #$attempt"
@@ -316,7 +317,8 @@ class Stats(
private fun <K, T> createPhaseProfiler(
phaseData: PhaseData<K, T>,
phaseName: String,
attempt: Int
attempt: Int,
profilerConfig: ProfilerConfig
): PhaseProfiler {
val profilerHandler = if (phaseData.profilerEnabled) ProfilerHandler.getInstance() else DummyProfilerHandler
@@ -325,7 +327,7 @@ class Stats(
check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for ${phaseData.testName}" }
val activityName = "${phaseData.testName}-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt"
ActualPhaseProfiler(activityName, profilerPath, profilerHandler)
ActualPhaseProfiler(activityName, profilerPath, profilerHandler, profilerConfig)
} else {
DummyPhaseProfiler
}
@@ -19,14 +19,17 @@ object DummyPhaseProfiler : PhaseProfiler {
class ActualPhaseProfiler(
private val activityName: String,
private val profilerPath: String,
private val profilerHandler: ProfilerHandler
private val profilerHandler: ProfilerHandler,
private val config: ProfilerConfig = ProfilerConfig()
) :
PhaseProfiler {
override fun start() {
profilerHandler.startProfiling(activityName)
profilerHandler.startProfiling(activityName, config)
}
override fun stop() {
profilerHandler.stopProfiling(profilerPath, activityName)
profilerHandler.stopProfiling(profilerPath, activityName, config)
}
}
}
data class ProfilerConfig(var tracing: Boolean = false, var options: List<String> = emptyList())
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.idea.perf.profilers.yk.YKProfilerHandler
import org.jetbrains.kotlin.idea.perf.util.logMessage
interface ProfilerHandler {
fun startProfiling(activityName: String, options: List<String> = emptyList())
fun startProfiling(activityName: String, config: ProfilerConfig)
fun stopProfiling(snapshotsPath: String, activityName: String, options: List<String> = emptyList())
fun stopProfiling(snapshotsPath: String, activityName: String, config: ProfilerConfig)
companion object {
private var instance: ProfilerHandler? = null
@@ -32,9 +32,9 @@ interface ProfilerHandler {
}
object DummyProfilerHandler : ProfilerHandler {
override fun startProfiling(activityName: String, options: List<String>) {}
override fun startProfiling(activityName: String, config: ProfilerConfig) {}
override fun stopProfiling(snapshotsPath: String, activityName: String, options: List<String>) {}
override fun stopProfiling(snapshotsPath: String, activityName: String, config: ProfilerConfig) {}
}
internal fun <T> doOrLog(message: String, block: () -> T?): T? {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.perf.profilers.async
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerConfig
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerHandler
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
import org.jetbrains.kotlin.idea.perf.util.logMessage
@@ -47,18 +48,18 @@ internal class AsyncProfilerHandler : ProfilerHandler {
executeMethod.invoke(asyncProfiler, command)
}
override fun startProfiling(activityName: String, options: List<String>) {
override fun startProfiling(activityName: String, config: ProfilerConfig) {
try {
profilingOptions = options
execute(AsyncProfilerCommandBuilder.buildStartCommand(options))
profilingOptions = config.options
execute(AsyncProfilerCommandBuilder.buildStartCommand(config.options))
profilingStarted = true
} catch (e: Exception) {
throw RuntimeException(e)
}
}
override fun stopProfiling(snapshotsPath: String, activityName: String, options: List<String>) {
val combinedOptions = ArrayList(options)
override fun stopProfiling(snapshotsPath: String, activityName: String, config: ProfilerConfig) {
val combinedOptions = ArrayList(config.options)
val commandBuilder = AsyncProfilerCommandBuilder(snapshotsPath)
val name = activityName.replace(' ', '_').replace('/', '_')
val stopAndDumpCommands = commandBuilder.buildStopAndDumpCommands(name, combinedOptions)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.perf.profilers.yk
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerConfig
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerHandler
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
import org.jetbrains.kotlin.idea.perf.util.logMessage
@@ -32,15 +33,18 @@ class YKProfilerHandler : ProfilerHandler {
}
}
override fun startProfiling(activityName: String, options: List<String>) {
startCPUSamplingMethod.invoke(controller, null)
override fun startProfiling(activityName: String, config: ProfilerConfig) {
if (config.tracing)
startTracingMethod.invoke(controller, null)
else
startCPUSamplingMethod.invoke(controller, null)
}
override fun stopProfiling(snapshotsPath: String, activityName: String, options: List<String>) {
override fun stopProfiling(snapshotsPath: String, activityName: String, config: ProfilerConfig) {
val dumpPath = captureSnapshotMethod.invoke(controller, SNAPSHOT_WITHOUT_HEAP) as String
stopCPUProfilingMethod.invoke(controller)
val path = Paths.get(dumpPath)
val target = path.parent.resolve(snapshotsPath)
val target = path.parent.resolve(snapshotsPath).resolve(activityName)
logMessage { "dump is moved to $target" }
Files.move(path, target)
}
@@ -57,6 +61,12 @@ class YKProfilerHandler : ProfilerHandler {
String::class.java
)
}
private val startTracingMethod: Method = doOrThrow("com.yourkit.api.Controller#startTracing(String) not found") {
ykLibClass.getMethod(
"startTracing",
String::class.java
)
}
private val captureSnapshotMethod: Method = doOrThrow("com.yourkit.api.Controller#captureSnapshot(long) not found") {
ykLibClass.getMethod(
"captureSnapshot",
@@ -64,6 +74,10 @@ class YKProfilerHandler : ProfilerHandler {
)
}
private val capturePerformanceSnapshotMethod: Method = doOrThrow("com.yourkit.api.Controller#capturePerformanceSnapshot() not found") {
ykLibClass.getMethod("capturePerformanceSnapshot")
}
private val stopCPUProfilingMethod: Method = doOrThrow("com.yourkit.api.Controller#stopCPUProfiling() not found") {
ykLibClass.getMethod("stopCPUProfiling")
}
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.perf.ProjectBuilder
import org.jetbrains.kotlin.idea.perf.Stats
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
import org.jetbrains.kotlin.idea.perf.performanceTest
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerConfig
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.disableAllInspections
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableAllInspections
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableInspections
@@ -139,6 +140,7 @@ class PerformanceSuite {
after?.invoke()
}
profilerEnabled(config.profile)
profilerConfig(config.profilerConfig)
}
return value
}
@@ -178,7 +180,7 @@ class PerformanceSuite {
}
override fun close() {
application?.setDataProvider(null)
application.setDataProvider(null)
}
companion object {
@@ -214,7 +216,7 @@ class PerformanceSuite {
}
class StatsScopeConfig(var name: String? = null, var warmup: Int = 2, var iterations: Int = 5, var profile: Boolean = false)
class StatsScopeConfig(var name: String? = null, var warmup: Int = 2, var iterations: Int = 5, var profile: Boolean = false, var profilerConfig: ProfilerConfig = ProfilerConfig())
class ProjectScopeConfig(val path: String, val openWith: ProjectOpenAction, val refresh: Boolean = false) {
val name: String = path.lastPathSegment()
@@ -329,8 +331,8 @@ class PerformanceSuite {
override fun close() {
RunAll(
ThrowableRunnable {
project?.let { prj ->
app.application?.closeProject(prj)
project.let { prj ->
app.application.closeProject(prj)
}
}).run()
}
@@ -407,7 +409,7 @@ fun UsefulTestCase.suite(
) {
PerformanceSuite.suite(
suiteName ?: this.javaClass.name,
PerformanceSuite.StatsScope(config, Stats(config.name ?: suiteName ?: name), testRootDisposable),
PerformanceSuite.StatsScope(config, Stats(config.name ?: suiteName ?: name, config.profilerConfig), testRootDisposable),
block
)
}
@@ -13,6 +13,8 @@ class ExternalProject(val path: String, val openWith: ProjectOpenAction) {
val KOTLIN_GRADLE = ExternalProject(KOTLIN_PROJECT_PATH, ProjectOpenAction.GRADLE_PROJECT)
val KOTLIN_JPS = ExternalProject(KOTLIN_PROJECT_PATH, ProjectOpenAction.EXISTING_IDEA_PROJECT)
// not intended for using in unit tests, only for local verification
val KOTLIN_AUTO = ExternalProject(KOTLIN_PROJECT_PATH, autoOpenAction(KOTLIN_PROJECT_PATH))
fun autoOpenAction(path: String): ProjectOpenAction {