(UnusedSymbolInspection) Added support for typing per inspection tests
relates to #KT-38653
This commit is contained in:
+55
@@ -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
|
package org.jetbrains.kotlin.idea.perf
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.perf.profilers.ProfilerConfig
|
||||||
|
|
||||||
class PerfTestBuilder<SV, TV> {
|
class PerfTestBuilder<SV, TV> {
|
||||||
private lateinit var stats: Stats
|
private lateinit var stats: Stats
|
||||||
private lateinit var name: String
|
private lateinit var name: String
|
||||||
@@ -15,6 +17,7 @@ class PerfTestBuilder<SV, TV> {
|
|||||||
private var tearDown: (TestData<SV, TV>) -> Unit = { }
|
private var tearDown: (TestData<SV, TV>) -> Unit = { }
|
||||||
private var profilerEnabled: Boolean = false
|
private var profilerEnabled: Boolean = false
|
||||||
private var checkStability: Boolean = true
|
private var checkStability: Boolean = true
|
||||||
|
private var profilerConfig: ProfilerConfig = ProfilerConfig()
|
||||||
|
|
||||||
internal fun run() {
|
internal fun run() {
|
||||||
stats.perfTest(
|
stats.perfTest(
|
||||||
@@ -61,6 +64,10 @@ class PerfTestBuilder<SV, TV> {
|
|||||||
this.profilerEnabled = profilerEnabled
|
this.profilerEnabled = profilerEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun profilerConfig(profilerConfig: ProfilerConfig) {
|
||||||
|
this.profilerConfig = profilerConfig
|
||||||
|
}
|
||||||
|
|
||||||
fun checkStability(checkStability: Boolean) {
|
fun checkStability(checkStability: Boolean) {
|
||||||
this.checkStability = checkStability
|
this.checkStability = checkStability
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ typealias StatInfos = Map<String, Any>?
|
|||||||
|
|
||||||
class Stats(
|
class Stats(
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
|
private val profilerConfig: ProfilerConfig = ProfilerConfig(),
|
||||||
private val header: Array<String> = arrayOf("Name", "ValueMS", "StdDev"),
|
private val header: Array<String> = arrayOf("Name", "ValueMS", "StdDev"),
|
||||||
private val acceptanceStabilityLevel: Int = 25
|
private val acceptanceStabilityLevel: Int = 25
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
@@ -266,7 +267,7 @@ class Stats(
|
|||||||
testData.reset()
|
testData.reset()
|
||||||
triggerGC(attempt)
|
triggerGC(attempt)
|
||||||
|
|
||||||
val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt)
|
val phaseProfiler = createPhaseProfiler(phaseData, phaseName, attempt, profilerConfig)
|
||||||
|
|
||||||
val setUpMillis = measureTimeMillis { phaseData.setUp(testData) }
|
val setUpMillis = measureTimeMillis { phaseData.setUp(testData) }
|
||||||
val attemptName = "${phaseData.testName} #$attempt"
|
val attemptName = "${phaseData.testName} #$attempt"
|
||||||
@@ -316,7 +317,8 @@ class Stats(
|
|||||||
private fun <K, T> createPhaseProfiler(
|
private fun <K, T> createPhaseProfiler(
|
||||||
phaseData: PhaseData<K, T>,
|
phaseData: PhaseData<K, T>,
|
||||||
phaseName: String,
|
phaseName: String,
|
||||||
attempt: Int
|
attempt: Int,
|
||||||
|
profilerConfig: ProfilerConfig
|
||||||
): PhaseProfiler {
|
): PhaseProfiler {
|
||||||
val profilerHandler = if (phaseData.profilerEnabled) ProfilerHandler.getInstance() else DummyProfilerHandler
|
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}" }
|
check(with(File(profilerPath)) { exists() || mkdirs() }) { "unable to mkdirs $profilerPath for ${phaseData.testName}" }
|
||||||
val activityName = "${phaseData.testName}-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt"
|
val activityName = "${phaseData.testName}-${if (phaseName.isEmpty()) "" else "$phaseName-"}$attempt"
|
||||||
|
|
||||||
ActualPhaseProfiler(activityName, profilerPath, profilerHandler)
|
ActualPhaseProfiler(activityName, profilerPath, profilerHandler, profilerConfig)
|
||||||
} else {
|
} else {
|
||||||
DummyPhaseProfiler
|
DummyPhaseProfiler
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -19,14 +19,17 @@ object DummyPhaseProfiler : PhaseProfiler {
|
|||||||
class ActualPhaseProfiler(
|
class ActualPhaseProfiler(
|
||||||
private val activityName: String,
|
private val activityName: String,
|
||||||
private val profilerPath: String,
|
private val profilerPath: String,
|
||||||
private val profilerHandler: ProfilerHandler
|
private val profilerHandler: ProfilerHandler,
|
||||||
|
private val config: ProfilerConfig = ProfilerConfig()
|
||||||
) :
|
) :
|
||||||
PhaseProfiler {
|
PhaseProfiler {
|
||||||
override fun start() {
|
override fun start() {
|
||||||
profilerHandler.startProfiling(activityName)
|
profilerHandler.startProfiling(activityName, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {
|
override fun stop() {
|
||||||
profilerHandler.stopProfiling(profilerPath, activityName)
|
profilerHandler.stopProfiling(profilerPath, activityName, config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class ProfilerConfig(var tracing: Boolean = false, var options: List<String> = emptyList())
|
||||||
+4
-4
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.idea.perf.profilers.yk.YKProfilerHandler
|
|||||||
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
||||||
|
|
||||||
interface ProfilerHandler {
|
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 {
|
companion object {
|
||||||
private var instance: ProfilerHandler? = null
|
private var instance: ProfilerHandler? = null
|
||||||
@@ -32,9 +32,9 @@ interface ProfilerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object DummyProfilerHandler : 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? {
|
internal fun <T> doOrLog(message: String, block: () -> T?): T? {
|
||||||
|
|||||||
+6
-5
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.perf.profilers.async
|
|||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.util.containers.ContainerUtil
|
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.ProfilerHandler
|
||||||
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
|
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
|
||||||
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
||||||
@@ -47,18 +48,18 @@ internal class AsyncProfilerHandler : ProfilerHandler {
|
|||||||
executeMethod.invoke(asyncProfiler, command)
|
executeMethod.invoke(asyncProfiler, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startProfiling(activityName: String, options: List<String>) {
|
override fun startProfiling(activityName: String, config: ProfilerConfig) {
|
||||||
try {
|
try {
|
||||||
profilingOptions = options
|
profilingOptions = config.options
|
||||||
execute(AsyncProfilerCommandBuilder.buildStartCommand(options))
|
execute(AsyncProfilerCommandBuilder.buildStartCommand(config.options))
|
||||||
profilingStarted = true
|
profilingStarted = true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw RuntimeException(e)
|
throw RuntimeException(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stopProfiling(snapshotsPath: String, activityName: String, options: List<String>) {
|
override fun stopProfiling(snapshotsPath: String, activityName: String, config: ProfilerConfig) {
|
||||||
val combinedOptions = ArrayList(options)
|
val combinedOptions = ArrayList(config.options)
|
||||||
val commandBuilder = AsyncProfilerCommandBuilder(snapshotsPath)
|
val commandBuilder = AsyncProfilerCommandBuilder(snapshotsPath)
|
||||||
val name = activityName.replace(' ', '_').replace('/', '_')
|
val name = activityName.replace(' ', '_').replace('/', '_')
|
||||||
val stopAndDumpCommands = commandBuilder.buildStopAndDumpCommands(name, combinedOptions)
|
val stopAndDumpCommands = commandBuilder.buildStopAndDumpCommands(name, combinedOptions)
|
||||||
|
|||||||
+18
-4
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.perf.profilers.yk
|
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.ProfilerHandler
|
||||||
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
|
import org.jetbrains.kotlin.idea.perf.profilers.doOrThrow
|
||||||
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
||||||
@@ -32,15 +33,18 @@ class YKProfilerHandler : ProfilerHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startProfiling(activityName: String, options: List<String>) {
|
override fun startProfiling(activityName: String, config: ProfilerConfig) {
|
||||||
startCPUSamplingMethod.invoke(controller, null)
|
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
|
val dumpPath = captureSnapshotMethod.invoke(controller, SNAPSHOT_WITHOUT_HEAP) as String
|
||||||
stopCPUProfilingMethod.invoke(controller)
|
stopCPUProfilingMethod.invoke(controller)
|
||||||
val path = Paths.get(dumpPath)
|
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" }
|
logMessage { "dump is moved to $target" }
|
||||||
Files.move(path, target)
|
Files.move(path, target)
|
||||||
}
|
}
|
||||||
@@ -57,6 +61,12 @@ class YKProfilerHandler : ProfilerHandler {
|
|||||||
String::class.java
|
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") {
|
private val captureSnapshotMethod: Method = doOrThrow("com.yourkit.api.Controller#captureSnapshot(long) not found") {
|
||||||
ykLibClass.getMethod(
|
ykLibClass.getMethod(
|
||||||
"captureSnapshot",
|
"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") {
|
private val stopCPUProfilingMethod: Method = doOrThrow("com.yourkit.api.Controller#stopCPUProfiling() not found") {
|
||||||
ykLibClass.getMethod("stopCPUProfiling")
|
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
|
||||||
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
|
import org.jetbrains.kotlin.idea.perf.Stats.Companion.runAndMeasure
|
||||||
import org.jetbrains.kotlin.idea.perf.performanceTest
|
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.disableAllInspections
|
||||||
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableAllInspections
|
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableAllInspections
|
||||||
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableInspections
|
import org.jetbrains.kotlin.idea.perf.util.ProfileTools.Companion.enableInspections
|
||||||
@@ -139,6 +140,7 @@ class PerformanceSuite {
|
|||||||
after?.invoke()
|
after?.invoke()
|
||||||
}
|
}
|
||||||
profilerEnabled(config.profile)
|
profilerEnabled(config.profile)
|
||||||
|
profilerConfig(config.profilerConfig)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@@ -178,7 +180,7 @@ class PerformanceSuite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
application?.setDataProvider(null)
|
application.setDataProvider(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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) {
|
class ProjectScopeConfig(val path: String, val openWith: ProjectOpenAction, val refresh: Boolean = false) {
|
||||||
val name: String = path.lastPathSegment()
|
val name: String = path.lastPathSegment()
|
||||||
@@ -329,8 +331,8 @@ class PerformanceSuite {
|
|||||||
override fun close() {
|
override fun close() {
|
||||||
RunAll(
|
RunAll(
|
||||||
ThrowableRunnable {
|
ThrowableRunnable {
|
||||||
project?.let { prj ->
|
project.let { prj ->
|
||||||
app.application?.closeProject(prj)
|
app.application.closeProject(prj)
|
||||||
}
|
}
|
||||||
}).run()
|
}).run()
|
||||||
}
|
}
|
||||||
@@ -407,7 +409,7 @@ fun UsefulTestCase.suite(
|
|||||||
) {
|
) {
|
||||||
PerformanceSuite.suite(
|
PerformanceSuite.suite(
|
||||||
suiteName ?: this.javaClass.name,
|
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
|
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_GRADLE = ExternalProject(KOTLIN_PROJECT_PATH, ProjectOpenAction.GRADLE_PROJECT)
|
||||||
val KOTLIN_JPS = ExternalProject(KOTLIN_PROJECT_PATH, ProjectOpenAction.EXISTING_IDEA_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))
|
val KOTLIN_AUTO = ExternalProject(KOTLIN_PROJECT_PATH, autoOpenAction(KOTLIN_PROJECT_PATH))
|
||||||
|
|
||||||
fun autoOpenAction(path: String): ProjectOpenAction {
|
fun autoOpenAction(path: String): ProjectOpenAction {
|
||||||
|
|||||||
Reference in New Issue
Block a user