diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java index 4d921d5d9454..14e3931eb283 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java @@ -25,6 +25,8 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.startup.StartupManager; @@ -41,6 +43,7 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry import com.intellij.psi.xml.XmlFileNSInfoProvider; import com.intellij.testFramework.*; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; +import com.intellij.util.ThrowableRunnable; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.XmlSchemaProvider; import it.unimi.dsi.fastutil.ints.IntArrayList; @@ -109,6 +112,16 @@ public abstract class DaemonAnalyzerTestCase extends JavaCodeInsightTestCase { } } + // when running very long tasks (e.g. during stress/perf tests) CoreProgressManager might decide to de-prioritize background processes, + // defeating the whole purpose. Do not let him do that. + @Override + protected void runTestRunnable(@NotNull ThrowableRunnable testRunnable) throws Throwable { + ((CoreProgressManager)ProgressManager.getInstance()).suppressAllDeprioritizationsDuringLongTestsExecutionIn(()-> { + super.runTestRunnable(testRunnable); + return null; + }); + } + protected final void enableInspectionTool(@NotNull InspectionProfileEntry tool) { InspectionsKt.enableInspectionTool(getProject(), tool, getTestRootDisposable()); } diff --git a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java index f07a6a42a72a..2810a694bd12 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java @@ -839,7 +839,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable { } protected boolean sleepIfNeededToGivePriorityToAnotherThread() { - if (!isCurrentThreadEffectivelyPrioritized() && isLowPriorityReallyApplicable()) { + if (isDeprioritizationEnabled() && !isCurrentThreadEffectivelyPrioritized() && isLowPriorityReallyApplicable()) { LockSupport.parkNanos(1_000_000); avoidBlockingPrioritizingThread(); return true; @@ -919,6 +919,21 @@ public class CoreProgressManager extends ProgressManager implements Disposable { return false; } + private boolean isDeprioritizationEnabled() { + return myDeprioritizations.get() < 1_000_000; + } + @TestOnly + @ApiStatus.Internal + public T suppressAllDeprioritizationsDuringLongTestsExecutionIn(@NotNull ThrowableComputable runnable) throws E { + myDeprioritizations.addAndGet(1_000_000); + try { + return runnable.compute(); + } + finally { + myDeprioritizations.addAndGet(-1_000_000); + } + } + @NotNull public static ModalityState getCurrentThreadProgressModality() { ProgressIndicator indicator = threadTopLevelIndicators.get(Thread.currentThread().getId()); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index fc0fae47659e..77138cfe4a28 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -84,6 +84,8 @@ import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; @@ -257,48 +259,50 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig DaemonCodeAnalyzerSettings settings = DaemonCodeAnalyzerSettings.getInstance(); ProjectInspectionProfileManager.getInstance(project); // avoid "severities changed, restart" event - ProcessCanceledException exception = null; - int retries = 1000; - for (int i = 0; i < retries; i++) { - int oldDelay = settings.getAutoReparseDelay(); - try { - settings.setAutoReparseDelay(0); - List infos = new ArrayList<>(); - EdtTestUtil.runInEdtAndWait(() -> { - codeAnalyzer.runPasses(file, editor.getDocument(), Collections.singletonList(textEditor), toIgnore, canChangeDocument, null); - IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current(); - if (policy != null) { - policy.waitForHighlighting(project, editor); - } - IdentifierHighlighterPassFactory.waitForIdentifierHighlighting(); - infos.addAll(DaemonCodeAnalyzerImpl.getHighlights(editor.getDocument(), null, project)); - if (readEditorMarkupModel) { - MarkupModelEx markupModel = (MarkupModelEx)editor.getMarkupModel(); - DaemonCodeAnalyzerEx.processHighlights(markupModel, project, null, 0, editor.getDocument().getTextLength(), - Processors.cancelableCollectProcessor(infos)); - } - }); - infos.addAll(DaemonCodeAnalyzerEx.getInstanceEx(project).getFileLevelHighlights(project, file)); - return infos; - } - catch (ProcessCanceledException e) { - Throwable cause = e.getCause(); - if (cause != null && cause.getClass() != Throwable.class) { - // canceled because of an exception, no need to repeat the same - throw e; + return ((CoreProgressManager)ProgressManager.getInstance()).suppressAllDeprioritizationsDuringLongTestsExecutionIn(() -> { + ProcessCanceledException exception = null; + int retries = 1000; + for (int i = 0; i < retries; i++) { + int oldDelay = settings.getAutoReparseDelay(); + try { + settings.setAutoReparseDelay(0); + List infos = new ArrayList<>(); + EdtTestUtil.runInEdtAndWait(() -> { + codeAnalyzer.runPasses(file, editor.getDocument(), Collections.singletonList(textEditor), toIgnore, canChangeDocument, null); + IdeaTestExecutionPolicy policy = IdeaTestExecutionPolicy.current(); + if (policy != null) { + policy.waitForHighlighting(project, editor); + } + IdentifierHighlighterPassFactory.waitForIdentifierHighlighting(); + infos.addAll(DaemonCodeAnalyzerImpl.getHighlights(editor.getDocument(), null, project)); + if (readEditorMarkupModel) { + MarkupModelEx markupModel = (MarkupModelEx)editor.getMarkupModel(); + DaemonCodeAnalyzerEx.processHighlights(markupModel, project, null, 0, editor.getDocument().getTextLength(), + Processors.cancelableCollectProcessor(infos)); + } + }); + infos.addAll(DaemonCodeAnalyzerEx.getInstanceEx(project).getFileLevelHighlights(project, file)); + return infos; } + catch (ProcessCanceledException e) { + Throwable cause = e.getCause(); + if (cause != null && cause.getClass() != Throwable.class) { + // canceled because of an exception, no need to repeat the same + throw e; + } - EdtTestUtil.runInEdtAndWait(() -> { - PsiDocumentManager.getInstance(project).commitAllDocuments(); - UIUtil.dispatchAllInvocationEvents(); - }); - exception = e; + EdtTestUtil.runInEdtAndWait(() -> { + PsiDocumentManager.getInstance(project).commitAllDocuments(); + UIUtil.dispatchAllInvocationEvents(); + }); + exception = e; + } + finally { + settings.setAutoReparseDelay(oldDelay); + } } - finally { - settings.setAutoReparseDelay(oldDelay); - } - } - throw new AssertionError("Unable to highlight after " + retries + " retries", exception); + throw new AssertionError("Unable to highlight after " + retries + " retries", exception); + }); } public static void ensureIndexesUpToDate(@NotNull Project project) {