Add build gradle kts performance tests
This commit is contained in:
@@ -181,6 +181,7 @@ dependencies {
|
||||
performanceTestCompile(sourceSets["test"].output)
|
||||
performanceTestCompile(sourceSets["main"].output)
|
||||
performanceTestCompile(project(":nj2k"))
|
||||
performanceTestCompile(intellijPluginDep("gradle"))
|
||||
performanceTestRuntime(sourceSets["performanceTest"].output)
|
||||
}
|
||||
|
||||
|
||||
+5
-8
@@ -8,9 +8,8 @@ package org.jetbrains.kotlin.idea.perf
|
||||
import org.jetbrains.kotlin.idea.completion.test.handlers.CompletionHandlerTestBase
|
||||
import com.intellij.application.options.CodeStyle
|
||||
import com.intellij.codeInsight.completion.CompletionType
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.completion.test.ExpectedCompletionUtils
|
||||
import org.jetbrains.kotlin.idea.completion.test.configureWithExtraFile
|
||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||
@@ -127,7 +126,7 @@ abstract class AbstractPerformanceCompletionHandlerTests(
|
||||
val testName = getTestName(false)
|
||||
|
||||
val stats = stats()
|
||||
stats.perfTest(
|
||||
stats.perfTest<Unit, Unit>(
|
||||
testName = testName,
|
||||
setUp = {
|
||||
setUpFixture(testPath)
|
||||
@@ -136,11 +135,9 @@ abstract class AbstractPerformanceCompletionHandlerTests(
|
||||
perfTestCore(completionType, time, lookupString, itemText, tailText, completionChar)
|
||||
},
|
||||
tearDown = {
|
||||
assertNotNull(it)
|
||||
|
||||
FileDocumentManager.getInstance().reloadFromDisk(editor.document)
|
||||
fixture.configureByText(KotlinFileType.INSTANCE, "")
|
||||
commitAllDocuments()
|
||||
runWriteAction {
|
||||
myFixture.file.delete()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -6,7 +6,8 @@
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionType
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.completion.CompletionBindingContextProvider
|
||||
@@ -97,20 +98,19 @@ abstract class AbstractPerformanceCompletionIncrementalResolveTest : KotlinLight
|
||||
}
|
||||
}
|
||||
|
||||
private fun innerPerfTest(name: String, setUpBody: () -> Unit) {
|
||||
private fun innerPerfTest(name: String, setUpBody: (TestData<Unit, Array<LookupElement>>) -> Unit) {
|
||||
CompletionBindingContextProvider.ENABLED = true
|
||||
try {
|
||||
stats.perfTest(
|
||||
testName = name,
|
||||
setUp = setUpBody,
|
||||
test = { perfTestCore() },
|
||||
test = { it.value = perfTestCore() },
|
||||
tearDown = {
|
||||
// no reasons to validate output as it is a performance test
|
||||
assertNotNull(it)
|
||||
|
||||
FileDocumentManager.getInstance().reloadFromDisk(editor.document)
|
||||
myFixture.configureByText(KotlinFileType.INSTANCE, "")
|
||||
commitAllDocuments()
|
||||
assertNotNull(it.value)
|
||||
runWriteAction {
|
||||
myFixture.file.delete()
|
||||
}
|
||||
}
|
||||
)
|
||||
} finally {
|
||||
|
||||
+9
-10
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl.ensureIndexesUpToDate
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
@@ -71,17 +71,16 @@ abstract class AbstractPerformanceHighlightingTest : KotlinLightCodeInsightFixtu
|
||||
}
|
||||
}
|
||||
|
||||
private fun innerPerfTest(name: String, setUpBody: () -> Unit) {
|
||||
stats.perfTest(
|
||||
private fun innerPerfTest(name: String, setUpBody: (TestData<Unit, MutableList<HighlightInfo>>) -> Unit) {
|
||||
stats.perfTest<Unit, MutableList<HighlightInfo>>(
|
||||
testName = name,
|
||||
setUp = { setUpBody() },
|
||||
test = { perfTestCore() },
|
||||
setUp = { setUpBody(it) },
|
||||
test = { it.value = perfTestCore() },
|
||||
tearDown = {
|
||||
assertNotNull("no reasons to validate output as it is a performance test", it)
|
||||
|
||||
FileDocumentManager.getInstance().reloadFromDisk(editor.document)
|
||||
myFixture.configureByText(KotlinFileType.INSTANCE, "")
|
||||
commitAllDocuments()
|
||||
assertNotNull("no reasons to validate output as it is a performance test", it.value)
|
||||
runWriteAction {
|
||||
myFixture.file.delete()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+8
-6
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.application.options.CodeStyle
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.codeStyle.PackageEntry
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
@@ -81,7 +81,7 @@ abstract class AbstractPerformanceImportTest : KotlinLightCodeInsightFixtureTest
|
||||
val importInsertHelper = ImportInsertHelper.getInstance(project)
|
||||
val psiDocumentManager = PsiDocumentManager.getInstance(project)
|
||||
|
||||
stats().perfTest(
|
||||
stats().perfTest<Unit, String>(
|
||||
testName = testName,
|
||||
setUp = {
|
||||
fixture.configureByFile(testPath)
|
||||
@@ -90,11 +90,12 @@ abstract class AbstractPerformanceImportTest : KotlinLightCodeInsightFixtureTest
|
||||
fileText = file.text
|
||||
},
|
||||
test = {
|
||||
project.executeWriteCommand<String?>("") {
|
||||
it.value = project.executeWriteCommand<String?>("") {
|
||||
perfTestCore(file, fqName, filter, descriptorName, importInsertHelper, psiDocumentManager)
|
||||
}
|
||||
},
|
||||
tearDown = { log: String? ->
|
||||
tearDown = {
|
||||
val log = it.value
|
||||
KotlinTestUtils.assertEqualsToFile(File("$testPath.after"), fixture.file.text)
|
||||
if (log != null) {
|
||||
val logFile = File("$testPath.log")
|
||||
@@ -104,8 +105,9 @@ abstract class AbstractPerformanceImportTest : KotlinLightCodeInsightFixtureTest
|
||||
TestCase.assertFalse(logFile.exists())
|
||||
}
|
||||
}
|
||||
commitAllDocuments()
|
||||
FileDocumentManager.getInstance().reloadFromDisk(editor.document)
|
||||
runWriteAction {
|
||||
myFixture.file.delete()
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
CodeStyle.dropTemporarySettings(project)
|
||||
|
||||
+9
-8
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.AbstractJavaToKotlinCopyPasteConversionTest
|
||||
import org.jetbrains.kotlin.idea.conversion.copy.ConvertJavaCopyPasteProcessor
|
||||
@@ -44,13 +46,8 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
|
||||
}
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
commitAllDocuments()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
private fun doWarmUpPerfTest() {
|
||||
stats().perfTest(
|
||||
stats().perfTest<Unit, Unit>(
|
||||
testName = "warm-up",
|
||||
setUp = {
|
||||
with(myFixture) {
|
||||
@@ -64,9 +61,13 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
|
||||
myFixture.performEditorAction(IdeActions.ACTION_PASTE)
|
||||
},
|
||||
tearDown = {
|
||||
commitAllDocuments()
|
||||
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()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -85,7 +86,7 @@ abstract class AbstractPerformanceJavaToKotlinCopyPasteConversionTest(private va
|
||||
val fileText = myFixture.editor.document.text
|
||||
val noConversionExpected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// NO_CONVERSION_EXPECTED").isNotEmpty()
|
||||
|
||||
stats().perfTest(
|
||||
stats().perfTest<Unit, Unit>(
|
||||
testName = testName,
|
||||
setUp = {
|
||||
myFixture.configureByFiles("$testName.java")
|
||||
|
||||
+253
-48
@@ -5,51 +5,82 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.perf
|
||||
|
||||
import com.intellij.codeInsight.daemon.*
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl.waitForAllEditorsFinallyLoaded
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.codeInspection.ex.InspectionProfileImpl
|
||||
import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory
|
||||
import com.intellij.ide.highlighter.ModuleFileType
|
||||
import com.intellij.ide.impl.ProjectUtil
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl
|
||||
import com.intellij.idea.IdeaTestApplication
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.lang.ExternalAnnotatorsFilter
|
||||
import com.intellij.lang.LanguageAnnotators
|
||||
import com.intellij.lang.StdLanguages
|
||||
import com.intellij.lang.injection.InjectedLanguageManager
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.module.ModuleTypeId
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
import com.intellij.openapi.project.impl.ProjectImpl
|
||||
import com.intellij.openapi.projectRoots.JavaSdk
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
|
||||
import com.intellij.openapi.roots.FileIndexFacade
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.startup.StartupManager
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFileManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import com.intellij.testFramework.RunAll
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.impl.search.IndexPatternBuilder
|
||||
import com.intellij.psi.xml.XmlFileNSInfoProvider
|
||||
import com.intellij.testFramework.*
|
||||
import com.intellij.testFramework.fixtures.EditorTestFixture
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
|
||||
import com.intellij.testFramework.propertyBased.MadTestingUtil
|
||||
import com.intellij.util.ThrowableRunnable
|
||||
import com.intellij.util.indexing.UnindexedFilesUpdater
|
||||
import com.intellij.util.io.exists
|
||||
import com.intellij.xml.XmlSchemaProvider
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionsManager
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptDependenciesManager
|
||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||
import org.jetbrains.kotlin.idea.core.util.toPsiFile
|
||||
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.invalidateLibraryCache
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectOpenProcessor
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
|
||||
// myProject is not required for all potential perf test cases
|
||||
private var myProject: Project? = null
|
||||
protected var myProject: Project? = null
|
||||
private lateinit var jdk18: Sdk
|
||||
private lateinit var myApplication: IdeaTestApplication
|
||||
|
||||
override fun isStressTest(): Boolean = true
|
||||
|
||||
override fun isPerformanceTest(): Boolean = false
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
@@ -71,7 +102,6 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
jdkTable.addJdk(internal, testRootDisposable)
|
||||
KotlinSdkType.setUpIfNeeded()
|
||||
}
|
||||
InspectionProfileImpl.INIT_INSPECTIONS = true
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
@@ -79,6 +109,9 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
ThrowableRunnable { super.tearDown() },
|
||||
ThrowableRunnable {
|
||||
if (myProject != null) {
|
||||
DaemonCodeAnalyzerSettings.getInstance().isImportHintEnabled = true // return default value to avoid unnecessary save
|
||||
(StartupManager.getInstance(myProject!!) as StartupManagerImpl).checkCleared()
|
||||
(DaemonCodeAnalyzer.getInstance(myProject!!) as DaemonCodeAnalyzerImpl).cleanupAfterTest()
|
||||
closeProject(myProject!!)
|
||||
myProject = null
|
||||
}
|
||||
@@ -100,7 +133,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
note: String,
|
||||
path: String = "idea/testData/perfTest"
|
||||
): Project {
|
||||
val projectPath = "$path/$name"
|
||||
val projectPath = File("$path/$name").canonicalPath
|
||||
|
||||
val warmUpIterations = 1
|
||||
val iterations = 3
|
||||
@@ -109,39 +142,126 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
var lastProject: Project? = null
|
||||
var counter = 0
|
||||
|
||||
stats.perfTest<Project, Project>(
|
||||
stats.perfTest<Unit, Pair<Project, Boolean>>(
|
||||
warmUpIterations = warmUpIterations,
|
||||
iterations = iterations,
|
||||
testName = "open project${if (note.isNotEmpty()) " $note" else ""}",
|
||||
test = {
|
||||
|
||||
val project = projectManagerEx.loadAndOpenProject(projectPath)!!
|
||||
if (!Paths.get(projectPath, ".idea").exists()) {
|
||||
val projectPathExists = Paths.get(projectPath, ".idea").exists()
|
||||
val project = if (projectPathExists) {
|
||||
val project = ProjectUtil.openProject(projectPath, null, false)!!
|
||||
project
|
||||
} else {
|
||||
val project = projectManagerEx.loadAndOpenProject(projectPath)!!
|
||||
initKotlinProject(project, projectPath, name)
|
||||
project
|
||||
}
|
||||
|
||||
(project as ProjectImpl).registerComponentImplementation(
|
||||
FileEditorManager::class.java,
|
||||
FileEditorManagerImpl::class.java
|
||||
)
|
||||
|
||||
projectManagerEx.openTestProject(project)
|
||||
|
||||
val changeListManagerImpl = ChangeListManager.getInstance(project) as ChangeListManagerImpl
|
||||
changeListManagerImpl.waitUntilRefreshed()
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
project
|
||||
},
|
||||
tearDown = { project ->
|
||||
lastProject = project
|
||||
val prj = project!!
|
||||
|
||||
// close all project but last - we're going to return and use it further
|
||||
if (counter < warmUpIterations + iterations - 1) {
|
||||
closeProject(prj)
|
||||
with(StartupManager.getInstance(project) as StartupManagerImpl) {
|
||||
scheduleInitialVfsRefresh()
|
||||
runPostStartupActivities()
|
||||
}
|
||||
|
||||
with(ChangeListManager.getInstance(project) as ChangeListManagerImpl) {
|
||||
waitUntilRefreshed()
|
||||
}
|
||||
|
||||
it.value = Pair(project, projectPathExists)
|
||||
},
|
||||
tearDown = {
|
||||
it.value?.let { pair ->
|
||||
val project = pair.first
|
||||
|
||||
// import gradle project if `$project/.idea` is present but modules are not imported
|
||||
// it is a temporary dirty hack as it is fixed in latest IC:
|
||||
// ProjectUtil.openProject picks up gradle import via extension point
|
||||
if (pair.second && ModuleManager.getInstance(project).modules.isEmpty()) {
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
val virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(projectPath)!!
|
||||
|
||||
FileDocumentManager.getInstance().saveAllDocuments()
|
||||
|
||||
GradleProjectOpenProcessor.openGradleProject(project, null, Paths.get(virtualFile.path))
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
runInEdtAndWait {
|
||||
PlatformTestUtil.saveProject(project)
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(
|
||||
"project has to have at least one module",
|
||||
ModuleManager.getInstance(project).modules.isNotEmpty()
|
||||
)
|
||||
|
||||
lastProject = project
|
||||
VirtualFileManager.getInstance().syncRefresh()
|
||||
|
||||
// close all project but last - we're going to return and use it further
|
||||
if (counter < warmUpIterations + iterations - 1) {
|
||||
closeProject(project)
|
||||
}
|
||||
counter++
|
||||
}
|
||||
counter++
|
||||
}
|
||||
)
|
||||
|
||||
// indexing
|
||||
lastProject?.let { project ->
|
||||
invalidateLibraryCache(project)
|
||||
|
||||
CodeInsightTestFixtureImpl.ensureIndexesUpToDate(project)
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
with(DumbService.getInstance(project)) {
|
||||
queueTask(UnindexedFilesUpdater(project))
|
||||
completeJustSubmittedTasks()
|
||||
}
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
enableAnnotatorsAndLoadDefinitions(project)
|
||||
}
|
||||
|
||||
return lastProject!!
|
||||
}
|
||||
|
||||
protected fun enableAnnotatorsAndLoadDefinitions() = enableAnnotatorsAndLoadDefinitions(myProject!!)
|
||||
|
||||
protected fun enableAnnotatorsAndLoadDefinitions(project: Project) {
|
||||
InjectedLanguageManager.getInstance(project) // zillion of Dom Sem classes
|
||||
LanguageAnnotators.INSTANCE.allForLanguage(JavaLanguage.INSTANCE) // pile of annotator classes loads
|
||||
LanguageAnnotators.INSTANCE.allForLanguage(StdLanguages.XML)
|
||||
LanguageAnnotators.INSTANCE.allForLanguage(KotlinLanguage.INSTANCE)
|
||||
DaemonAnalyzerTestCase.assertTrue(
|
||||
"side effect: to load extensions",
|
||||
ProblemHighlightFilter.EP_NAME.extensions.toMutableList()
|
||||
.plus(ImplicitUsageProvider.EP_NAME.extensions)
|
||||
.plus(XmlSchemaProvider.EP_NAME.extensions)
|
||||
.plus(XmlFileNSInfoProvider.EP_NAME.extensions)
|
||||
.plus(ExternalAnnotatorsFilter.EXTENSION_POINT_NAME.extensions)
|
||||
.plus(IndexPatternBuilder.EP_NAME.extensions).isNotEmpty()
|
||||
)
|
||||
// side effect: to load script definitions"
|
||||
val scriptDefinitionsManager = ScriptDefinitionsManager.getInstance(project)
|
||||
scriptDefinitionsManager.getAllDefinitions()
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
assertTrue(scriptDefinitionsManager.isReady())
|
||||
assertFalse(KotlinScriptingSettings.getInstance(project).isAutoReloadEnabled)
|
||||
}
|
||||
|
||||
|
||||
private fun initKotlinProject(
|
||||
project: Project,
|
||||
projectPath: String,
|
||||
@@ -166,7 +286,6 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
protected fun perfHighlightFile(name: String, stats: Stats): List<HighlightInfo> =
|
||||
perfHighlightFile(myProject!!, name, stats)
|
||||
|
||||
|
||||
protected fun perfHighlightFile(
|
||||
project: Project,
|
||||
fileName: String,
|
||||
@@ -174,42 +293,125 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
note: String = ""
|
||||
): List<HighlightInfo> {
|
||||
var highlightInfos: List<HighlightInfo> = emptyList()
|
||||
stats.perfTest(
|
||||
testName = "highlighting ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}",
|
||||
setUp = {
|
||||
val fileInEditor = openFileInEditor(project, fileName)
|
||||
fileInEditor.psiFile
|
||||
},
|
||||
test = { file ->
|
||||
highlightFile(file!!)
|
||||
},
|
||||
tearDown = {
|
||||
highlightInfos = it ?: emptyList()
|
||||
commitAllDocuments()
|
||||
}
|
||||
)
|
||||
IdentifierHighlighterPassFactory.doWithHighlightingEnabled {
|
||||
stats.perfTest<EditorFile, List<HighlightInfo>>(
|
||||
testName = "highlighting ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}",
|
||||
setUp = {
|
||||
it.setUpValue = openFileInEditor(project, fileName)
|
||||
},
|
||||
test = {
|
||||
val file = it.setUpValue
|
||||
it.value = highlightFile(project, file!!.psiFile)
|
||||
},
|
||||
tearDown = {
|
||||
highlightInfos = it.value ?: emptyList()
|
||||
commitAllDocuments()
|
||||
FileEditorManager.getInstance(project).closeFile(it.setUpValue!!.psiFile.virtualFile)
|
||||
PsiManager.getInstance(project).dropPsiCaches()
|
||||
}
|
||||
)
|
||||
}
|
||||
//println("${"-".repeat(40)}\n$fileName ->\n${highlightInfos.joinToString("\n")}\n")
|
||||
|
||||
return highlightInfos
|
||||
}
|
||||
|
||||
private fun highlightFile(psiFile: PsiFile): List<HighlightInfo> {
|
||||
private fun highlightFile(project: Project, psiFile: PsiFile): List<HighlightInfo> {
|
||||
val document = FileDocumentManager.getInstance().getDocument(psiFile.virtualFile)!!
|
||||
val editor = EditorFactory.getInstance().getEditors(document).first()
|
||||
return CodeInsightTestFixtureImpl.instantiateAndRun(psiFile, editor, intArrayOf(), false)
|
||||
val fixture = EditorTestFixture(project, editor, psiFile.virtualFile)
|
||||
return fixture.doHighlighting(true)
|
||||
}
|
||||
|
||||
data class EditorFile(val psiFile: PsiFile, val document: Document)
|
||||
protected fun perfFileAnalysis(name: String, stats: Stats, note: String = "") =
|
||||
perfFileAnalysis(myProject!!, name, stats, note = note)
|
||||
|
||||
private fun perfFileAnalysis(
|
||||
project: Project,
|
||||
fileName: String,
|
||||
stats: Stats,
|
||||
note: String = ""
|
||||
) {
|
||||
val disposable = Disposer.newDisposable("perfFileAnalysis $fileName")
|
||||
|
||||
MadTestingUtil.enableAllInspections(project, disposable)
|
||||
|
||||
try {
|
||||
IdentifierHighlighterPassFactory.doWithHighlightingEnabled {
|
||||
stats.perfTest(
|
||||
testName = "fileAnalysis ${if (note.isNotEmpty()) "$note " else ""}${simpleFilename(fileName)}",
|
||||
setUp = perfFileAnalysisSetUp(project, fileName),
|
||||
test = perfFileAnalysisTest(project),
|
||||
tearDown = perfFileAnalysisTearDown(fileName, project)
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
Disposer.dispose(disposable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisSetUp(
|
||||
project: Project,
|
||||
fileName: String
|
||||
): (TestData<EditorFile, List<HighlightInfo>>) -> Unit {
|
||||
return {
|
||||
val fileInEditor = openFileInEditor(project, fileName)
|
||||
|
||||
// Note: Kotlin scripts require dependencies to be loaded
|
||||
if (isAKotlinScriptFile(fileName)) {
|
||||
val vFile = fileInEditor.psiFile.virtualFile
|
||||
ScriptDependenciesManager.updateScriptDependenciesSynchronously(vFile, project)
|
||||
}
|
||||
|
||||
//enableHints(false)
|
||||
|
||||
println("fileAnalysis -> $fileName\n")
|
||||
it.setUpValue = fileInEditor
|
||||
}
|
||||
}
|
||||
|
||||
// quite simple impl - good so far
|
||||
fun isAKotlinScriptFile(fileName: String) = fileName.endsWith(".kts")
|
||||
|
||||
private fun perfFileAnalysisTest(project: Project): (TestData<EditorFile, List<HighlightInfo>>) -> Unit {
|
||||
return {
|
||||
val fileInEditor = it.setUpValue!!
|
||||
it.value = highlightFile(project, fileInEditor.psiFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisTearDown(
|
||||
fileName: String,
|
||||
project: Project
|
||||
): (TestData<EditorFile, List<HighlightInfo>>) -> Unit {
|
||||
return {
|
||||
commitAllDocuments()
|
||||
//println("fileAnalysis <- $fileName:\n${it.value?.joinToString("\n")}\n")
|
||||
println("fileAnalysis <- $fileName:\n${it.value?.size ?: 0} highlightInfos\n")
|
||||
FileEditorManager.getInstance(project).closeFile(it.setUpValue!!.psiFile.virtualFile)
|
||||
PsiManager.getInstance(project).dropPsiCaches()
|
||||
}
|
||||
}
|
||||
|
||||
private fun openFileInEditor(project: Project, name: String): EditorFile {
|
||||
val fileDocumentManager = FileDocumentManager.getInstance()
|
||||
val fileEditorManager = FileEditorManager.getInstance(project)
|
||||
|
||||
val psiFile = projectFileByName(project, name)
|
||||
val vFile = psiFile.virtualFile
|
||||
|
||||
FileDocumentManager.getInstance().reloadFiles(vFile)
|
||||
assertTrue("file $vFile is not indexed yet", FileIndexFacade.getInstance(project).isInContent(vFile))
|
||||
|
||||
runInEdtAndWait {
|
||||
fileEditorManager.openFile(vFile, true)
|
||||
}
|
||||
val document = fileDocumentManager.getDocument(vFile)!!
|
||||
|
||||
assertNotNull("doc not found for $vFile", EditorFactory.getInstance().getEditors(document))
|
||||
assertTrue("expected non empty doc", document.text.isNotEmpty())
|
||||
|
||||
waitForAllEditorsFinallyLoaded(project, 30, TimeUnit.SECONDS)
|
||||
|
||||
val fileEditorManager = FileEditorManager.getInstance(project)
|
||||
fileEditorManager.openFile(vFile, true)
|
||||
val document = FileDocumentManager.getInstance().getDocument(vFile)!!
|
||||
assertNotNull(EditorFactory.getInstance().getEditors(document))
|
||||
disposeOnTearDown(Disposable { fileEditorManager.closeFile(vFile) })
|
||||
return EditorFile(psiFile = psiFile, document = document)
|
||||
}
|
||||
|
||||
@@ -219,4 +421,7 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
val virtualFile = fileManager.refreshAndFindFileByUrl(url)
|
||||
return virtualFile!!.toPsiFile(project)!!
|
||||
}
|
||||
|
||||
private data class EditorFile(val psiFile: PsiFile, val document: Document)
|
||||
|
||||
}
|
||||
@@ -67,4 +67,36 @@ class PerformanceProjectsTest : AbstractPerformanceProjectsTest() {
|
||||
}
|
||||
}
|
||||
|
||||
fun testKotlinProjectHighlightBuildGradle() {
|
||||
tcSuite("Kotlin project highlight build gradle") {
|
||||
val stats = Stats("kotlin project highlight build gradle")
|
||||
stats.use {
|
||||
perfOpenProject("perfTestProject", stats = it, path = "..")
|
||||
|
||||
enableAnnotatorsAndLoadDefinitions()
|
||||
|
||||
perfFileAnalysisBuildGradleKts(it)
|
||||
perfFileAnalysisIdeaBuildGradleKts(it)
|
||||
perfFileAnalysisJpsGradleKts(it)
|
||||
perfFileAnalysisVersionGradleKts(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisBuildGradleKts(it: Stats) {
|
||||
perfFileAnalysis("build.gradle.kts", stats = it)
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisIdeaBuildGradleKts(it: Stats) {
|
||||
perfFileAnalysis("idea/build.gradle.kts", stats = it, note = "idea/")
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisJpsGradleKts(it: Stats) {
|
||||
perfFileAnalysis("gradle/jps.gradle.kts", stats = it, note = "gradle/")
|
||||
}
|
||||
|
||||
private fun perfFileAnalysisVersionGradleKts(it: Stats) {
|
||||
perfFileAnalysis("gradle/versions.gradle.kts", stats = it, note = "gradle/")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,22 +37,22 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
append(arrayOf(file, id, nanoTime.nsToMs))
|
||||
}
|
||||
|
||||
fun <T, K> perfTest(
|
||||
fun <K, T> perfTest(
|
||||
testName: String,
|
||||
warmUpIterations: Int = 3,
|
||||
iterations: Int = 10,
|
||||
setUp: () -> T? = { null },
|
||||
test: (t: T?) -> K,
|
||||
tearDown: (t: K?) -> Unit = {}
|
||||
setUp: (TestData<K, T>) -> Unit = { null },
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit = { null }
|
||||
) {
|
||||
val namePrefix = "$name: $testName"
|
||||
val timingsNs = LongArray(iterations)
|
||||
val errors = Array<Throwable?>(iterations, init = { null })
|
||||
|
||||
tcSuite(namePrefix) {
|
||||
warmUpPhase<K, T>(warmUpIterations, namePrefix, setUp, test, tearDown)
|
||||
warmUpPhase(warmUpIterations, namePrefix, setUp, test, tearDown)
|
||||
|
||||
mainPhase<K, T>(iterations, setUp, test, timingsNs, namePrefix, errors, tearDown)
|
||||
mainPhase(iterations, setUp, test, tearDown, timingsNs, namePrefix, errors)
|
||||
|
||||
val meanNs = timingsNs.average()
|
||||
val meanMs = meanNs.toLong().nsToMs
|
||||
@@ -81,27 +81,29 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
|
||||
private fun <K, T> mainPhase(
|
||||
iterations: Int,
|
||||
setUp: () -> T?,
|
||||
test: (t: T?) -> K,
|
||||
setUp: (TestData<K, T>) -> Unit,
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit,
|
||||
timingsNs: LongArray,
|
||||
namePrefix: String,
|
||||
errors: Array<Throwable?>,
|
||||
tearDown: (t: K?) -> Unit
|
||||
errors: Array<Throwable?>
|
||||
) {
|
||||
val testData = TestData<K, T>(null, null)
|
||||
try {
|
||||
for (attempt in 0 until iterations) {
|
||||
val setupValue: T? = setUp()
|
||||
var value: K? = null
|
||||
testData.reset()
|
||||
setUp(testData)
|
||||
try {
|
||||
val spentNs = measureNanoTime {
|
||||
value = test(setupValue)
|
||||
test(testData)
|
||||
}
|
||||
timingsNs[attempt] = spentNs
|
||||
} catch (t: Throwable) {
|
||||
println("error at $namePrefix #$attempt:")
|
||||
t.printStackTrace()
|
||||
errors[attempt] = t
|
||||
} finally {
|
||||
tearDown(value)
|
||||
tearDown(testData)
|
||||
}
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
@@ -113,27 +115,34 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
private fun <K, T> warmUpPhase(
|
||||
warmUpIterations: Int,
|
||||
namePrefix: String,
|
||||
setUp: () -> T?,
|
||||
test: (t: T?) -> K,
|
||||
tearDown: (t: K?) -> Unit
|
||||
setUp: (TestData<K, T>) -> Unit,
|
||||
test: (TestData<K, T>) -> Unit,
|
||||
tearDown: (TestData<K, T>) -> Unit
|
||||
) {
|
||||
val testData = TestData<K, T>(null, null)
|
||||
for (attempt in 0 until warmUpIterations) {
|
||||
testData.reset()
|
||||
val n = "$namePrefix warm-up #$attempt"
|
||||
println("##teamcity[testStarted name='$n' captureStandardOutput='true']")
|
||||
|
||||
try {
|
||||
val setupValue: T? = setUp()
|
||||
var value: K? = null
|
||||
setUp(testData)
|
||||
var spentNs: Long = 0
|
||||
try {
|
||||
spentNs = measureNanoTime {
|
||||
value = test(setupValue)
|
||||
test(testData)
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
println("error at $n:")
|
||||
println("error at $n:\n")
|
||||
|
||||
t.printStackTrace()
|
||||
|
||||
println("\n")
|
||||
|
||||
tcPrintErrors(n, listOf(t))
|
||||
throw t
|
||||
} finally {
|
||||
tearDown(value)
|
||||
tearDown(testData)
|
||||
}
|
||||
val spentMs = spentNs.nsToMs
|
||||
println("##teamcity[buildStatisticValue key='$n' value='$spentMs']")
|
||||
@@ -153,6 +162,13 @@ class Stats(val name: String = "", val header: Array<String> = arrayOf("Name", "
|
||||
}
|
||||
}
|
||||
|
||||
data class TestData<SV, V>(var setUpValue: SV?, var value: V?) {
|
||||
fun reset() {
|
||||
setUpValue = null
|
||||
value = null
|
||||
}
|
||||
}
|
||||
|
||||
inline fun tcSuite(name: String, block: () -> Unit) {
|
||||
println("##teamcity[testSuiteStarted name='$name']")
|
||||
block()
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.intellij.lang.injection.InjectedLanguageManager
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ex.ApplicationEx
|
||||
import com.intellij.openapi.application.runWriteAction
|
||||
import com.intellij.openapi.projectRoots.JavaSdk
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
|
||||
@@ -43,7 +44,7 @@ abstract class WholeProjectPerformanceTest : DaemonAnalyzerTestCase(), WholeProj
|
||||
|
||||
IdeaTestApplication.getInstance()
|
||||
// to prevent leaked SDKs: 1.8 and Kotlin SDK
|
||||
ApplicationManager.getApplication().runWriteAction {
|
||||
runWriteAction {
|
||||
val jdkTableImpl = JavaAwareProjectJdkTableImpl.getInstanceEx()
|
||||
val homePath = if (jdkTableImpl.internalJdk.homeDirectory!!.name == "jre") {
|
||||
jdkTableImpl.internalJdk.homeDirectory!!.parent.path
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase
|
||||
import com.intellij.testFramework.EdtTestUtil
|
||||
import com.intellij.util.ThrowableRunnable
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.kotlin.idea.parameterInfo.HintType
|
||||
|
||||
fun commitAllDocuments() {
|
||||
ProjectManagerEx.getInstanceEx().openProjects.forEach { project ->
|
||||
@@ -23,8 +25,23 @@ fun commitAllDocuments() {
|
||||
}
|
||||
}
|
||||
|
||||
fun enableHints(enable: Boolean) =
|
||||
HintType.values().forEach { it.option.set(enable) }
|
||||
|
||||
fun runInEdtAndWait(block: () -> Unit) {
|
||||
EdtTestUtil.runInEdtAndWait(ThrowableRunnable {
|
||||
block()
|
||||
})
|
||||
}
|
||||
|
||||
fun dispatchAllInvocationEvents() {
|
||||
runInEdtAndWait {
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
}
|
||||
}
|
||||
|
||||
fun closeProject(project: Project) {
|
||||
commitAllDocuments()
|
||||
dispatchAllInvocationEvents()
|
||||
val projectManagerEx = ProjectManagerEx.getInstanceEx()
|
||||
projectManagerEx.forceCloseProject(project, true)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase
|
||||
import com.intellij.testFramework.EdtTestUtil
|
||||
import com.intellij.util.ThrowableRunnable
|
||||
import com.intellij.util.ui.UIUtil
|
||||
|
||||
fun commitAllDocuments() {
|
||||
ProjectManagerEx.getInstanceEx().openProjects.forEach { project ->
|
||||
@@ -23,8 +24,17 @@ fun commitAllDocuments() {
|
||||
}
|
||||
}
|
||||
|
||||
fun enableHints(enable: Boolean) =
|
||||
HintType.values().forEach { it.option.set(enable) }
|
||||
|
||||
fun runInEdtAndWait(block: () -> Unit) {
|
||||
EdtTestUtil.runInEdtAndWait(ThrowableRunnable {
|
||||
block()
|
||||
})
|
||||
}
|
||||
|
||||
fun closeProject(project: Project) {
|
||||
commitAllDocuments()
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
val projectManagerEx = ProjectManagerEx.getInstanceEx()
|
||||
projectManagerEx.closeAndDispose(project)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user