From 801995bcb71205345307a66f85a160e68ca1d0cc Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 25 May 2016 14:06:47 +0300 Subject: [PATCH] vcs: BackgroundTaskQueue - run task synchronously in launcher thread in tests restore original behaviour --- .../openapi/progress/BackgroundTaskQueue.java | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 4b1d81477b91..dfa0e2302114 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -17,6 +17,7 @@ package com.intellij.openapi.progress; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator; @@ -40,7 +41,8 @@ public class BackgroundTaskQueue { @NotNull private final String myTitle; @NotNull private final QueueProcessor myProcessor; - private boolean myForceAsyncInTests = false; + @NotNull private final Object TEST_TASK_LOCK = new Object(); + private volatile boolean myForceAsyncInTests = false; public BackgroundTaskQueue(@Nullable Project project, @NotNull String title) { myTitle = title; @@ -56,6 +58,7 @@ public class BackgroundTaskQueue { indicator = new EmptyProgressIndicator(); } else { + // BackgroundableProcessIndicator should be created from EDT indicator = new BackgroundableProcessIndicator(task); } } @@ -102,7 +105,13 @@ public class BackgroundTaskQueue { } public void run(@NotNull Task.Backgroundable task, @Nullable ModalityState modalityState, @Nullable ProgressIndicator indicator) { - myProcessor.add(new TaskData(task, modalityState, indicator), modalityState); + TaskData taskData = new TaskData(task, modalityState, indicator); + if (!myForceAsyncInTests && ApplicationManager.getApplication().isUnitTestMode()) { + runTaskInCurrentThread(taskData); + } + else { + myProcessor.add(taskData, modalityState); + } } private static class TaskData { @@ -119,7 +128,6 @@ public class BackgroundTaskQueue { @TestOnly public void setForceAsyncInTests(boolean value, @Nullable Disposable disposable) { - ApplicationManager.getApplication().assertIsDispatchThread(); myForceAsyncInTests = value; if (disposable != null) { Disposer.register(disposable, new Disposable() { @@ -130,4 +138,55 @@ public class BackgroundTaskQueue { }); } } + + private void runTaskInCurrentThread(@NotNull TaskData data) { + Task.Backgroundable task = data.task; + + ProgressIndicator indicator = data.indicator; + if (indicator == null) indicator = new EmptyProgressIndicator(); + + ModalityState modalityState = data.modalityState; + if (modalityState == null) modalityState = ModalityState.NON_MODAL; + + boolean processCanceled = false; + Exception exception = null; + try { + synchronized (TEST_TASK_LOCK) { + task.run(indicator); + } + } + catch (ProcessCanceledException e) { + processCanceled = true; + } + catch (Exception e) { + exception = e; + } + + final boolean finalCanceled = processCanceled || indicator.isCanceled(); + final Exception finalException = exception; + Runnable finishTask = () -> { + try { + if (finalException != null) { + task.onError(finalException); + } + else if (finalCanceled) { + task.onCancel(); + } + else { + task.onSuccess(); + } + } + finally { + task.onFinished(); + } + }; + + Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + finishTask.run(); + } + else { + application.invokeLater(finishTask, modalityState); + } + } }