[NPW|Assets] fix: wait for project wizard tracked project configurations (Reformat code, VF and PSI file resolution)

Issues: IDEA-349863, IDEA-341180

GitOrigin-RevId: bf359aaea23f21c2843d17aab12c0bc656224190
This commit is contained in:
Sergei Vorobyov
2024-09-17 15:03:23 +02:00
committed by intellij-monorepo-bot
parent 58244594be
commit 4b5a4a8a97
4 changed files with 86 additions and 30 deletions

View File

@@ -33,6 +33,7 @@
<orderEntry type="library" name="org.codehaus.groovy:groovy" level="project" />
<orderEntry type="module" module-name="intellij.java.impl.refactorings" />
<orderEntry type="module" module-name="intellij.platform.debugger.impl" />
<orderEntry type="module" module-name="intellij.platform.backend.observation" />
</component>
<component name="copyright">
<Base>

View File

@@ -28,6 +28,7 @@ import com.intellij.projectImport.ProjectImportProvider;
import com.intellij.testFramework.HeavyPlatformTestCase;
import com.intellij.testFramework.IndexingTestUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.TestObservation;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
@@ -37,6 +38,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -124,6 +126,7 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
UIUtil.dispatchAllInvocationEvents();
IndexingTestUtil.waitUntilIndexesAreReady(myCreatedProject);
TestObservation.waitForConfiguration(TimeUnit.MINUTES.toMillis(10), myCreatedProject, LOG::debug);
return myCreatedProject;
}
@@ -133,7 +136,13 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
}
private Module createModuleFromWizard(@NotNull Project project) {
return new NewModuleAction().createModuleFromWizard(project, null, myWizard);
Module createdModule = new NewModuleAction().createModuleFromWizard(project, null, myWizard);
UIUtil.dispatchAllInvocationEvents();
IndexingTestUtil.waitUntilIndexesAreReady(project);
TestObservation.waitForConfiguration(TimeUnit.MINUTES.toMillis(10), project, LOG::debug);
return createdModule;
}
private static void setSelectedTemplate(@NotNull Step step, @NotNull String group, @Nullable String name) {

View File

@@ -0,0 +1,70 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework
import com.intellij.diagnostic.ThreadDumper
import com.intellij.diagnostic.dumpCoroutines
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.platform.backend.observation.Observation
import com.intellij.testFramework.concurrency.waitForPromiseAndPumpEdt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import org.jetbrains.concurrency.asPromise
import java.util.function.Consumer
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
object TestObservation {
@JvmStatic
@JvmOverloads
fun waitForConfiguration(timeout: Long, project: Project, messageCallback: Consumer<String>? = null) {
waitForConfiguration(timeout.milliseconds, project, messageCallback?.let { it::accept })
}
fun waitForConfiguration(timeout: Duration, project: Project, messageCallback: ((String) -> Unit)? = null) {
val coroutineScope = CoroutineScopeService.getCoroutineScope(project)
val job = coroutineScope.launch {
awaitConfiguration(timeout, project, messageCallback)
}
val promise = job.asPromise()
promise.waitForPromiseAndPumpEdt(Duration.INFINITE)
}
suspend fun awaitConfiguration(timeout: Duration, project: Project, messageCallback: ((String) -> Unit)? = null) {
try {
withTimeout(timeout) {
Observation.awaitConfiguration(project, messageCallback)
}
}
catch (_: TimeoutCancellationException) {
throwWaitingTimoutError(timeout)
}
}
private fun throwWaitingTimoutError(timeout: Duration): Nothing {
val coroutineDump = dumpCoroutines()
val threadDump = ThreadDumper.dumpThreadsToString()
throw AssertionError("""
|The waiting takes too long. Expected to take no more than $timeout ms.
|------- Thread dump begin -------
|$threadDump
|-------- Thread dump end --------
|------ Coroutine dump begin -----
|$coroutineDump
|------- Coroutine dump end ------
""".trimMargin())
}
@Service(Service.Level.PROJECT)
private class CoroutineScopeService(private val coroutineScope: CoroutineScope) {
companion object {
fun getCoroutineScope(project: Project): CoroutineScope {
return project.service<CoroutineScopeService>().coroutineScope
}
}
}
}

View File

@@ -5,8 +5,6 @@ package org.jetbrains.plugins.gradle.testFramework.util
import com.intellij.build.BuildProgressListener
import com.intellij.build.output.BuildOutputParser
import com.intellij.diagnostic.ThreadDumper
import com.intellij.diagnostic.dumpCoroutines
import com.intellij.execution.ExecutionListener
import com.intellij.execution.ExecutionManager
import com.intellij.execution.process.ProcessHandler
@@ -26,14 +24,12 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.ThrowableComputable
import com.intellij.openapi.util.use
import com.intellij.platform.backend.observation.ActivityKey
import com.intellij.platform.backend.observation.Observation
import com.intellij.platform.backend.observation.trackActivity
import com.intellij.testFramework.ExtensionTestUtil
import com.intellij.testFramework.TestObservation
import com.intellij.testFramework.common.DEFAULT_TEST_TIMEOUT
import com.intellij.testFramework.observable.operation.core.waitForOperationAndPumpEdt
import com.intellij.testFramework.withProjectAsync
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.withTimeout
import org.jetbrains.annotations.Nls
import org.jetbrains.plugins.gradle.execution.build.output.GradleOutputDispatcherFactory
import org.jetbrains.plugins.gradle.util.GradleConstants
@@ -43,41 +39,21 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
private val DEFAULT_SYNC_TIMEOUT: Duration = 10.minutes
private val LOG = Logger.getInstance(TestGradleProjectConfigurationActivityKey::class.java)
private object TestGradleProjectConfigurationActivityKey: ActivityKey {
override val presentableName: @Nls String
get() = "The test Gradle project configuration"
}
val LOG = Logger.getInstance(TestGradleProjectConfigurationActivityKey::class.java)
suspend fun awaitGradleOpenProjectConfiguration(openProject: suspend () -> Project): Project {
return openProject()
.withProjectAsync { awaitConfiguration(DEFAULT_SYNC_TIMEOUT, it, LOG::debug) }
.withProjectAsync { TestObservation.awaitConfiguration(DEFAULT_SYNC_TIMEOUT, it, LOG::debug) }
}
suspend fun <R> awaitGradleProjectConfiguration(project: Project, action: suspend () -> R): R {
return project.trackActivity(TestGradleProjectConfigurationActivityKey, action)
.also { awaitConfiguration(DEFAULT_SYNC_TIMEOUT, project, LOG::debug) }
}
suspend fun awaitConfiguration(timeout: Duration, project: Project, messageCallback: ((String) -> Unit)? = null) {
try {
withTimeout(timeout) {
Observation.awaitConfiguration(project, messageCallback)
}
}
catch (e: TimeoutCancellationException) {
val coroutineDump = dumpCoroutines()
val threadDump = ThreadDumper.dumpThreadsToString()
throw AssertionError("""
|The waiting takes too long
|------- Thread dump begin -------
|$threadDump
|-------- Thread dump end --------
|------ Coroutine dump begin -----
|$coroutineDump
|------- Coroutine dump end ------
""".trimMargin())
}
.also { TestObservation.awaitConfiguration(DEFAULT_SYNC_TIMEOUT, project, LOG::debug) }
}
fun <R> waitForAnyGradleTaskExecution(action: ThrowableComputable<R, Throwable>): R {