Performance tests DSL is added

This commit is contained in:
Vladimir Dolzhenko
2019-12-01 13:19:25 +01:00
parent 1b075340f8
commit 7fede87825
9 changed files with 226 additions and 148 deletions
@@ -13,8 +13,6 @@ import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.idea.completion.test.ExpectedCompletionUtils
import org.jetbrains.kotlin.idea.completion.test.configureWithExtraFile
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.CODE_STYLE_SETTING_PREFIX
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.COMPLETION_CHARS_PREFIX
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.COMPLETION_CHAR_PREFIX
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.ELEMENT_TEXT_PREFIX
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.INVOCATION_COUNT_PREFIX
import org.jetbrains.kotlin.idea.completion.test.handlers.AbstractCompletionHandlerTest.Companion.LOOKUP_STRING_PREFIX
@@ -116,23 +114,21 @@ abstract class AbstractPerformanceCompletionHandlerTests(
tailText: String?,
completionChars: String
) {
val testName = getTestName(false)
val stats = stats()
stats.perfTest<Unit, Unit>(
testName = testName,
setUp = {
performanceTest<Unit, Unit> {
name(getTestName(false))
stats(stats())
setUp {
setUpFixture(testPath)
},
test = {
}
test {
perfTestCore(completionType, time, lookupString, itemText, tailText, completionChars)
},
tearDown = {
}
tearDown {
runWriteAction {
myFixture.file.delete()
}
})
}
}
}
private fun perfTestCore(
@@ -102,18 +102,19 @@ abstract class AbstractPerformanceCompletionIncrementalResolveTest : KotlinLight
private fun innerPerfTest(name: String, setUpBody: (TestData<Unit, Array<LookupElement>>) -> Unit) {
CompletionBindingContextProvider.ENABLED = true
try {
stats.perfTest(
testName = name,
setUp = setUpBody,
test = { it.value = perfTestCore() },
tearDown = {
performanceTest<Unit, Array<LookupElement>> {
name(name)
stats(stats)
setUp(setUpBody)
test { it.value = perfTestCore() }
tearDown {
// no reasons to validate output as it is a performance test
assertNotNull(it.value)
runWriteAction {
myFixture.file.delete()
}
}
)
}
} finally {
CompletionBindingContextProvider.ENABLED = false
}
@@ -72,19 +72,20 @@ abstract class AbstractPerformanceHighlightingTest : KotlinLightCodeInsightFixtu
}
private fun innerPerfTest(name: String, setUpBody: (TestData<Unit, MutableList<HighlightInfo>>) -> Unit) {
stats.perfTest<Unit, MutableList<HighlightInfo>>(
testName = name,
setUp = {
performanceTest<Unit, MutableList<HighlightInfo>> {
name(name)
stats(stats)
setUp {
setUpBody(it)
},
test = { it.value = perfTestCore() },
tearDown = {
}
test { it.value = perfTestCore() }
tearDown {
assertNotNull("no reasons to validate output as it is a performance test", it.value)
runWriteAction {
myFixture.file.delete()
}
}
)
}
}
private fun perfTestCore(): MutableList<HighlightInfo> = myFixture.doHighlighting()
@@ -80,20 +80,21 @@ abstract class AbstractPerformanceImportTest : KotlinLightCodeInsightFixtureTest
val importInsertHelper = ImportInsertHelper.getInstance(project)
val psiDocumentManager = PsiDocumentManager.getInstance(project)
stats().perfTest<Unit, String>(
testName = testName,
setUp = {
performanceTest<Unit, String> {
name(testName)
stats(stats())
setUp {
fixture.configureByFile(fileName())
file = fixture.file as KtFile
fileText = file.text
},
test = {
}
test {
it.value = project.executeWriteCommand<String?>("") {
perfTestCore(file, fqName, filter, descriptorName, importInsertHelper, psiDocumentManager)
}
},
tearDown = {
}
tearDown {
val log = it.value
val testPath = testPath()
val afterFile = File("$testPath.after")
@@ -109,7 +110,8 @@ abstract class AbstractPerformanceImportTest : KotlinLightCodeInsightFixtureTest
runWriteAction {
myFixture.file.delete()
}
})
}
}
} finally {
CodeStyle.dropTemporarySettings(project)
}
@@ -47,29 +47,28 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
}
private fun doWarmUpPerfTest() {
stats().perfTest<Unit, Unit>(
testName = WARM_UP,
setUp = {
performanceTest<Unit, Unit> {
name(WARM_UP)
stats(stats())
setUp {
with(myFixture) {
configureByText(JavaFileType.INSTANCE, "<selection>public class Foo {\nprivate String value;\n}</selection>")
performEditorAction(IdeActions.ACTION_CUT)
configureByText(KotlinFileType.INSTANCE, "<caret>")
}
ConvertJavaCopyPasteProcessor.conversionPerformed = false
},
test = {
}
test {
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
},
tearDown = {
}
tearDown {
val document = myFixture.getDocument(myFixture.file)
PsiDocumentManager.getInstance(project).commitDocument(document)
kotlin.test.assertFalse(!ConvertJavaCopyPasteProcessor.conversionPerformed, "No conversion to Kotlin suggested")
assertEquals("class Foo {\n private val value: String? = null\n}", myFixture.file.text)
runWriteAction {
myFixture.file.delete()
}
deleteFixtureFile()
}
)
}
}
private fun j2kIndex(): Int {
@@ -86,9 +85,10 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
val fileText = myFixture.editor.document.text
val noConversionExpected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// NO_CONVERSION_EXPECTED").isNotEmpty()
stats().perfTest<Unit, Unit>(
testName = testName,
setUp = {
performanceTest<Unit, Unit> {
name(testName)
stats(stats())
setUp {
myFixture.configureByFiles("$testName.java")
myFixture.performEditorAction(IdeActions.ACTION_COPY)
@@ -98,18 +98,22 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
configureTargetFile("$testName.to.kt")
ConvertJavaCopyPasteProcessor.conversionPerformed = false
},
test = {
}
test {
perfTestCore()
},
tearDown = {
}
tearDown {
commitAllDocuments()
validate(path, noConversionExpected)
// to avoid VFS refresh
myFixture.performEditorAction(IdeActions.ACTION_UNDO)
deleteFixtureFile()
}
)
}
}
private fun deleteFixtureFile() {
runWriteAction {
myFixture.file.delete()
}
}
private fun perfTestCore() {
@@ -46,25 +46,26 @@ abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractC
private fun doWarmUpPerfTest() {
val fileEditorManager = FileEditorManagerEx.getInstance(project)
stats.perfTest<Pair<PsiFile, PsiFile>, Unit>(
testName = WARM_UP,
iterations = 1,
setUp = {
performanceTest<Pair<PsiFile, PsiFile>, Unit> {
name(WARM_UP)
stats(stats)
iterations(1)
setUp {
val file1 = myFixture.configureByText(
"src.kt",
"class Foo {\n <selection>private val value: String? = n<caret></selection>\n}"
)
val file2 = myFixture.configureByText("target.kt", "<caret>")
it.setUpValue = Pair(file1, file2)
},
test = {
}
test {
fileEditorManager.setSelectedEditor(it.setUpValue!!.first.virtualFile, "")
myFixture.performEditorAction(IdeActions.ACTION_COPY)
fileEditorManager.setSelectedEditor(it.setUpValue!!.second.virtualFile, "")
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
},
tearDown = {
}
tearDown {
assertEquals("private val value: String? = n", it.setUpValue!!.second.text)
// to avoid VFS refresh
@@ -75,7 +76,7 @@ abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractC
it.setUpValue!!.second.delete()
}
}
)
}
}
fun doPerfTest(unused: String) {
@@ -85,19 +86,20 @@ abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractC
val expectedPath = File(testPath.replace(".kt", ".expected.kt"))
val fileEditorManager = FileEditorManagerEx.getInstance(project)
stats.perfTest<Array<PsiFile>, Unit>(
testName = testName,
setUp = {
performanceTest<Array<PsiFile>, Unit> {
name(testName)
stats(stats)
setUp {
it.setUpValue = myFixture.configureByFiles(fileName, fileName.replace(".kt", ".to.kt"))
},
test = {
}
test {
fileEditorManager.setSelectedEditor(it.setUpValue!![0].virtualFile, "")
myFixture.performEditorAction(IdeActions.ACTION_COPY)
fileEditorManager.setSelectedEditor(it.setUpValue!![1].virtualFile, "")
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
},
tearDown = {
}
tearDown {
KotlinTestUtils.assertEqualsToFile(expectedPath, it.setUpValue!![1].text)
// to avoid VFS refresh
@@ -107,6 +109,6 @@ abstract class AbstractPerformanceLiteralKotlinToKotlinCopyPasteTest : AbstractC
it.setUpValue!!.forEach { f -> f.delete() }
}
}
)
}
}
}
@@ -157,11 +157,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
var lastProject: Project? = null
var counter = 0
stats.perfTest<Unit, Project>(
warmUpIterations = warmUpIterations,
iterations = iterations,
testName = "open project${if (note.isNotEmpty()) " $note" else ""}",
test = {
performanceTest<Unit, Project> {
name("open project${if (note.isNotEmpty()) " $note" else ""}")
stats(stats)
warmUpIterations(warmUpIterations)
iterations(iterations)
test {
val project = if (!simpleModule) {
val project = loadProjectWithName(name = name, path = path)
assertNotNull("project $name at $path is not loaded", project)
@@ -196,8 +197,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
}
it.value = project
},
tearDown = {
}
tearDown {
it.value?.let { project ->
runAndMeasure("refresh gradle project $name") {
@@ -234,7 +235,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
counter++
}
}
)
}
// indexing
lastProject?.let { project ->
@@ -305,11 +306,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
note: String = ""
) {
assertTrue("lookupElements has to be not empty", lookupElements.isNotEmpty())
stats.perfTest<Pair<String, Fixture>, Array<LookupElement>>(
warmUpIterations = 8,
iterations = 15,
testName = "typeAndAutocomplete ${notePrefix(note)}$fileName",
setUp = {
performanceTest<Pair<String, Fixture>, Array<LookupElement>> {
name("typeAndAutocomplete ${notePrefix(note)}$fileName")
stats(stats)
warmUpIterations(8)
iterations(15)
setUp {
val fixture = openFixture(project, fileName)
val editor = fixture.editor
@@ -340,12 +342,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
fixture.type(insertString)
it.setUpValue = Pair(initialText, fixture)
},
test = {
}
test {
val fixture = it.setUpValue!!.second
it.value = fixture.complete()
},
tearDown = {
}
tearDown {
val items = it.value?.map { e -> e.lookupString }?.toList() ?: emptyList()
try {
for (lookupElement in lookupElements) {
@@ -357,9 +359,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
}
commitAllDocuments()
}
},
profileEnabled = true
)
}
profileEnabled(true)
}
}
fun perfTypeAndHighlight(
@@ -388,11 +390,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
revertChangesAtTheEnd: Boolean = true,
note: String = ""
) {
stats.perfTest<Pair<String, Fixture>, List<HighlightInfo>>(
warmUpIterations = 8,
iterations = 15,
testName = "typeAndHighlight ${notePrefix(note)}$fileName",
setUp = {
performanceTest<Pair<String, Fixture>, List<HighlightInfo>> {
name("typeAndHighlight ${notePrefix(note)}$fileName")
stats(stats)
warmUpIterations(8)
iterations(15)
setUp {
val fixture = openFixture(project, fileName)
val editor = fixture.editor
@@ -423,12 +426,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
fixture.type(insertString)
it.setUpValue = Pair(initialText, fixture)
},
test = {
}
test {
val fixture = it.setUpValue!!.second
it.value = fixture.doHighlighting()
},
tearDown = {
}
tearDown {
it.value?.let { list ->
assertNotEmpty(list)
}
@@ -436,9 +439,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
pair.second.revertChanges(revertChangesAtTheEnd, pair.first)
}
commitAllDocuments()
},
profileEnabled = true
)
}
profileEnabled(true)
}
}
fun perfCopyAndPaste(
@@ -468,11 +471,12 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
targetFinalMarker: String? = null,
note: String = ""
) {
stats.perfTest<Pair<Array<Fixture>, String>, Boolean>(
warmUpIterations = 8,
iterations = 15,
testName = "${notePrefix(note)}$sourceFileName",
setUp = {
performanceTest<Pair<Array<Fixture>, String>, Boolean> {
name("${notePrefix(note)}$sourceFileName")
stats(stats)
warmUpIterations(8)
iterations(15)
setUp {
val fixture1 = openFixture(project, sourceFileName)
val fixture2 = openFixture(project, targetFileName)
@@ -485,16 +489,16 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
fixture2.selectMarkers(targetInitialMarker, targetFinalMarker)
it.setUpValue = Pair(arrayOf(fixture1, fixture2), initialText2)
},
test = {
}
test {
it.setUpValue?.let { setUpValue ->
val fixture1 = setUpValue.first[0]
val fixture2 = setUpValue.first[1]
it.value = fixture1.performEditorAction(IdeActions.ACTION_COPY) &&
fixture2.performEditorAction(IdeActions.ACTION_PASTE)
}
},
tearDown = {
}
tearDown {
try {
commitAllDocuments()
it.value?.let { performed ->
@@ -510,9 +514,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
}
commitAllDocuments()
}
},
profileEnabled = true
)
}
profileEnabled(true)
}
}
private fun updateScriptDependenciesIfNeeded(
@@ -560,25 +564,26 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
return highlightFile {
val isWarmUp = note == WARM_UP
var highlightInfos: List<HighlightInfo> = emptyList()
stats.perfTest<EditorFile, List<HighlightInfo>>(
warmUpIterations = if (isWarmUp) 1 else 3,
iterations = if (isWarmUp) 2 else 10,
testName = "highlighting ${notePrefix(note)}${simpleFilename(fileName)}",
setUp = {
performanceTest<EditorFile, List<HighlightInfo>> {
name("highlighting ${notePrefix(note)}${simpleFilename(fileName)}")
stats(stats)
warmUpIterations(if (isWarmUp) 1 else 3)
iterations(if (isWarmUp) 2 else 10)
setUp {
it.setUpValue = openFileInEditor(project, fileName)
},
test = {
}
test {
val file = it.setUpValue
it.value = highlightFile(project, file!!.psiFile)
},
tearDown = {
}
tearDown {
highlightInfos = it.value ?: emptyList()
commitAllDocuments()
FileEditorManager.getInstance(project).closeFile(it.setUpValue!!.psiFile.virtualFile)
PsiManager.getInstance(project).dropPsiCaches()
},
profileEnabled = !isWarmUp
)
}
profileEnabled(!isWarmUp)
}
highlightInfos
}
}
@@ -610,19 +615,20 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
note: String = ""
) {
if (!isAKotlinScriptFile(fileName)) return
stats.perfTest<EditorFile, EditorFile>(
testName = "updateScriptDependencies ${notePrefix(note)}${simpleFilename(fileName)}",
setUp = { it.setUpValue = openFileInEditor(project, fileName) },
test = {
performanceTest<EditorFile, EditorFile> {
name("updateScriptDependencies ${notePrefix(note)}${simpleFilename(fileName)}")
stats(stats)
setUp { it.setUpValue = openFileInEditor(project, fileName) }
test {
ScriptConfigurationManager.updateScriptDependenciesSynchronously(it.setUpValue!!.psiFile, project)
it.value = it.setUpValue
},
tearDown = {
}
tearDown {
it.setUpValue?.let { ef -> cleanupCaches(project, ef.psiFile.virtualFile) }
it.value?.let { v -> assertNotNull(v) }
},
profileEnabled = true
)
}
profileEnabled(true)
}
}
fun notePrefix(note: String) = if (note.isNotEmpty()) {
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2019 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
class PerfTestBuilder<SV, TV> {
private lateinit var stats: Stats
private lateinit var name: String
private var warmUpIterations: Int = 5
private var iterations: Int = 20
private var setUp: (TestData<SV, TV>) -> Unit = { }
private lateinit var test: (TestData<SV, TV>) -> Unit
private var tearDown: (TestData<SV, TV>) -> Unit = { }
private var profileEnabled: Boolean = false
fun run() {
stats.perfTest(
testName = name,
warmUpIterations = warmUpIterations,
iterations = iterations,
setUp = setUp,
test = test,
tearDown = tearDown,
profileEnabled = profileEnabled
)
}
fun stats(stats: Stats) {
this.stats = stats
}
fun name(name: String) {
this.name = name
}
fun warmUpIterations(warmUpIterations: Int) {
this.warmUpIterations = warmUpIterations
}
fun iterations(iterations: Int) {
this.iterations = iterations
}
fun setUp(setUp: (TestData<SV, TV>) -> Unit) {
this.setUp = setUp
}
fun test(test: (TestData<SV, TV>) -> Unit) {
this.test = test
}
fun tearDown(tearDown: (TestData<SV, TV>) -> Unit) {
this.tearDown = tearDown
}
fun profileEnabled(profileEnabled: Boolean) {
this.profileEnabled = profileEnabled
}
}
fun <SV, TV> performanceTest(initializer: PerfTestBuilder<SV, TV>.() -> Unit) {
PerfTestBuilder<SV, TV>().apply(initializer).run()
}
@@ -248,15 +248,16 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
val warmUpIterations = 3
val iterations = 10
stats.perfTest(
warmUpIterations = warmUpIterations,
iterations = iterations,
testName = testName,
setUp = perfKtsFileAnalysisSetUp(project, fileName),
test = perfKtsFileAnalysisTest(),
tearDown = perfKtsFileAnalysisTearDown(extraTimingsNs, project),
profileEnabled = true
)
performanceTest<Fixture, Pair<Long, List<HighlightInfo>>> {
name(testName)
stats(stats)
warmUpIterations(warmUpIterations)
iterations(iterations)
setUp(perfKtsFileAnalysisSetUp(project, fileName))
test(perfKtsFileAnalysisTest())
tearDown(perfKtsFileAnalysisTearDown(extraTimingsNs, project))
profileEnabled(true)
}
extraStats.printWarmUpTimings(
"annotator",