diff --git a/java/compiler/impl/src/com/intellij/compiler/progress/BuildViewServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/progress/BuildViewServiceImpl.java index 022663a308cf..53064da662bf 100644 --- a/java/compiler/impl/src/com/intellij/compiler/progress/BuildViewServiceImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/progress/BuildViewServiceImpl.java @@ -119,11 +119,11 @@ public class BuildViewServiceImpl implements BuildViewService { public void onEnd(Object sessionId, ExitStatus exitStatus, long endBuildStamp) { String message; if (exitStatus == ExitStatus.ERRORS) { - message = JavaCompilerBundle.message("compiler.build.messages.failed", wordsToBeginFromLowerCase(myContentName)); + message = BuildBundle.message("build.messages.failed", wordsToBeginFromLowerCase(myContentName)); myBuildProgress.fail(endBuildStamp, message); } else if (exitStatus == ExitStatus.CANCELLED) { - message = JavaCompilerBundle.message("compiler.build.messages.cancelled", wordsToBeginFromLowerCase(myContentName)); + message = BuildBundle.message("build.messages.cancelled", wordsToBeginFromLowerCase(myContentName)); myBuildProgress.cancel(endBuildStamp, message); } else { @@ -136,7 +136,8 @@ public class BuildViewServiceImpl implements BuildViewService { myBuildProgress.output(JavaCompilerBundle.message("compiler.build.messages.classes.check.outdated"), true); } } - myBuildProgress.finish(endBuildStamp, isUpToDate); + message = BuildBundle.message("build.messages.finished", wordsToBeginFromLowerCase(myContentName)); + myBuildProgress.finish(endBuildStamp, isUpToDate, message); } } diff --git a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties index 8b174463deea..33f4a0350c37 100644 --- a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties +++ b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties @@ -22,8 +22,6 @@ compiler.error.exception=Error: {0} status.compilation.aborted=Compilation aborted status.all.up.to.date=All files are up-to-date compiler.error.failed.to.delete=Failed to delete {0} -compiler.build.messages.failed={0} failed -compiler.build.messages.cancelled={0} cancelled compiler.build.messages.classes.check.uptodate=Build results are up-to-date for requested compile scope.\nSubsequent incremental build wouldn't do anything. compiler.build.messages.classes.check.outdated=Build results are outdated for requested compile scope.\nSubsequent incremental build will compile files for changed sources and remove obsolete results of the previous build. progress.updating.caches=Updating caches... diff --git a/java/compiler/tests/com/intellij/compiler/progress/CompilerBuildViewTest.kt b/java/compiler/tests/com/intellij/compiler/progress/CompilerBuildViewTest.kt new file mode 100644 index 000000000000..9114626f6672 --- /dev/null +++ b/java/compiler/tests/com/intellij/compiler/progress/CompilerBuildViewTest.kt @@ -0,0 +1,114 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.compiler.progress + +import com.intellij.compiler.BaseCompilerTestCase +import com.intellij.openapi.Disposable +import com.intellij.openapi.compiler.CompileStatusNotification +import com.intellij.openapi.module.Module +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.registry.Registry +import com.intellij.testFramework.RunAll +import com.intellij.testFramework.fixtures.BuildViewTestFixture +import com.intellij.util.ThrowableRunnable + +class CompilerBuildViewTest : BaseCompilerTestCase() { + + private lateinit var buildViewTestFixture: BuildViewTestFixture + private val testDisposable: Disposable = object : Disposable { + override fun dispose() { + } + } + + @Throws(Exception::class) + public override fun setUp() { + super.setUp() + buildViewTestFixture = BuildViewTestFixture(project) + buildViewTestFixture.setUp() + val registryValue = Registry.get("ide.jps.use.build.tool.window") + registryValue.setValue(true, testDisposable) + } + + public override fun tearDown() { + RunAll() + .append(ThrowableRunnable { if (::buildViewTestFixture.isInitialized) buildViewTestFixture.tearDown() }) + .append(ThrowableRunnable { Disposer.dispose(testDisposable) }) + .append(ThrowableRunnable { super.tearDown() }) + .run() + } + + fun `test empty build`() { + make(compilerManager.createProjectCompileScope(myProject)) + buildViewTestFixture.assertBuildViewTreeEquals("-\n build finished") + buildViewTestFixture.assertBuildViewSelectedNode("build finished", "", false) + + rebuildProject(false) + buildViewTestFixture.assertBuildViewTreeEquals("-\n rebuild finished") + buildViewTestFixture.assertBuildViewSelectedNode("rebuild finished", "", false) + + compile(compilerManager.createProjectCompileScope(myProject), true) + buildViewTestFixture.assertBuildViewTreeEquals("-\n recompile finished") + buildViewTestFixture.assertBuildViewSelectedNode("recompile finished", "", false) + } + + fun `test successful build`() { + val file = createFile("src/A.java", "public class A {}") + val srcRoot = file.parent + val module = addModule("a", srcRoot) + build(module) + buildViewTestFixture.assertBuildViewTreeEquals("-\n build finished") + + rebuildProject() + buildViewTestFixture.assertBuildViewTreeEquals("-\n rebuild finished") + + rebuild(module) + buildViewTestFixture.assertBuildViewTreeEquals("-\n recompile finished") + } + + fun `test build with compile error`() { + val file = createFile("src/A.java", "public class A a{}foo") + val srcRoot = file.parent + val module = addModule("a", srcRoot) + build(module, true) + buildViewTestFixture.assertBuildViewTreeEquals( + "-\n" + + " -build failed\n" + + " -src/A.java\n" + + " '{' expected\n" + + " reached end of file while parsing" + ) + + rebuildProject(true) + buildViewTestFixture.assertBuildViewTreeEquals( + "-\n" + + " -rebuild failed\n" + + " -src/A.java\n" + + " '{' expected\n" + + " reached end of file while parsing" + ) + + rebuild(module, true) + buildViewTestFixture.assertBuildViewTreeEquals( + "-\n" + + " -recompile failed\n" + + " -src/A.java\n" + + " '{' expected\n" + + " reached end of file while parsing" + ) + } + + private fun build(module: Module, errorsExpected: Boolean = false): CompilationLog? { + val compileScope = compilerManager.createModuleCompileScope(module, false) + return compile(compileScope, false, errorsExpected) + } + + private fun rebuild(module: Module, errorsExpected: Boolean = false): CompilationLog? { + val compileScope = compilerManager.createModuleCompileScope(module, false) + return compile(compileScope, true, errorsExpected) + } + + private fun rebuildProject(errorsExpected: Boolean = false): CompilationLog? { + return compile(errorsExpected) { compileStatusNotification: CompileStatusNotification? -> + compilerManager.rebuild(compileStatusNotification) + } + } +} \ No newline at end of file diff --git a/platform/lang-impl/resources/messages/BuildBundle.properties b/platform/lang-impl/resources/messages/BuildBundle.properties new file mode 100644 index 000000000000..17cc831088d9 --- /dev/null +++ b/platform/lang-impl/resources/messages/BuildBundle.properties @@ -0,0 +1,7 @@ +build.status.finished=finished +build.status.failed=failed +build.status.cancelled=cancelled +build.status.running=running... +build.messages.finished={0} finished +build.messages.failed={0} failed +build.messages.cancelled={0} cancelled \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/build/BuildBundle.java b/platform/lang-impl/src/com/intellij/build/BuildBundle.java new file mode 100644 index 000000000000..e99fe2038788 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/build/BuildBundle.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.build; + +import com.intellij.DynamicBundle; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.PropertyKey; + +import java.util.function.Supplier; + +public class BuildBundle extends DynamicBundle { + @NonNls private static final String BUNDLE = "messages.BuildBundle"; + private static final BuildBundle INSTANCE = new BuildBundle(); + + private BuildBundle() { + super(BUNDLE); + } + + @NotNull + public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getMessage(key, params); + } + + @NotNull + public static Supplier messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, Object @NotNull ... params) { + return INSTANCE.getLazyMessage(key, params); + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/build/BuildView.java b/platform/lang-impl/src/com/intellij/build/BuildView.java index 0a99fd87edc4..338dca598779 100644 --- a/platform/lang-impl/src/com/intellij/build/BuildView.java +++ b/platform/lang-impl/src/com/intellij/build/BuildView.java @@ -152,10 +152,11 @@ public class BuildView extends CompositeView Disposer.register(this, runContentDescriptor); } } - if (myExecutionConsole != null) { - myExecutionConsole.getComponent(); //create editor to be able to add console editor actions + ExecutionConsole executionConsole = myExecutionConsole; + if (executionConsole != null) { + executionConsole.getComponent(); //create editor to be able to add console editor actions if (myViewSettingsProvider.isExecutionViewHidden() || !myViewSettingsProvider.isSideBySideView()) { - addViewAndShowIfNeeded(myExecutionConsole, CONSOLE_VIEW_NAME, myViewManager.isConsoleEnabledByDefault()); + addViewAndShowIfNeeded(executionConsole, CONSOLE_VIEW_NAME, myViewManager.isConsoleEnabledByDefault()); } } diff --git a/platform/lang-impl/src/com/intellij/build/MultipleBuildsView.java b/platform/lang-impl/src/com/intellij/build/MultipleBuildsView.java index 8b17100ec501..cb25c21499e7 100644 --- a/platform/lang-impl/src/com/intellij/build/MultipleBuildsView.java +++ b/platform/lang-impl/src/com/intellij/build/MultipleBuildsView.java @@ -280,7 +280,12 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable { consoleComponent.add(tb.getComponent(), BorderLayout.WEST); myContent = new ContentImpl(consoleComponent, myViewManager.getViewName(), true); - Disposer.register(myContent, this); + Disposer.register(myContent, new Disposable() { + @Override + public void dispose() { + Disposer.dispose(MultipleBuildsView.this); + } + }); Disposer.register(myContent, new Disposable() { @Override public void dispose() { diff --git a/platform/lang-impl/src/com/intellij/build/progress/BuildProgress.java b/platform/lang-impl/src/com/intellij/build/progress/BuildProgress.java index e1a87cc0f08b..6463377ea15f 100644 --- a/platform/lang-impl/src/com/intellij/build/progress/BuildProgress.java +++ b/platform/lang-impl/src/com/intellij/build/progress/BuildProgress.java @@ -34,7 +34,7 @@ public interface BuildProgress { @NotNull BuildProgress finish(boolean isUpToDate); - @NotNull BuildProgress finish(long timeStamp, boolean isUpToDate); + @NotNull BuildProgress finish(long timeStamp, boolean isUpToDate, @NotNull String message); @NotNull BuildProgress fail(); diff --git a/platform/lang-impl/src/com/intellij/build/progress/BuildProgressImpl.java b/platform/lang-impl/src/com/intellij/build/progress/BuildProgressImpl.java index 634082ab7076..0ef26da8a3cc 100644 --- a/platform/lang-impl/src/com/intellij/build/progress/BuildProgressImpl.java +++ b/platform/lang-impl/src/com/intellij/build/progress/BuildProgressImpl.java @@ -125,28 +125,28 @@ class BuildProgressImpl implements BuildProgr @NotNull @Override public BuildProgress finish() { - return finish(System.currentTimeMillis(), false); + return finish(false); } @NotNull @Override public BuildProgress finish(boolean isUpToDate) { - return finish(System.currentTimeMillis(), isUpToDate); + return finish(System.currentTimeMillis(), isUpToDate, myDescriptor.getTitle()); } @NotNull @Override public BuildProgress finish(long timeStamp) { - return finish(timeStamp, false); + return finish(timeStamp, false, myDescriptor.getTitle()); } @NotNull @Override - public BuildProgress finish(long timeStamp, boolean isUpToDate) { + public BuildProgress finish(long timeStamp, boolean isUpToDate, @NotNull String message) { assertStarted(); assert myParentProgress != null; EventResult result = new SuccessResultImpl(isUpToDate); - FinishEvent event = new FinishEventImpl(getId(), myParentProgress.getId(), timeStamp, myDescriptor.getTitle(), result); + FinishEvent event = new FinishEventImpl(getId(), myParentProgress.getId(), timeStamp, message, result); myListener.onEvent(getBuildId(), event); return myParentProgress; } diff --git a/platform/lang-impl/src/com/intellij/build/progress/BuildRootProgressImpl.java b/platform/lang-impl/src/com/intellij/build/progress/BuildRootProgressImpl.java index 38788e1479a5..3afdb35ba7f2 100644 --- a/platform/lang-impl/src/com/intellij/build/progress/BuildRootProgressImpl.java +++ b/platform/lang-impl/src/com/intellij/build/progress/BuildRootProgressImpl.java @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.build.progress; +import com.intellij.build.BuildBundle; import com.intellij.build.BuildProgressListener; import com.intellij.build.events.FinishBuildEvent; import com.intellij.build.events.FinishEvent; @@ -27,14 +28,19 @@ public class BuildRootProgressImpl extends BuildProgressImpl finish() { + return finish(System.currentTimeMillis(), false, BuildBundle.message("build.status.finished")); } @NotNull @Override - public BuildProgress finish(long timeStamp, boolean isUpToDate) { + public BuildProgress finish(long timeStamp, boolean isUpToDate, @NotNull String message) { assertStarted(); - FinishEvent event = new FinishBuildEventImpl(getId(), null, timeStamp, "finished", new SuccessResultImpl(isUpToDate)); + FinishEvent event = new FinishBuildEventImpl(getId(), null, timeStamp, message, new SuccessResultImpl(isUpToDate)); myListener.onEvent(getBuildId(), event); return this; } @@ -42,10 +48,9 @@ public class BuildRootProgressImpl extends BuildProgressImpl fail() { - return fail(System.currentTimeMillis(), "failed"); + return fail(System.currentTimeMillis(), BuildBundle.message("build.status.failed")); } - @NotNull @Override public BuildRootProgressImpl fail(long timeStamp, @NotNull String message) { @@ -58,7 +63,7 @@ public class BuildRootProgressImpl extends BuildProgressImpl cancel() { - return cancel(System.currentTimeMillis(), "cancelled"); + return cancel(System.currentTimeMillis(), BuildBundle.message("build.status.cancelled")); } @NotNull diff --git a/platform/lang-impl/testSources/com/intellij/build/BuildViewTest.kt b/platform/lang-impl/testSources/com/intellij/build/BuildViewTest.kt new file mode 100644 index 000000000000..d485bd8c2636 --- /dev/null +++ b/platform/lang-impl/testSources/com/intellij/build/BuildViewTest.kt @@ -0,0 +1,155 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.build + +import com.intellij.build.events.MessageEvent.Kind.ERROR +import com.intellij.build.events.MessageEvent.Kind.INFO +import com.intellij.build.progress.BuildProgressDescriptor +import com.intellij.testFramework.LightPlatformTestCase +import com.intellij.testFramework.RunAll +import com.intellij.testFramework.fixtures.BuildViewTestFixture +import com.intellij.util.ThrowableRunnable +import org.junit.After +import org.junit.Before +import org.junit.Test +import java.io.File + +class BuildViewTest : LightPlatformTestCase() { + + private lateinit var buildViewTestFixture: BuildViewTestFixture + + @Before + override fun setUp() { + super.setUp() + buildViewTestFixture = BuildViewTestFixture(project) + buildViewTestFixture.setUp() + } + + @After + override fun tearDown() { + RunAll() + .append(ThrowableRunnable { if (::buildViewTestFixture.isInitialized) buildViewTestFixture.tearDown() }) + .append(ThrowableRunnable { super.tearDown() }) + .run() + } + + @Test + fun `test successful build`() { + val title = "A build" + val buildDescriptor = DefaultBuildDescriptor(Object(), title, "", System.currentTimeMillis()) + val progressDescriptor = object : BuildProgressDescriptor { + override fun getBuildDescriptor(): BuildDescriptor = buildDescriptor + override fun getTitle(): String = title + } + + // @formatter:off + BuildViewManager + .newBuildProgress(project) + .start(progressDescriptor) + .message("Root message", "Tex of the root message console", INFO, null) + .progress("Running ...") + .startChildProgress("Inner progress") + .fileMessage("File message1", "message1 descriptive text", INFO, FilePosition(File("aFile.java"), 0, 0)) + .fileMessage("File message2", "message2 descriptive text", INFO, FilePosition(File("aFile.java"), 0, 0)) + .finish() + .finish() + // @formatter:on + + buildViewTestFixture.assertBuildViewTreeEquals( + """ + - + -finished + Root message + -Inner progress + -aFile.java + File message1 + File message2 + """.trimIndent() + ) + + buildViewTestFixture.assertBuildViewSelectedNode("finished", "", false) + buildViewTestFixture.assertBuildViewSelectedNode("Root message", "Tex of the root message console\n", false) + buildViewTestFixture.assertBuildViewSelectedNode( + "File message1", + "aFile.java\n" + + "message1 descriptive text", + false + ) + } + + @Test + fun `test build with errors`() { + val title = "A build" + val buildDescriptor = DefaultBuildDescriptor(Object(), title, "", System.currentTimeMillis()) + val progressDescriptor = object : BuildProgressDescriptor { + override fun getBuildDescriptor(): BuildDescriptor = buildDescriptor + override fun getTitle(): String = title + } + + // @formatter:off + BuildViewManager + .newBuildProgress(project) + .start(progressDescriptor) + .message("Root message", "Tex of the root message console", INFO, null) + .progress("Running ...") + .startChildProgress("Inner progress") + .fileMessage("File message1", "message1 descriptive text", ERROR, FilePosition(File("aFile.java"), 0, 0)) + .fileMessage("File message2", "message2 descriptive text", ERROR, FilePosition(File("aFile.java"), 0, 0)) + .fail() + .fail() + // @formatter:on + + buildViewTestFixture.assertBuildViewTreeEquals( + """ + - + -failed + Root message + -Inner progress + -aFile.java + File message1 + File message2 + """.trimIndent() + ) + + buildViewTestFixture.assertBuildViewSelectedNode( + "File message1", + "aFile.java\n" + + "message1 descriptive text" + ) + buildViewTestFixture.assertBuildViewSelectedNode("failed", "", false) + buildViewTestFixture.assertBuildViewSelectedNode("Root message", "Tex of the root message console\n", false) + } + + @Test + fun `test cancelled build`() { + val title = "A build" + val buildDescriptor = DefaultBuildDescriptor(Object(), title, "", System.currentTimeMillis()) + val progressDescriptor = object : BuildProgressDescriptor { + override fun getBuildDescriptor(): BuildDescriptor = buildDescriptor + override fun getTitle(): String = title + } + + // @formatter:off + BuildViewManager + .newBuildProgress(project) + .start(progressDescriptor) + .message("Root message", "Tex of the root message console", INFO, null) + .progress("Running ...") + .startChildProgress("Inner progress") + .cancel() + .cancel() + // @formatter:on + + buildViewTestFixture.assertBuildViewTreeEquals( + """ + - + -cancelled + Root message + Inner progress + """.trimIndent() + ) + + buildViewTestFixture.assertBuildViewSelectedNode("cancelled", "", false) + buildViewTestFixture.assertBuildViewSelectedNode("Root message", "Tex of the root message console\n", false) + buildViewTestFixture.assertBuildViewSelectedNode("Inner progress", "", false) + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/BuildViewTestFixture.kt b/platform/testFramework/src/com/intellij/testFramework/fixtures/BuildViewTestFixture.kt new file mode 100644 index 000000000000..59d43f361bf7 --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/BuildViewTestFixture.kt @@ -0,0 +1,226 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.testFramework.fixtures + +import com.intellij.build.* +import com.intellij.openapi.Disposable +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Disposer +import com.intellij.testFramework.* +import com.intellij.testFramework.UsefulTestCase.assertSameElements +import com.intellij.util.ThrowableRunnable +import com.intellij.util.concurrency.Semaphore +import com.intellij.util.ui.tree.TreeUtil +import junit.framework.TestCase +import junit.framework.TestCase.assertEquals +import javax.swing.tree.DefaultMutableTreeNode + +class BuildViewTestFixture(private val myProject: Project) : IdeaTestFixture { + + private val fixtureDisposable: Disposable = object : Disposable { + override fun dispose() { + } + } + private lateinit var syncViewManager: TestSyncViewManager + private lateinit var buildViewManager: TestBuildViewManager + + @Throws(Exception::class) + override fun setUp() { + myProject.replaceService( + BuildContentManager::class.java, + BuildContentManagerImpl(myProject), fixtureDisposable) + syncViewManager = TestSyncViewManager(myProject) + myProject.replaceService(SyncViewManager::class.java, syncViewManager, fixtureDisposable) + buildViewManager = TestBuildViewManager(myProject) + myProject.replaceService(BuildViewManager::class.java, buildViewManager, fixtureDisposable) + } + + @Throws(Exception::class) + override fun tearDown() = RunAll() + .append(ThrowableRunnable { if (::syncViewManager.isInitialized) syncViewManager.waitForPendingBuilds() }) + .append(ThrowableRunnable { if (::buildViewManager.isInitialized) buildViewManager.waitForPendingBuilds() }) + .append(ThrowableRunnable { Disposer.dispose(fixtureDisposable) }) + .run() + + fun assertSyncViewTreeEquals(executionTreeText: String) { + assertExecutionTree(syncViewManager, executionTreeText, false) + } + + fun assertSyncViewTreeSame(executionTreeText: String) { + assertExecutionTree(syncViewManager, executionTreeText, true) + } + + fun assertBuildViewTreeEquals(executionTree: String) { + assertExecutionTree(buildViewManager, executionTree, false) + } + + fun assertBuildViewTreeSame(executionTree: String) { + assertExecutionTree(buildViewManager, executionTree, true) + } + + fun assertSyncViewSelectedNode(nodeText: String, consoleText: String) { + assertExecutionTreeNode(syncViewManager, nodeText, { assertEquals(consoleText, it) }, true) + } + + fun assertSyncViewSelectedNode(nodeText: String, assertSelected: Boolean, consoleTextChecker: (String?) -> Unit) { + assertExecutionTreeNode(syncViewManager, nodeText, consoleTextChecker, assertSelected) + } + + fun getSyncViewRerunActions(): List { + val buildView = syncViewManager.buildsMap[syncViewManager.getRecentBuild()] + return BuildView.RESTART_ACTIONS.getData(buildView!!)!! + } + + fun getBuildViewRerunActions(): List { + val buildView = buildViewManager.buildsMap[syncViewManager.getRecentBuild()] + return BuildView.RESTART_ACTIONS.getData(buildView!!)!! + } + + fun assertBuildViewSelectedNode(nodeText: String, consoleText: String, assertSelected: Boolean = true) { + assertExecutionTreeNode(buildViewManager, nodeText, { assertEquals(consoleText, it) }, assertSelected) + } + + private fun assertExecutionTree(viewManager: TestViewManager, expected: String, ignoreTasksOrder: Boolean) { + viewManager.waitForPendingBuilds() + val recentBuild = viewManager.getRecentBuild() + val buildView = viewManager.getBuildsMap()[recentBuild] + assertExecutionTree(buildView!!, expected, ignoreTasksOrder) + } + + private fun assertExecutionTreeNode( + viewManager: TestViewManager, + nodeText: String, + consoleTextChecker: (String?) -> Unit, + assertSelected: Boolean + ) { + viewManager.waitForPendingBuilds() + val recentBuild = viewManager.getRecentBuild() + val buildView = viewManager.getBuildsMap()[recentBuild] + assertExecutionTreeNode(buildView!!, nodeText, + consoleTextChecker, + assertSelected) + } + + companion object { + fun assertExecutionTree(buildView: BuildView, expected: String, ignoreTasksOrder: Boolean) { + val eventView = buildView.getView(BuildTreeConsoleView::class.java.name, BuildTreeConsoleView::class.java) + eventView!!.addFilter { true } + val treeStringPresentation = runInEdtAndGet { + val tree = eventView.tree + PlatformTestUtil.dispatchAllEventsInIdeEventQueue() + PlatformTestUtil.waitWhileBusy(tree) + return@runInEdtAndGet PlatformTestUtil.print(tree, false) + } + if (ignoreTasksOrder) { + assertSameElements( + buildTasksNodesAsList( + treeStringPresentation.trim()), + buildTasksNodesAsList(expected.trim()) + ) + } + else { + assertEquals(expected.trim(), treeStringPresentation.trim()) + } + } + + fun assertExecutionTreeNode( + buildView: BuildView, + nodeText: String, + consoleTextChecker: (String?) -> Unit, + assertSelected: Boolean + ) { + val eventView = buildView.getView(BuildTreeConsoleView::class.java.name, BuildTreeConsoleView::class.java) + eventView!!.addFilter { true } + val tree = eventView.tree + val node = runInEdtAndGet { + PlatformTestUtil.dispatchAllEventsInIdeEventQueue() + PlatformTestUtil.waitWhileBusy(tree) + + TreeUtil.findNode(tree.model.root as DefaultMutableTreeNode) { + val userObject = it.userObject + userObject is ExecutionNode && userObject.name == nodeText + } + } + val selectedPathComponent = + if (!assertSelected && node != tree.selectionPath?.lastPathComponent) { + runInEdtAndGet { + TreeUtil.selectNode(tree, node) + PlatformTestUtil.dispatchAllEventsInIdeEventQueue() + PlatformTestUtil.waitWhileBusy(tree) + tree.selectionPath!!.lastPathComponent + } + } + else { + tree.selectionPath!!.lastPathComponent + } + if (node != selectedPathComponent) { + assertEquals(node.toString(), selectedPathComponent.toString()) + } + val selectedNodeConsoleText = runInEdtAndGet { eventView.selectedNodeConsoleText } + consoleTextChecker.invoke(selectedNodeConsoleText) + } + + private fun buildTasksNodesAsList(treeStringPresentation: String): List { + val list = mutableListOf() + val buffer = StringBuilder() + for (line in treeStringPresentation.lineSequence()) { + if (line.startsWith(" -") || line.startsWith(" :") || line.startsWith(" -")) { + list.add(buffer.toString()) + buffer.clear() + } + buffer.appendln(line) + } + if (buffer.isNotEmpty()) { + list.add(buffer.toString()) + } + return list + } + } + + private interface TestViewManager : ViewManager { + fun getBuildsMap(): MutableMap + fun waitForPendingBuilds() + fun getRecentBuild(): BuildDescriptor + } + + private class TestSyncViewManager(project: Project) : SyncViewManager(project), TestViewManager { + private val semaphore = Semaphore() + private lateinit var recentBuild: BuildDescriptor + override fun waitForPendingBuilds() = TestCase.assertTrue(semaphore.waitFor(1000)) + override fun getRecentBuild(): BuildDescriptor = recentBuild + override fun getBuildsMap(): MutableMap = super.getBuildsMap() + + override fun onBuildStart(buildDescriptor: BuildDescriptor) { + super.onBuildStart(buildDescriptor) + recentBuild = buildDescriptor + semaphore.down() + } + + override fun onBuildFinish(buildDescriptor: BuildDescriptor) { + super.onBuildFinish(buildDescriptor) + semaphore.up() + } + } + + private class TestBuildViewManager(project: Project) : BuildViewManager(project), TestViewManager { + private val semaphore = Semaphore() + private lateinit var recentBuild: BuildDescriptor + override fun waitForPendingBuilds() { + TestCase.assertTrue(semaphore.waitFor(1000)) + runInEdtAndWait { PlatformTestUtil.dispatchAllEventsInIdeEventQueue() } + } + + override fun getRecentBuild(): BuildDescriptor = recentBuild + override fun getBuildsMap(): MutableMap = super.getBuildsMap() + override fun onBuildStart(buildDescriptor: BuildDescriptor) { + super.onBuildStart(buildDescriptor) + recentBuild = buildDescriptor + semaphore.down() + } + + override fun onBuildFinish(buildDescriptor: BuildDescriptor?) { + super.onBuildFinish(buildDescriptor) + semaphore.up() + } + } +} \ No newline at end of file diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/execution/GradleRunAnythingProviderTestCase.kt b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/execution/GradleRunAnythingProviderTestCase.kt index d76fd4aecc3e..453c6c7c7795 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/execution/GradleRunAnythingProviderTestCase.kt +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/execution/GradleRunAnythingProviderTestCase.kt @@ -19,11 +19,11 @@ import com.intellij.openapi.util.Ref import com.intellij.openapi.util.text.StringUtil import com.intellij.testFramework.PlatformTestUtil.dispatchAllEventsInIdeEventQueue import com.intellij.testFramework.PlatformTestUtil.waitWhileBusy +import com.intellij.testFramework.fixtures.BuildViewTestFixture import com.intellij.util.TimeoutUtil import com.intellij.util.concurrency.Semaphore import groovyjarjarcommonscli.Option import org.assertj.core.api.Assertions.assertThat -import org.jetbrains.plugins.gradle.importing.BuildViewMessagesImportingTestCase import org.jetbrains.plugins.gradle.importing.GradleImportingTestCase import org.jetbrains.plugins.gradle.service.execution.cmd.GradleCommandLineOptionsProvider import org.junit.Assert @@ -170,11 +170,11 @@ abstract class GradleRunAnythingProviderTestCase : GradleImportingTestCase() { } fun BuildView.assertExecutionTree(expected: String): BuildView { - BuildViewMessagesImportingTestCase.assertExecutionTree(this, expected, false) + BuildViewTestFixture.assertExecutionTree(this, expected, false) return this } fun BuildView.assertExecutionTreeNode(nodeText: String, consoleTextChecker: (String?) -> Unit, assertSelected: Boolean = false): BuildView { - BuildViewMessagesImportingTestCase.assertExecutionTreeNode(this, nodeText, consoleTextChecker, assertSelected) + BuildViewTestFixture.assertExecutionTreeNode(this, nodeText, consoleTextChecker, assertSelected) return this } \ No newline at end of file diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/BuildViewMessagesImportingTestCase.kt b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/BuildViewMessagesImportingTestCase.kt index da15f21055d9..8430f395a59b 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/BuildViewMessagesImportingTestCase.kt +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/importing/BuildViewMessagesImportingTestCase.kt @@ -1,219 +1,66 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.gradle.importing -import com.intellij.build.* import com.intellij.openapi.externalSystem.util.ExternalSystemBundle -import com.intellij.openapi.project.Project -import com.intellij.testFramework.PlatformTestUtil import com.intellij.testFramework.RunAll -import com.intellij.testFramework.replaceService -import com.intellij.testFramework.runInEdtAndGet +import com.intellij.testFramework.fixtures.BuildViewTestFixture import com.intellij.util.ThrowableRunnable -import com.intellij.util.concurrency.Semaphore -import com.intellij.util.ui.tree.TreeUtil -import junit.framework.TestCase import org.jetbrains.plugins.gradle.util.GradleConstants -import javax.swing.tree.DefaultMutableTreeNode abstract class BuildViewMessagesImportingTestCase : GradleImportingTestCase() { - private lateinit var syncViewManager: TestSyncViewManager - private lateinit var buildViewManager: TestBuildViewManager + private lateinit var buildViewTestFixture: BuildViewTestFixture @Throws(Exception::class) override fun setUp() { super.setUp() currentExternalProjectSettings.delegatedBuild = true useProjectTaskManager = true - myProject.replaceService(BuildContentManager::class.java, BuildContentManagerImpl(myProject), testRootDisposable) - syncViewManager = TestSyncViewManager(myProject) - myProject.replaceService(SyncViewManager::class.java, syncViewManager, testRootDisposable) - buildViewManager = TestBuildViewManager(myProject) - myProject.replaceService(BuildViewManager::class.java, buildViewManager, testRootDisposable) + buildViewTestFixture = BuildViewTestFixture(myProject) + buildViewTestFixture.setUp() } override fun tearDown() = RunAll() - .append(ThrowableRunnable { if (::syncViewManager.isInitialized) syncViewManager.waitForPendingBuilds() }) - .append(ThrowableRunnable { if (::buildViewManager.isInitialized) buildViewManager.waitForPendingBuilds() }) + .append(ThrowableRunnable { if (::buildViewTestFixture.isInitialized) buildViewTestFixture.tearDown() }) .append(ThrowableRunnable { super.tearDown() }) .run() protected fun assertSyncViewTreeEquals(executionTreeText: String) { - assertExecutionTree(syncViewManager, executionTreeText, false) + buildViewTestFixture.assertSyncViewTreeEquals(executionTreeText) } protected fun assertSyncViewTreeSame(executionTreeText: String) { - assertExecutionTree(syncViewManager, executionTreeText, true) + buildViewTestFixture.assertSyncViewTreeSame(executionTreeText) } protected fun assertBuildViewTreeEquals(executionTree: String) { - assertExecutionTree(buildViewManager, executionTree, false) + buildViewTestFixture.assertBuildViewTreeEquals(executionTree) } protected fun assertBuildViewTreeSame(executionTree: String) { - assertExecutionTree(buildViewManager, executionTree, true) + buildViewTestFixture.assertBuildViewTreeSame(executionTree) } protected fun assertSyncViewSelectedNode(nodeText: String, consoleText: String) { - assertExecutionTreeNode(syncViewManager, nodeText, { assertEquals(consoleText, it) }, true) + buildViewTestFixture.assertSyncViewSelectedNode(nodeText, consoleText) } protected fun assertSyncViewSelectedNode(nodeText: String, assertSelected: Boolean, consoleTextChecker: (String?) -> Unit) { - assertExecutionTreeNode(syncViewManager, nodeText, consoleTextChecker, assertSelected) + buildViewTestFixture.assertSyncViewSelectedNode(nodeText, assertSelected, consoleTextChecker) } protected fun assertSyncViewRerunActions() { - val buildView = syncViewManager.buildsMap[syncViewManager.getRecentBuild()] - val rerunActions = BuildView.RESTART_ACTIONS.getData(buildView!!)!! + val rerunActions = buildViewTestFixture.getSyncViewRerunActions() assertSize(1, rerunActions) val reimportActionText = ExternalSystemBundle.message("action.refresh.project.text", GradleConstants.SYSTEM_ID.readableName) assertEquals(reimportActionText, rerunActions[0].templateText) } protected fun assertBuildViewSelectedNode(nodeText: String, consoleText: String) { - assertExecutionTreeNode(buildViewManager, nodeText, { assertEquals(consoleText, it) }, true) - } - - private fun assertExecutionTree(viewManager: TestViewManager, expected: String, ignoreTasksOrder: Boolean) { - viewManager.waitForPendingBuilds() - val recentBuild = viewManager.getRecentBuild() - val buildView = viewManager.getBuildsMap()[recentBuild] - assertExecutionTree(buildView!!, expected, ignoreTasksOrder) - } - - private fun assertExecutionTreeNode( - viewManager: TestViewManager, - nodeText: String, - consoleTextChecker: (String?) -> Unit, - assertSelected: Boolean - ) { - viewManager.waitForPendingBuilds() - val recentBuild = viewManager.getRecentBuild() - val buildView = viewManager.getBuildsMap()[recentBuild] - assertExecutionTreeNode(buildView!!, nodeText, consoleTextChecker, assertSelected) - } - - interface TestViewManager : ViewManager { - fun getBuildsMap(): MutableMap - fun waitForPendingBuilds() - fun getRecentBuild(): BuildDescriptor - } - - protected class TestSyncViewManager(project: Project) : - SyncViewManager(project), TestViewManager { - private val semaphore = Semaphore() - private lateinit var recentBuild: BuildDescriptor - override fun waitForPendingBuilds() = TestCase.assertTrue(semaphore.waitFor(1000)) - override fun getRecentBuild(): BuildDescriptor = recentBuild - override fun getBuildsMap(): MutableMap = super.getBuildsMap() - - override fun onBuildStart(buildDescriptor: BuildDescriptor) { - super.onBuildStart(buildDescriptor) - recentBuild = buildDescriptor - semaphore.down() - } - - override fun onBuildFinish(buildDescriptor: BuildDescriptor) { - super.onBuildFinish(buildDescriptor) - semaphore.up() - } - } - - protected class TestBuildViewManager(project: Project) : - BuildViewManager(project), TestViewManager { - private val semaphore = Semaphore() - private lateinit var recentBuild: BuildDescriptor - override fun waitForPendingBuilds() = TestCase.assertTrue(semaphore.waitFor(1000)) - override fun getRecentBuild(): BuildDescriptor = recentBuild - override fun getBuildsMap(): MutableMap = super.getBuildsMap() - override fun onBuildStart(buildDescriptor: BuildDescriptor) { - super.onBuildStart(buildDescriptor) - recentBuild = buildDescriptor - semaphore.down() - } - - override fun onBuildFinish(buildDescriptor: BuildDescriptor?) { - super.onBuildFinish(buildDescriptor) - semaphore.up() - } + buildViewTestFixture.assertBuildViewSelectedNode(nodeText, consoleText) } override fun handleImportFailure(errorMessage: String, errorDetails: String?) { // do not fail tests with failed builds } - - companion object { - fun assertExecutionTree(buildView: BuildView, expected: String, ignoreTasksOrder: Boolean) { - val eventView = buildView.getView(BuildTreeConsoleView::class.java.name, BuildTreeConsoleView::class.java) - eventView!!.addFilter { true } - val treeStringPresentation = runInEdtAndGet { - val tree = eventView.tree - PlatformTestUtil.dispatchAllEventsInIdeEventQueue() - PlatformTestUtil.waitWhileBusy(tree) - return@runInEdtAndGet PlatformTestUtil.print(tree, false) - } - if (ignoreTasksOrder) { - assertSameElements( - buildTasksNodesAsList(treeStringPresentation.trim()), - buildTasksNodesAsList(expected.trim()) - ) - } - else { - assertEquals(expected.trim(), treeStringPresentation.trim()) - } - } - - fun assertExecutionTreeNode( - buildView: BuildView, - nodeText: String, - consoleTextChecker: (String?) -> Unit, - assertSelected: Boolean - ) { - val eventView = buildView.getView(BuildTreeConsoleView::class.java.name, BuildTreeConsoleView::class.java) - eventView!!.addFilter { true } - val tree = eventView.tree - val node = runInEdtAndGet { - PlatformTestUtil.dispatchAllEventsInIdeEventQueue() - PlatformTestUtil.waitWhileBusy(tree) - - TreeUtil.findNode(tree.model.root as DefaultMutableTreeNode) { - val userObject = it.userObject - userObject is ExecutionNode && userObject.name == nodeText - } - } - val selectedPathComponent = - if (!assertSelected && node != tree.selectionPath?.lastPathComponent) { - runInEdtAndGet { - TreeUtil.selectNode(tree, node) - PlatformTestUtil.dispatchAllEventsInIdeEventQueue() - PlatformTestUtil.waitWhileBusy(tree) - tree.selectionPath!!.lastPathComponent - } - } - else { - tree.selectionPath!!.lastPathComponent - } - if (node != selectedPathComponent) { - assertEquals(node.toString(), selectedPathComponent.toString()) - } - val selectedNodeConsoleText = runInEdtAndGet { eventView.selectedNodeConsoleText } - consoleTextChecker.invoke(selectedNodeConsoleText) - } - - private fun buildTasksNodesAsList(treeStringPresentation: String): List { - val list = mutableListOf() - val buffer = StringBuilder() - for (line in treeStringPresentation.lineSequence()) { - if (line.startsWith(" -") || line.startsWith(" :") || line.startsWith(" -")) { - list.add(buffer.toString()) - buffer.clear() - } - buffer.appendln(line) - } - if (buffer.isNotEmpty()) { - list.add(buffer.toString()) - } - return list - } - } }