Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Loskutov2016-03-14 10:06:55 -0400
committerAndrey Loskutov2016-08-01 04:45:01 -0400
commitc668724f83ea175ecc55095039907e6620bcc13a (patch)
tree95b289c8d8c385cd7222eddfeca8436bdefafcfb
parent8124e2bb15eb3d3793ac8f160e83bddaf1a5c7d8 (diff)
downloadeclipse.platform.debug-c668724f83ea175ecc55095039907e6620bcc13a.tar.gz
eclipse.platform.debug-c668724f83ea175ecc55095039907e6620bcc13a.tar.xz
eclipse.platform.debug-c668724f83ea175ecc55095039907e6620bcc13a.zip
Bug 489546 - Call to ConsoleManager.showConsoleView(x) has no effect ifY20160811-1000I20160809-1300I20160809-1100
ShowConsoleViewJob is already running Change-Id: Iab3d68b31476704a81f75172cb41ef21b62a57e9 Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
-rw-r--r--org.eclipse.debug.tests/META-INF/MANIFEST.MF4
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java4
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleManagerTests.java248
-rw-r--r--org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleManager.java82
4 files changed, 305 insertions, 33 deletions
diff --git a/org.eclipse.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
index ce0c92c34..6cec1e3ba 100644
--- a/org.eclipse.debug.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
@@ -13,12 +13,14 @@ Require-Bundle: org.eclipse.ui;bundle-version="[3.6.0,4.0.0)",
org.eclipse.test.performance;bundle-version="3.6.0",
org.eclipse.core.resources;bundle-version="[3.5.0,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.9.0,4.0.0)",
- org.eclipse.ui.externaltools;bundle-version="[3.3.0,4.0.0)"
+ org.eclipse.ui.externaltools;bundle-version="[3.3.0,4.0.0)",
+ org.eclipse.ui.console;bundle-version="[3.7.0,4.0.0)"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-Vendor: %providerName
Export-Package: org.eclipse.debug.tests,
org.eclipse.debug.tests.breakpoint,
+ org.eclipse.debug.tests.console,
org.eclipse.debug.tests.expressions,
org.eclipse.debug.tests.launching,
org.eclipse.debug.tests.sourcelookup,
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
index 7af33159d..92efb0d1c 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
@@ -16,6 +16,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.debug.tests.breakpoint.BreakpointOrderingTests;
+import org.eclipse.debug.tests.console.ConsoleManagerTests;
import org.eclipse.debug.tests.launching.AcceleratorSubstitutionTests;
import org.eclipse.debug.tests.launching.ArgumentParsingTests;
import org.eclipse.debug.tests.launching.LaunchConfigurationTests;
@@ -97,5 +98,8 @@ public class AutomatedSuite extends TestSuite {
// Step filters
addTest(new TestSuite(StepFiltersTests.class));
+
+ // Console view
+ addTest(new TestSuite(ConsoleManagerTests.class));
}
}
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleManagerTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleManagerTests.java
new file mode 100644
index 000000000..1761c70e5
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleManagerTests.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Andrey Loskutov and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.tests.console;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.console.ConsolePlugin;
+import org.eclipse.ui.console.IConsole;
+import org.eclipse.ui.console.IConsoleManager;
+import org.eclipse.ui.console.IConsoleView;
+import org.eclipse.ui.part.IPageBookViewPage;
+import org.eclipse.ui.part.MessagePage;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests console manager
+ */
+public class ConsoleManagerTests extends TestCase {
+
+ private static final String INTROVIEW_ID = "org.eclipse.ui.internal.introview"; //$NON-NLS-1$
+ private ExecutorService executorService;
+ private IConsoleManager manager;
+ private int count;
+ private CountDownLatch latch;
+ private ConsoleMock[] consoles;
+ ConsoleMock firstConsole;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ count = 20;
+ latch = new CountDownLatch(count);
+ executorService = Executors.newFixedThreadPool(count);
+ manager = ConsolePlugin.getDefault().getConsoleManager();
+ IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ hideWelcomePage(activePage);
+ processUIEvents(100);
+ consoles = new ConsoleMock[count];
+ for (int i = 0; i < count; i++) {
+ final ConsoleMock console = new ConsoleMock(i + 1);
+ consoles[i] = console;
+ }
+ // register consoles (this does *not* show anything)
+ manager.addConsoles(consoles);
+
+ IViewPart consoleView = activePage.showView("org.eclipse.ui.console.ConsoleView"); //$NON-NLS-1$
+ activePage.activate(consoleView);
+ processUIEvents(100);
+
+ // The test is unstable ("show" event on the the first console seem to
+ // be not always sent), so make sure console view has shown at least
+ // one console for real before starting the main test
+ firstConsole = new ConsoleMock(0);
+ manager.addConsoles(new ConsoleMock[] { firstConsole });
+ manager.showConsoleView(firstConsole);
+ waitForJobs();
+ processUIEvents(100);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ executorService.shutdownNow();
+ manager.removeConsoles(consoles);
+ manager.removeConsoles(new ConsoleMock[] { firstConsole });
+ processUIEvents(100);
+ super.tearDown();
+ }
+
+ private void hideWelcomePage(IWorkbenchPage activePage) {
+ IViewReference[] refs = activePage.getViewReferences();
+ IViewPart intro = null;
+ for (IViewReference ref : refs) {
+ if (INTROVIEW_ID.equals(ref.getId())) {
+ intro = ref.getView(false);
+ }
+ }
+ if (intro != null) {
+ activePage.hideView(intro);
+ processUIEvents(100);
+ }
+ }
+
+ /**
+ * The test triggers {@link #count} simultaneous calls to the
+ * {@link IConsoleManager#showConsoleView(IConsole)} and checks if all of
+ * this calls were properly proceeded by the manager.
+ * <p>
+ * See bug 489546.
+ *
+ * @throws Exception
+ */
+ public void testShowAllConsoles() throws Exception {
+ // Create a number of threads which will start and wait for the last one
+ // created to call ConsoleManager.show.
+ for (ConsoleMock console : consoles) {
+ showConsole(console);
+ }
+ // Console manager starts a job with delay, let wait for him a bit
+ waitForJobs();
+
+ // Give UI a chance to proceed pending console manager jobs
+ processUIEvents(3000);
+
+ executorService.shutdown();
+ executorService.awaitTermination(1, TimeUnit.MINUTES);
+ List<ConsoleMock> shown = new ArrayList<>();
+ for (ConsoleMock console : consoles) {
+ if (console.showCalled > 0) {
+ shown.add(console);
+ }
+ }
+ assertEquals("Only " + shown.size() + " consoles were shown from " + count, count, shown.size()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ private void processUIEvents(final long millis) {
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() - start < millis) {
+ PlatformUI.getWorkbench().getDisplay().readAndDispatch();
+ }
+ }
+
+ private void waitForJobs() throws Exception {
+ if (Display.getCurrent() == null) {
+ Thread.sleep(200);
+ } else {
+ processUIEvents(200);
+ }
+ while (!Job.getJobManager().isIdle()) {
+ if (Display.getCurrent() == null) {
+ Thread.sleep(200);
+ } else {
+ processUIEvents(200);
+ }
+ }
+ }
+
+ private void showConsole(final ConsoleMock console) {
+ executorService.execute(new Runnable() {
+ @Override
+ public void run() {
+ // last one arriving here triggers execution for all at same
+ // time
+ latch.countDown();
+ try {
+ latch.await(1, TimeUnit.MINUTES);
+ System.out.println("Requesting to show: " + console); //$NON-NLS-1$
+ manager.showConsoleView(console);
+ waitForJobs();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ /**
+ * Dummy console page showing mock number and counting the numbers its
+ * control was shown in the console view.
+ */
+ static final class ConsoleMock implements IConsole {
+ MessagePage page;
+ volatile int showCalled;
+ final int number;
+
+ public ConsoleMock(int number) {
+ this.number = number;
+ }
+
+ @Override
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ }
+
+ @Override
+ public String getType() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return toString();
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ @Override
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ }
+
+ /**
+ * Just a page showing the mock console name
+ */
+ @Override
+ public IPageBookViewPage createPage(IConsoleView view) {
+ page = new MessagePage() {
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ // This listener is get called if the page is really shown
+ // in the console view
+ getControl().addListener(SWT.Show, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ showCalled++;
+ System.out.println("Shown: " + ConsoleMock.this); //$NON-NLS-1$
+ }
+ });
+ }
+
+ };
+ page.setMessage(toString());
+ return page;
+ }
+
+ @Override
+ public String toString() {
+ return "mock #" + number; //$NON-NLS-1$
+ }
+ }
+}
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleManager.java b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleManager.java
index db73423cd..1ef4b9830 100644
--- a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleManager.java
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleManager.java
@@ -7,12 +7,14 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Andrey Loskutov <loskutov@gmx.de> - bug 489546
*******************************************************************************/
package org.eclipse.ui.internal.console;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.PatternSyntaxException;
@@ -280,7 +282,7 @@ public class ConsoleManager implements IConsoleManager {
private class ShowConsoleViewJob extends WorkbenchJob {
- private IConsole console;
+ private Set<IConsole> queue = new LinkedHashSet<IConsole>();
ShowConsoleViewJob() {
super("Show Console View"); //$NON-NLS-1$
@@ -288,50 +290,66 @@ public class ConsoleManager implements IConsoleManager {
setPriority(Job.SHORT);
}
- void setConsole(IConsole console) {
- this.console = console;
+ void addConsole(IConsole console) {
+ synchronized (queue) {
+ queue.add(console);
+ }
}
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
+ Set<IConsole> consolesToShow;
+ synchronized (queue) {
+ consolesToShow = new LinkedHashSet<>(queue);
+ queue.clear();
+ }
+ for (IConsole c : consolesToShow) {
+ showConsole(c);
+ }
+ synchronized (queue) {
+ if (!queue.isEmpty()) {
+ schedule();
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ private void showConsole(IConsole c) {
boolean consoleFound = false;
- IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
- IConsole c = console;
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window != null && c != null) {
- IWorkbenchPage page= window.getActivePage();
- if (page != null) {
- synchronized (fConsoleViews) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ synchronized (fConsoleViews) {
for (IConsoleView consoleView : fConsoleViews) {
if (consoleView.getSite().getPage().equals(page)) {
- boolean consoleVisible = page.isPartVisible(consoleView);
- if (consoleVisible) {
- consoleFound = true;
+ boolean consoleVisible = page.isPartVisible(consoleView);
+ if (consoleVisible) {
+ consoleFound = true;
boolean bringToTop = shouldBringToTop(c, consoleView);
- if (bringToTop) {
- page.bringToTop(consoleView);
- }
+ if (bringToTop) {
+ page.bringToTop(consoleView);
+ }
consoleView.display(c);
- }
- }
+ }
+ }
}
- }
+ }
- if (!consoleFound) {
- try {
- IConsoleView consoleView = (IConsoleView) page.showView(IConsoleConstants.ID_CONSOLE_VIEW, null, IWorkbenchPage.VIEW_CREATE);
+ if (!consoleFound) {
+ try {
+ IConsoleView consoleView = (IConsoleView) page.showView(IConsoleConstants.ID_CONSOLE_VIEW, null, IWorkbenchPage.VIEW_CREATE);
boolean bringToTop = shouldBringToTop(c, consoleView);
- if (bringToTop) {
- page.bringToTop(consoleView);
- }
+ if (bringToTop) {
+ page.bringToTop(consoleView);
+ }
consoleView.display(c);
- } catch (PartInitException pie) {
- ConsolePlugin.log(pie);
- }
- }
- }
- }
- console = null;
- return Status.OK_STATUS;
+ } catch (PartInitException pie) {
+ ConsolePlugin.log(pie);
+ }
+ }
+ }
+ }
}
}
@@ -341,7 +359,7 @@ public class ConsoleManager implements IConsoleManager {
*/
@Override
public void showConsoleView(final IConsole console) {
- showJob.setConsole(console);
+ showJob.addConsole(console);
showJob.schedule(100);
}

Back to the top