diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/AbstractPerformanceProjectsTest.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/AbstractPerformanceProjectsTest.kt index c8227c1e1f3..2d1535668d2 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/AbstractPerformanceProjectsTest.kt +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/AbstractPerformanceProjectsTest.kt @@ -41,6 +41,7 @@ import com.intellij.util.ArrayUtilRt import com.intellij.util.ThrowableRunnable import com.intellij.util.indexing.UnindexedFilesUpdater import com.intellij.util.io.exists +import com.intellij.util.ui.UIUtil import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager import org.jetbrains.kotlin.idea.framework.KotlinSdkType @@ -55,7 +56,6 @@ import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.isAKotlinScript import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFileInEditor import org.jetbrains.kotlin.idea.testFramework.Fixture.Companion.openFixture import org.jetbrains.kotlin.idea.util.getProjectJdkTableSafe -import org.jetbrains.kotlin.psi.KtFile import java.io.File import java.nio.file.Paths @@ -280,18 +280,90 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() { note: String = "" ) { assertTrue("lookupElements has to be not empty", lookupElements.isNotEmpty()) + perfTypeAndDo( + project, + fileName, + "typeAndAutocomplete", + note, + stats, + marker, + typeAfterMarker, + surroundItems, + insertString, + setupBlock = {}, + testBlock = { fixture: Fixture -> + fixture.complete() + }, + tearDownCheck = { _, value: Array? -> + val items = value?.map { e -> e.lookupString }?.toList() ?: emptyList() + for (lookupElement in lookupElements) { + assertTrue("'$lookupElement' has to be present in items $items", items.contains(lookupElement)) + } + }, + revertChangesAtTheEnd = revertChangesAtTheEnd + ) + } + + fun perfTypeAndUndo( + project: Project, + stats: Stats, + fileName: String, + marker: String, + insertString: String, + surroundItems: String = "\n", + typeAfterMarker: Boolean = true, + revertChangesAtTheEnd: Boolean = true, + note: String = "" + ) { + var fileText: String? = null + perfTypeAndDo( + project, + fileName, + "typeAndUndo", + note, + stats, + marker, + typeAfterMarker, + surroundItems, + insertString, + setupBlock = { fixture: Fixture -> + fileText = fixture.document.text + }, + testBlock = { fixture: Fixture -> + fixture.performEditorAction(IdeActions.ACTION_UNDO) + UIUtil.dispatchAllInvocationEvents() + }, + tearDownCheck = { fixture, _ -> + val text = fixture.document.text + assert(fileText != text) { "undo has to change document text\nbefore undo:\n$fileText\n\nafter undo:\n$text" } + }, + revertChangesAtTheEnd = revertChangesAtTheEnd + ) + } + + private fun perfTypeAndDo( + project: Project, + fileName: String, + typeTestPrefix: String, + note: String, + stats: Stats, + marker: String, + typeAfterMarker: Boolean, + surroundItems: String, + insertString: String, + setupBlock: (Fixture) -> Unit, + testBlock: (Fixture) -> V, + tearDownCheck: (Fixture, V?) -> Unit, + revertChangesAtTheEnd: Boolean + ) { openFixture(project, fileName).use { fixture -> val editor = fixture.editor val initialText = editor.document.text updateScriptDependenciesIfNeeded(fileName, fixture, project) - val scriptConfigurationManager = ScriptConfigurationManager.getInstance(fixture.project) - val configuration = scriptConfigurationManager.getConfiguration(fixture.psiFile as KtFile) - //scriptConfigurationManager.reloadScriptDefinitions() - //scriptConfigurationManager.forceReloadConfiguration(fixture.vFile, loaderForOutOfProjectScripts) - performanceTest, Array> { - name("typeAndAutocomplete ${notePrefix(note)}$fileName") + performanceTest { + name("$typeTestPrefix ${notePrefix(note)}$fileName") stats(stats) warmUpIterations(8) iterations(15) @@ -319,19 +391,14 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() { } fixture.type(insertString) - - it.setUpValue = Pair(initialText, fixture) + setupBlock(fixture) } test { - val fixture = it.setUpValue!!.second - it.value = fixture.complete() + it.value = testBlock(fixture) } tearDown { - val items = it.value?.map { e -> e.lookupString }?.toList() ?: emptyList() try { - for (lookupElement in lookupElements) { - assertTrue("'$lookupElement' has to be present in items $items", items.contains(lookupElement)) - } + tearDownCheck(fixture, it.value) } finally { fixture.revertChanges(revertChangesAtTheEnd, initialText) commitAllDocuments() @@ -562,7 +629,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() { protected fun perfScriptDependencies(name: String, stats: Stats, note: String = "") = perfScriptDependencies(project(), name, stats, note = note) - private fun project() = myProject ?: error("project has not been initialized") + protected fun project() = myProject ?: error("project has not been initialized") private fun perfScriptDependencies( project: Project, @@ -574,6 +641,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() { performanceTest { name("updateScriptDependencies ${notePrefix(note)}${simpleFilename(fileName)}") stats(stats) + warmUpIterations(20) + iterations(50) setUp { it.setUpValue = openFileInEditor(project, fileName) } test { ScriptConfigurationManager.updateScriptDependenciesSynchronously(it.setUpValue!!.psiFile, project) @@ -587,6 +656,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() { it.value?.let { v -> assertNotNull(v) } } profileEnabled(true) + checkStability(false) } } diff --git a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceProjectsTest.kt b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceProjectsTest.kt index c2794c19763..ab9154ce475 100644 --- a/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceProjectsTest.kt +++ b/idea/performanceTests/test/org/jetbrains/kotlin/idea/perf/PerformanceProjectsTest.kt @@ -40,7 +40,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() { init { // there is no @AfterClass for junit3.8 - Runtime.getRuntime().addShutdownHook(Thread(Runnable { hwStats.close() })) + Runtime.getRuntime().addShutdownHook(Thread { hwStats.close() }) } fun resetTimestamp() { @@ -62,6 +62,7 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() { } fun testHelloWorldProject() { + tcSuite("Hello world project") { myProject = perfOpenHelloWorld(hwStats) @@ -154,17 +155,6 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() { perfOpenKotlinProjectFast(stat) } -// runAndMeasure("type and autocomplete") { -// perfTypeAndAutocomplete( -// stat, -// "build.gradle.kts", -// "tasks {", -// "default", -// lookupElements = listOf("defaultJvmTarget"), -// note = "tasks-create" -// ) -// } - runAndMeasure("type and autocomplete") { perfTypeAndAutocomplete( stat, @@ -176,6 +166,16 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() { ) } + runAndMeasure("type and undo") { + perfTypeAndUndo( + project(), + stat, + "build.gradle.kts", + "tasks {", + "register", + note = "type-undo" + ) + } } } @@ -281,14 +281,14 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() { val extraStats = Stats("${stats.name} $testName") val extraTimingsNs = mutableListOf?>() - val warmUpIterations = 3 - val iterations = 10 + val warmUpIterations = 20 + val iterations = 30 performanceTest>> { name(testName) stats(stats) - warmUpIterations(warmUpIterations) - iterations(iterations) + warmUpIterations(30) + iterations(50) setUp(perfKtsFileAnalysisSetUp(project, fileName)) test(perfKtsFileAnalysisTest()) tearDown(perfKtsFileAnalysisTearDown(extraTimingsNs, project))