IDE perf tests for K/N: check successful Gradle project import
This commit is contained in:
+2
@@ -82,6 +82,8 @@ abstract class AbstractPerformanceProjectsTest : UsefulTestCase() {
|
||||
jdkTable.addJdk(internal, testRootDisposable)
|
||||
KotlinSdkType.setUpIfNeeded()
|
||||
}
|
||||
|
||||
GradleProcessOutputInterceptor.install(testRootDisposable)
|
||||
}
|
||||
|
||||
protected fun warmUpProject(stats: Stats, vararg filesToHighlight: String, openProject: () -> Project) {
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.testFramework
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener.EP_NAME as EP
|
||||
import com.intellij.testFramework.ExtensionTestUtil.maskExtensions
|
||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.lang.Exception
|
||||
import kotlin.test.assertNull
|
||||
|
||||
interface GradleProcessOutputInterceptor {
|
||||
companion object {
|
||||
fun getInstance(): GradleProcessOutputInterceptor? = EP.extensions.firstIsInstanceOrNull()
|
||||
|
||||
fun install(parentDisposable: Disposable) {
|
||||
val installedExtensions = EP.extensions
|
||||
|
||||
assertNull(
|
||||
installedExtensions.firstIsInstanceOrNull<GradleProcessOutputInterceptor>(),
|
||||
"Another ${GradleProcessOutputInterceptor::class.java.simpleName} is already installed"
|
||||
)
|
||||
|
||||
maskExtensions(
|
||||
EP,
|
||||
listOf(GradleProcessOutputInterceptorImpl()) + installedExtensions,
|
||||
parentDisposable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun reset()
|
||||
fun getOutput(): String
|
||||
}
|
||||
|
||||
private class GradleProcessOutputInterceptorImpl : GradleProcessOutputInterceptor, ExternalSystemTaskNotificationListener {
|
||||
private val buffer = StringBuilder()
|
||||
|
||||
override fun onTaskOutput(id: ExternalSystemTaskId, text: String, stdOut: Boolean) {
|
||||
if (id.projectSystemId == GRADLE_SYSTEM_ID && text.isNotEmpty())
|
||||
buffer.append(text)
|
||||
}
|
||||
|
||||
override fun reset() = buffer.setLength(0)
|
||||
override fun getOutput() = buffer.toString()
|
||||
|
||||
override fun onSuccess(id: ExternalSystemTaskId) = Unit
|
||||
override fun onFailure(id: ExternalSystemTaskId, e: Exception) = Unit
|
||||
override fun onStatusChange(event: ExternalSystemTaskNotificationEvent) = Unit
|
||||
override fun onCancel(id: ExternalSystemTaskId) = Unit
|
||||
override fun onEnd(id: ExternalSystemTaskId) = Unit
|
||||
override fun beforeCancel(id: ExternalSystemTaskId) = Unit
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
override fun onStart(id: ExternalSystemTaskId) = Unit
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.testFramework
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener
|
||||
import com.intellij.testFramework.PlatformTestUtil.maskExtensions
|
||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import kotlin.test.assertNull
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener.EP_NAME as EP
|
||||
|
||||
interface GradleProcessOutputInterceptor {
|
||||
companion object {
|
||||
fun getInstance(): GradleProcessOutputInterceptor? = EP.extensions.firstIsInstanceOrNull()
|
||||
|
||||
fun install(parentDisposable: Disposable) {
|
||||
val installedExtensions = EP.extensions
|
||||
|
||||
assertNull(
|
||||
installedExtensions.firstIsInstanceOrNull<GradleProcessOutputInterceptor>(),
|
||||
"Another ${GradleProcessOutputInterceptor::class.java.simpleName} is already installed"
|
||||
)
|
||||
|
||||
maskExtensions(
|
||||
EP,
|
||||
listOf(GradleProcessOutputInterceptorImpl()) + installedExtensions,
|
||||
parentDisposable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun reset()
|
||||
fun getOutput(): String
|
||||
}
|
||||
|
||||
private class GradleProcessOutputInterceptorImpl : GradleProcessOutputInterceptor, ExternalSystemTaskNotificationListener {
|
||||
private val buffer = StringBuilder()
|
||||
|
||||
override fun onTaskOutput(id: ExternalSystemTaskId, text: String, stdOut: Boolean) {
|
||||
if (id.projectSystemId == GRADLE_SYSTEM_ID && text.isNotEmpty())
|
||||
buffer.append(text)
|
||||
}
|
||||
|
||||
override fun reset() = buffer.setLength(0)
|
||||
override fun getOutput() = buffer.toString()
|
||||
|
||||
override fun onSuccess(id: ExternalSystemTaskId) = Unit
|
||||
override fun onFailure(id: ExternalSystemTaskId, e: Exception) = Unit
|
||||
override fun onStatusChange(event: ExternalSystemTaskNotificationEvent) = Unit
|
||||
override fun onCancel(id: ExternalSystemTaskId) = Unit
|
||||
override fun onEnd(id: ExternalSystemTaskId) = Unit
|
||||
override fun beforeCancel(id: ExternalSystemTaskId) = Unit
|
||||
override fun onQueued(id: ExternalSystemTaskId, workingDir: String?) = Unit
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
override fun onStart(id: ExternalSystemTaskId) = Unit
|
||||
}
|
||||
+5
@@ -85,6 +85,11 @@ enum class ProjectOpenAction {
|
||||
|
||||
refreshGradleProject(projectPath, project)
|
||||
|
||||
assertTrue(
|
||||
ModuleManager.getInstance(project).modules.isNotEmpty(),
|
||||
"Gradle project $projectName at $projectPath has to have at least one module"
|
||||
)
|
||||
|
||||
return project
|
||||
}
|
||||
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.testFramework
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.guessProjectDir
|
||||
import java.io.Closeable
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.fail
|
||||
|
||||
class StatefulTestGradleProjectRefreshCallback(
|
||||
private val projectPath: String,
|
||||
private val project: Project
|
||||
) : ExternalProjectRefreshCallback, Closeable {
|
||||
|
||||
private class Error(val message: String, val details: String? = null)
|
||||
|
||||
private var alreadyUsed = false
|
||||
private var error: Error? = null
|
||||
|
||||
init {
|
||||
GradleProcessOutputInterceptor.getInstance()?.reset()
|
||||
}
|
||||
|
||||
override fun onSuccess(externalProject: DataNode<ProjectData>?) {
|
||||
checkAlreadyUsed()
|
||||
|
||||
if (externalProject == null) {
|
||||
error = Error("Got null external project after Gradle import")
|
||||
return
|
||||
}
|
||||
ServiceManager.getService(ProjectDataManager::class.java).importData(externalProject, project, true)
|
||||
}
|
||||
|
||||
override fun onFailure(errorMessage: String, errorDetails: String?) {
|
||||
checkAlreadyUsed()
|
||||
|
||||
error = Error(errorMessage, errorDetails)
|
||||
}
|
||||
|
||||
override fun close() = assertError()
|
||||
|
||||
fun assertError() {
|
||||
val error = error ?: return
|
||||
|
||||
val failure = buildString {
|
||||
appendln("Gradle import failed for ${project.name} at $projectPath")
|
||||
|
||||
project.guessProjectDir()
|
||||
|
||||
append("=".repeat(40)).appendln(" Error message:")
|
||||
appendln(error.message.trimEnd())
|
||||
|
||||
append("=".repeat(40)).appendln(" Error details:")
|
||||
appendln(error.details?.trimEnd().orEmpty())
|
||||
|
||||
append("=".repeat(40)).appendln(" Gradle process output:")
|
||||
appendln(GradleProcessOutputInterceptor.getInstance()?.getOutput()?.trimEnd() ?: "<interceptor not installed>")
|
||||
|
||||
appendln("=".repeat(40))
|
||||
}
|
||||
|
||||
fail(failure)
|
||||
}
|
||||
|
||||
private fun checkAlreadyUsed() {
|
||||
assertFalse(
|
||||
alreadyUsed,
|
||||
"${StatefulTestGradleProjectRefreshCallback::class.java} can be used only once." +
|
||||
" Please create a new instance of ${StatefulTestGradleProjectRefreshCallback::class.java} every time you" +
|
||||
" do import from Gradle."
|
||||
)
|
||||
|
||||
alreadyUsed = true
|
||||
}
|
||||
}
|
||||
+9
-35
@@ -5,13 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.testFramework
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
@@ -58,41 +53,20 @@ private fun _attachGradleProjectAndRefresh(
|
||||
ExternalSystemUtil.ensureToolWindowInitialized(project, GradleConstants.SYSTEM_ID)
|
||||
}
|
||||
}
|
||||
//ExternalProjectsManagerImpl.getInstance(project).setStoreExternally(false)
|
||||
|
||||
ExternalProjectsManagerImpl.disableProjectWatcherAutoUpdate(project)
|
||||
val settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||
settings.linkProject(gradleProjectSettings)
|
||||
}
|
||||
//ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, false, ProgressExecutionMode.MODAL_SYNC)
|
||||
|
||||
val progressExecutionMode = ProgressExecutionMode.MODAL_SYNC
|
||||
val externalSystemId = GradleConstants.SYSTEM_ID
|
||||
val callback = object : ExternalProjectRefreshCallback {
|
||||
override fun onFailure(errorMessage: String, errorDetails: String?) {
|
||||
super.onFailure(errorMessage, errorDetails)
|
||||
throw RuntimeException(errorMessage)
|
||||
}
|
||||
|
||||
override fun onFailure(
|
||||
externalTaskId: ExternalSystemTaskId,
|
||||
errorMessage: String,
|
||||
errorDetails: String?
|
||||
) {
|
||||
super.onFailure(externalTaskId, errorMessage, errorDetails)
|
||||
throw RuntimeException(errorMessage)
|
||||
}
|
||||
|
||||
override fun onSuccess(externalProject: DataNode<ProjectData>?) {
|
||||
if (externalProject == null) {
|
||||
return
|
||||
}
|
||||
val synchronous = progressExecutionMode == ProgressExecutionMode.MODAL_SYNC
|
||||
ServiceManager.getService(
|
||||
ProjectDataManager::class.java
|
||||
).importData(externalProject, project, synchronous)
|
||||
}
|
||||
StatefulTestGradleProjectRefreshCallback(externalProjectPath, project).use { callback ->
|
||||
ExternalSystemUtil.refreshProject(
|
||||
externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.callback(callback)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
ExternalSystemUtil.refreshProject(project, externalSystemId, externalProjectPath, callback, false, progressExecutionMode, true)
|
||||
}
|
||||
|
||||
+10
-33
@@ -5,50 +5,27 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.testFramework
|
||||
|
||||
import com.intellij.ide.impl.ProjectUtil
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.runInEdtAndWait
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
import org.jetbrains.plugins.gradle.service.project.GradleProjectOpenProcessor
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
|
||||
fun refreshGradleProject(projectPath: String, project: Project) {
|
||||
GradleProjectOpenProcessor.openGradleProject(project, null, Paths.get(projectPath))
|
||||
|
||||
val gradleArguments = System.getProperty("kotlin.test.gradle.import.arguments")
|
||||
ExternalSystemUtil.refreshProjects(
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.forceWhenUptodate()
|
||||
.useDefaultCallback()
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.also {
|
||||
gradleArguments?.run(it::withArguments)
|
||||
}
|
||||
)
|
||||
StatefulTestGradleProjectRefreshCallback(projectPath, project).use { callback ->
|
||||
ExternalSystemUtil.refreshProjects(
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.forceWhenUptodate()
|
||||
.withArguments(System.getProperty("kotlin.test.gradle.import.arguments"))
|
||||
.callback(callback)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
}
|
||||
|
||||
fun openGradleProject(projectPath: String, project: Project) {
|
||||
dispatchAllInvocationEvents()
|
||||
|
||||
val virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(projectPath)!!
|
||||
|
||||
FileDocumentManager.getInstance().saveAllDocuments()
|
||||
|
||||
val path = Paths.get(virtualFile.path)
|
||||
GradleProjectOpenProcessor.openGradleProject(project, null, path)
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
runInEdtAndWait {
|
||||
PlatformTestUtil.saveProject(project)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.testFramework
|
||||
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
@@ -16,10 +17,11 @@ import org.jetbrains.plugins.gradle.service.project.open.setupGradleSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
fun refreshGradleProject(projectPath: String, project: Project) {
|
||||
_importProject(projectPath, project)
|
||||
_importProject(File(projectPath).absolutePath, project)
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
}
|
||||
@@ -55,6 +57,14 @@ private fun _attachGradleProjectAndRefresh(
|
||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||
settings.linkProject(gradleProjectSettings)
|
||||
}
|
||||
//ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, true, ProgressExecutionMode.MODAL_SYNC)
|
||||
ExternalSystemUtil.refreshProject(project, GradleConstants.SYSTEM_ID, externalProjectPath, false, ProgressExecutionMode.MODAL_SYNC)
|
||||
|
||||
StatefulTestGradleProjectRefreshCallback(externalProjectPath, project).use { callback ->
|
||||
ExternalSystemUtil.refreshProject(
|
||||
externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.callback(callback)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user