Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Keller2017-03-08 17:27:39 +0000
committerMarkus Keller2017-03-08 17:27:39 +0000
commitdad356880b62128e58665dd3e641e51ab61e03c0 (patch)
treee12b8e459073947b0a6b22293a142b966501b994
parent5985a1edc5adad4a81892f9229e3269c8b25e794 (diff)
downloadeclipse.platform.text-dad356880b62128e58665dd3e641e51ab61e03c0.tar.gz
eclipse.platform.text-dad356880b62128e58665dd3e641e51ab61e03c0.tar.xz
eclipse.platform.text-dad356880b62128e58665dd3e641e51ab61e03c0.zip
Bug 511101: [Generic Editor] misses quick fix on error markers
- improved HoverTest (no endless loop, better logging) - removed dependency on platform.ui test bundle - improved ScreenshotTest
-rw-r--r--org.eclipse.jface.text.tests/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/util/DisplayHelper.java581
-rw-r--r--org.eclipse.ui.genericeditor.tests/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/HoverTest.java31
-rw-r--r--org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/ScreenshotTest.java81
5 files changed, 655 insertions, 44 deletions
diff --git a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF
index e716de1e27d..cbb20943ee5 100644
--- a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF
@@ -9,7 +9,8 @@ Export-Package:
org.eclipse.jface.text.tests,
org.eclipse.jface.text.tests.reconciler,
org.eclipse.jface.text.tests.rules,
- org.eclipse.jface.text.tests.source
+ org.eclipse.jface.text.tests.source,
+ org.eclipse.jface.text.tests.util
Require-Bundle:
org.eclipse.jface.text;bundle-version="[3.5.0,4.0.0)",
org.eclipse.jface;bundle-version="[3.5.0,4.0.0)",
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/util/DisplayHelper.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/util/DisplayHelper.java
new file mode 100644
index 00000000000..221e77fe96e
--- /dev/null
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/util/DisplayHelper.java
@@ -0,0 +1,581 @@
+package org.eclipse.jface.text.tests.util;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.junit.Assert;
+
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * Runs the event loop of the given display until {@link #condition()} becomes
+ * <code>true</code> or no events have occurred for the supplied timeout.
+ * Between running the event loop, {@link Display#sleep()} is called.
+ * <p>
+ * There is a caveat: the given timeouts must be long enough that the calling
+ * thread can enter <code>Display.sleep()</code> before the timeout elapses,
+ * otherwise, the waiter may time out before <code>sleep</code> is called and
+ * the sleeping thread may never be waken up.
+ * </p>
+ *
+ * @since 3.11
+ */
+public abstract class DisplayHelper {
+// copy of org.eclipse.jdt.testplugin.util.DisplayHelper in org.eclipse.jdt.ui.tests
+
+ /**
+ * Controls if the timeout is used. For debugging use true, false otherwise
+ */
+ private static final boolean DISABLE_TIMEOUT= false;
+
+ /**
+ * Creates a new instance.
+ */
+ protected DisplayHelper() {
+ }
+
+ /**
+ * Until {@link #condition()} becomes <code>true</code> or the timeout
+ * elapses, call {@link Display#sleep()} and run the event loop.
+ * <p>
+ * If <code>timeout &lt; 0</code>, the event loop is never driven and
+ * only the condition is checked. If <code>timeout == 0</code>, the event
+ * loop is driven at most once, but <code>Display.sleep()</code> is never
+ * invoked.
+ * </p>
+ *
+ * @param display the display to run the event loop of
+ * @param timeout the timeout in milliseconds
+ * @return <code>true</code> if the condition became <code>true</code>,
+ * <code>false</code> if the timeout elapsed
+ */
+ public final boolean waitForCondition(Display display, long timeout) {
+ // if the condition already holds, succeed
+ if (condition())
+ return true;
+
+ if (timeout < 0)
+ return false;
+
+ // if driving the event loop once makes the condition hold, succeed
+ // without spawning a thread.
+ driveEventQueue(display);
+ if (condition())
+ return true;
+
+ // if the timeout is negative or zero, fail
+ if (timeout == 0)
+ return false;
+
+ // repeatedly sleep until condition becomes true or timeout elapses
+ DisplayWaiter waiter= new DisplayWaiter(display);
+ DisplayWaiter.Timeout timeoutState= waiter.start(timeout);
+ boolean condition;
+ try {
+ do {
+ if (display.sleep())
+ driveEventQueue(display);
+ condition= condition();
+ } while (!condition && !timeoutState.hasTimedOut());
+ } finally {
+ waiter.stop();
+ }
+ return condition;
+ }
+
+ /**
+ * Call {@link Display#sleep()} and run the event loop until the given
+ * timeout has elapsed.
+ * <p>
+ * If <code>timeout &lt; 0</code>, nothing happens. If
+ * <code>timeout == 0</code>, the event loop is driven exactly once, but
+ * <code>Display.sleep()</code> is never invoked.
+ * </p>
+ *
+ * @param display the display to run the event loop of
+ * @param millis the timeout in milliseconds
+ */
+ public static void sleep(Display display, long millis) {
+ new DisplayHelper() {
+ @Override
+ public boolean condition() {
+ return false;
+ }
+ }.waitForCondition(display, millis);
+ }
+
+ /**
+ * The condition which has to be met in order for {@link #waitForCondition(Display, long)} to
+ * return before the timeout elapses.
+ *
+ * @return <code>true</code> if the condition is met, <code>false</code> if the event loop
+ * should be driven some more
+ */
+ protected abstract boolean condition();
+
+ /**
+ * Runs the event loop on the given display.
+ *
+ * @param display the display
+ * @return if <code>display.readAndDispatch</code> returned
+ * <code>true</code> at least once
+ */
+ private static boolean driveEventQueue(Display display) {
+ boolean events= false;
+ while (display.readAndDispatch()) {
+ events= true;
+ }
+ return events;
+ }
+
+ /**
+ * Until {@link #condition()} becomes <code>true</code> or the timeout
+ * elapses, call {@link Display#sleep()} and run the event loop.
+ * <p>
+ * If <code>timeout &lt; 0</code>, the event loop is never driven and
+ * only the condition is checked. If <code>timeout == 0</code>, the event
+ * loop is driven at most once, but <code>Display.sleep()</code> is never
+ * invoked.
+ * </p>
+ * <p>
+ * The condition gets rechecked every <code>interval</code> milliseconds, even
+ * if no events were read from the queue.
+ * </p>
+ *
+ * @param display the display to run the event loop of
+ * @param timeout the timeout in milliseconds
+ * @param interval the interval to re-check the condition in milliseconds
+ * @return <code>true</code> if the condition became <code>true</code>,
+ * <code>false</code> if the timeout elapsed
+ */
+ public final boolean waitForCondition(Display display, long timeout, long interval) {
+ // if the condition already holds, succeed
+ if (condition())
+ return true;
+
+ if (timeout < 0)
+ return false;
+
+ // if driving the event loop once makes the condition hold, succeed
+ // without spawning a thread.
+ driveEventQueue(display);
+ if (condition())
+ return true;
+
+ // if the timeout is negative or zero, fail
+ if (timeout == 0)
+ return false;
+
+ // repeatedly sleep until condition becomes true or timeout elapses
+ DisplayWaiter waiter= new DisplayWaiter(display, true);
+ long currentTimeMillis= System.currentTimeMillis();
+ long finalTimeout= timeout + currentTimeMillis;
+ if (finalTimeout < currentTimeMillis)
+ finalTimeout= Long.MAX_VALUE;
+ boolean condition;
+ try {
+ do {
+ waiter.restart(interval);
+ if (display.sleep())
+ driveEventQueue(display);
+ condition= condition();
+ } while (!condition && (DISABLE_TIMEOUT || finalTimeout > System.currentTimeMillis()));
+ } finally {
+ waiter.stop();
+ }
+ return condition;
+ }
+
+}
+
+/**
+ * Implements the thread that will wait for the timeout and wake up the display
+ * so it does not wait forever. The thread may be restarted after it was stopped
+ * or timed out.
+ */
+final class DisplayWaiter {
+ /**
+ * Timeout state of a display waiter thread.
+ */
+ public final class Timeout {
+ private boolean fTimeoutState= false;
+ /**
+ * Returns <code>true</code> if the timeout has been reached,
+ * <code>false</code> if not.
+ *
+ * @return <code>true</code> if the timeout has been reached,
+ * <code>false</code> if not
+ */
+ public boolean hasTimedOut() {
+ synchronized (fMutex) {
+ return fTimeoutState;
+ }
+ }
+ void setTimedOut(boolean timedOut) {
+ fTimeoutState= timedOut;
+ }
+ Timeout(boolean initialState) {
+ fTimeoutState= initialState;
+ }
+ }
+
+ // configuration
+ private final Display fDisplay;
+ private final Object fMutex= new Object();
+ private final boolean fKeepRunningOnTimeout;
+
+ /* State -- possible transitions:
+ *
+ * STOPPED -> RUNNING
+ * RUNNING -> STOPPED
+ * RUNNING -> IDLE
+ * IDLE -> RUNNING
+ * IDLE -> STOPPED
+ */
+ private static final int RUNNING= 1 << 1;
+ private static final int STOPPED= 1 << 2;
+ private static final int IDLE= 1 << 3;
+
+ /** The current state. */
+ private int fState;
+ /** The time in milliseconds (see Date) that the timeout will occur. */
+ private long fNextTimeout;
+ /** The thread. */
+ private Thread fCurrentThread;
+ /** The timeout state of the current thread. */
+ private Timeout fCurrentTimeoutState;
+
+ /**
+ * Creates a new instance on the given display and timeout.
+ *
+ * @param display the display to run the event loop of
+ */
+ public DisplayWaiter(Display display) {
+ this(display, false);
+ }
+
+ /**
+ * Creates a new instance on the given display and timeout.
+ *
+ * @param display the display to run the event loop of
+ * @param keepRunning <code>true</code> if the thread should be kept
+ * running after timing out
+ */
+ public DisplayWaiter(Display display, boolean keepRunning) {
+ Assert.assertNotNull(display);
+ fDisplay= display;
+ fState= STOPPED;
+ fKeepRunningOnTimeout= keepRunning;
+ }
+
+ /**
+ * Starts the timeout thread if it is not currently running. Nothing happens
+ * if a thread is already running.
+ *
+ * @param delay the delay from now in milliseconds
+ * @return the timeout state which can be queried for its timed out status
+ */
+ public Timeout start(long delay) {
+ Assert.assertTrue(delay > 0);
+ synchronized (fMutex) {
+ switch (fState) {
+ case STOPPED:
+ startThread();
+ setNextTimeout(delay);
+ break;
+ case IDLE:
+ unhold();
+ setNextTimeout(delay);
+ break;
+ }
+
+ return fCurrentTimeoutState;
+ }
+ }
+
+ /**
+ * Sets the next timeout to <em>current time</em> plus <code>delay</code>.
+ *
+ * @param delay the delay until the next timeout occurs in milliseconds from
+ * now
+ */
+ private void setNextTimeout(long delay) {
+ long currentTimeMillis= System.currentTimeMillis();
+ long next= currentTimeMillis + delay;
+ if (next > currentTimeMillis)
+ fNextTimeout= next;
+ else
+ fNextTimeout= Long.MAX_VALUE;
+ }
+
+ /**
+ * Starts the thread if it is not currently running; resets the timeout if
+ * it is.
+ *
+ * @param delay the delay from now in milliseconds
+ * @return the timeout state which can be queried for its timed out status
+ */
+ public Timeout restart(long delay) {
+ Assert.assertTrue(delay > 0);
+ synchronized (fMutex) {
+ switch (fState) {
+ case STOPPED:
+ startThread();
+ break;
+ case IDLE:
+ unhold();
+ break;
+ }
+ setNextTimeout(delay);
+
+ return fCurrentTimeoutState;
+ }
+ }
+
+ /**
+ * Stops the thread if it is running. If not, nothing happens. Another
+ * thread may be started by calling {@link #start(long)} or
+ * {@link #restart(long)}.
+ */
+ public void stop() {
+ synchronized (fMutex) {
+ if (tryTransition(RUNNING | IDLE, STOPPED))
+ fMutex.notifyAll();
+ }
+ }
+
+ /**
+ * Puts the reaper thread on hold but does not stop it. It may be restarted
+ * by calling {@link #start(long)} or {@link #restart(long)}.
+ */
+ public void hold() {
+ synchronized (fMutex) {
+ // nothing to do if there is no thread
+ if (tryTransition(RUNNING, IDLE))
+ fMutex.notifyAll();
+ }
+ }
+
+ /**
+ * Transition to <code>RUNNING</code> and clear the timed out flag. Assume
+ * current state is <code>IDLE</code>.
+ */
+ private void unhold() {
+ checkedTransition(IDLE, RUNNING);
+ fCurrentTimeoutState= new Timeout(false);
+ fMutex.notifyAll();
+ }
+
+ /**
+ * Start the thread. Assume the current state is <code>STOPPED</code>.
+ */
+ private void startThread() {
+ checkedTransition(STOPPED, RUNNING);
+ fCurrentTimeoutState= new Timeout(false);
+ fCurrentThread= new Thread() {
+ /**
+ * Exception thrown when a thread notices that it has been stopped
+ * and a new thread has been started.
+ */
+ final class ThreadChangedException extends Exception {
+ private static final long serialVersionUID= 1L;
+ }
+
+ /*
+ * @see java.lang.Runnable#run()
+ */
+ @Override
+ public void run() {
+ try {
+ run2();
+ } catch (InterruptedException e) {
+ // ignore and end the thread - we never interrupt ourselves,
+ // so it must be an external entity that interrupted us
+ Logger.getGlobal().log(Level.FINE, "", e);
+ } catch (ThreadChangedException e) {
+ // the thread was stopped and restarted before we got out
+ // of a wait - we're no longer used
+ // we might have been notified instead of the current thread,
+ // so wake it up
+ Logger.getGlobal().log(Level.FINE, "", e);
+ synchronized (fMutex) {
+ fMutex.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Runs the thread.
+ *
+ * @throws InterruptedException if the thread was interrupted
+ * @throws ThreadChangedException if the thread changed
+ */
+ private void run2() throws InterruptedException, ThreadChangedException {
+ synchronized (fMutex) {
+ checkThread();
+ tryHold(); // wait / potential state change
+ assertStates(STOPPED | RUNNING);
+
+ while (isState(RUNNING)) {
+ waitForTimeout(); // wait / potential state change
+
+ if (isState(RUNNING))
+ timedOut(); // state change
+ assertStates(STOPPED | IDLE);
+
+ tryHold(); // wait / potential state change
+ assertStates(STOPPED | RUNNING);
+ }
+ assertStates(STOPPED);
+ }
+ }
+
+ /**
+ * Check whether the current thread is this thread, throw an
+ * exception otherwise.
+ *
+ * @throws ThreadChangedException if the current thread changed
+ */
+ private void checkThread() throws ThreadChangedException {
+ if (fCurrentThread != this)
+ throw new ThreadChangedException();
+ }
+
+ /**
+ * Waits until the next timeout occurs.
+ *
+ * @throws InterruptedException if the thread was interrupted
+ * @throws ThreadChangedException if the thread changed
+ */
+ private void waitForTimeout() throws InterruptedException, ThreadChangedException {
+ long delta;
+ while (isState(RUNNING) && (delta = fNextTimeout - System.currentTimeMillis()) > 0) {
+ delta= Math.max(delta, 50); // wait at least 50ms in order to avoid timing out before the display is going to sleep
+ Logger.getGlobal().finest("sleeping for " + delta + "ms");
+ fMutex.wait(delta);
+ checkThread();
+ }
+ }
+
+ /**
+ * Sets the timed out flag and wakes up the display. Transitions to
+ * <code>IDLE</code> (if in keep-running mode) or
+ * <code>STOPPED</code>.
+ */
+ private void timedOut() {
+ Logger.getGlobal().finer("timed out");
+ fCurrentTimeoutState.setTimedOut(true);
+ fDisplay.wake(); // wake up call!
+ if (fKeepRunningOnTimeout)
+ checkedTransition(RUNNING, IDLE);
+ else
+ checkedTransition(RUNNING, STOPPED);
+ }
+
+ /**
+ * Waits while the state is <code>IDLE</code>, then returns. The
+ * state must not be <code>RUNNING</code> when calling this
+ * method. The state is either <code>STOPPED</code> or
+ * <code>RUNNING</code> when the method returns.
+ *
+ * @throws InterruptedException if the thread was interrupted
+ * @throws ThreadChangedException if the thread has changed while on
+ * hold
+ */
+ private void tryHold() throws InterruptedException, ThreadChangedException {
+ while (isState(IDLE)) {
+ fMutex.wait(0);
+ checkThread();
+ }
+ assertStates(STOPPED | RUNNING);
+ }
+ };
+
+ fCurrentThread.start();
+ }
+
+ /**
+ * Transitions to <code>nextState</code> if the current state is one of
+ * <code>possibleStates</code>. Returns <code>true</code> if the
+ * transition happened, <code>false</code> otherwise.
+ *
+ * @param possibleStates the states which trigger a transition
+ * @param nextState the state to transition to
+ * @return <code>true</code> if the transition happened,
+ * <code>false</code> otherwise
+ */
+ private boolean tryTransition(int possibleStates, int nextState) {
+ if (isState(possibleStates)) {
+ Logger.getGlobal().finer(name(fState) + " > " + name(nextState) + " (" + name(possibleStates) + ")");
+ fState= nextState;
+ return true;
+ }
+ Logger.getGlobal().finest("noTransition" + name(fState) + " !> " + name(nextState) + " (" + name(possibleStates) + ")");
+ return false;
+ }
+
+ /**
+ * Checks the <code>possibleStates</code> and throws an assertion if it is
+ * not met, then transitions to <code>nextState</code>.
+ *
+ * @param possibleStates the allowed states
+ * @param nextState the state to transition to
+ */
+ private void checkedTransition(int possibleStates, int nextState) {
+ assertStates(possibleStates);
+ Logger.getGlobal().finer(name(fState) + " > " + name(nextState));
+ fState= nextState;
+ }
+
+ /**
+ * Implements state consistency checking.
+ *
+ * @param states the allowed states
+ * @throws junit.framework.AssertionFailedError if the current state is not
+ * in <code>states</code>
+ */
+ private void assertStates(int states) {
+ Assert.assertTrue("illegal state", isState(states));
+ }
+
+ /**
+ * Answers <code>true</code> if the current state is in the given
+ * <code>states</code>.
+ *
+ * @param states the possible states
+ * @return <code>true</code> if the current state is in the given states,
+ * <code>false</code> otherwise
+ */
+ private boolean isState(int states) {
+ return (states & fState) == fState;
+ }
+
+ /**
+ * Pretty print the given states.
+ *
+ * @param states the states
+ * @return a string representation of the states
+ */
+ private String name(int states) {
+ StringBuffer buf= new StringBuffer();
+ boolean comma= false;
+ if ((states & RUNNING) == RUNNING) {
+ buf.append("RUNNING");
+ comma= true;
+ }
+ if ((states & STOPPED) == STOPPED) {
+ if (comma)
+ buf.append(",");
+ buf.append("STOPPED");
+ comma= true;
+ }
+ if ((states & IDLE) == IDLE) {
+ if (comma)
+ buf.append(",");
+ buf.append("IDLE");
+ }
+ return buf.toString();
+ }
+
+}
diff --git a/org.eclipse.ui.genericeditor.tests/META-INF/MANIFEST.MF b/org.eclipse.ui.genericeditor.tests/META-INF/MANIFEST.MF
index cf5e719441c..123f4c261a7 100644
--- a/org.eclipse.ui.genericeditor.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.ui.genericeditor.tests/META-INF/MANIFEST.MF
@@ -17,8 +17,9 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.6.0,4.0.0)",
org.eclipse.ui;bundle-version="3.108.0",
org.eclipse.ui.workbench.texteditor;bundle-version="3.10.0",
org.eclipse.ui.ide;bundle-version="3.11.0",
+ org.eclipse.jface.text.tests;bundle-version="3.11.100",
org.eclipse.text.tests;bundle-version="3.11.0",
- org.eclipse.ui.tests.harness
+ org.eclipse.ui.workbench.texteditor.tests;bundle-version="3.11.100"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Eclipse-BundleShape: dir
Bundle-ActivationPolicy: lazy
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/HoverTest.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/HoverTest.java
index 4a6a394b4af..f130f4d236c 100644
--- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/HoverTest.java
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/HoverTest.java
@@ -14,6 +14,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.util.Collections;
@@ -21,7 +22,9 @@ import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
@@ -41,12 +44,14 @@ import org.eclipse.jface.text.AbstractInformationControl;
import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextViewer;
+import org.eclipse.jface.text.tests.util.DisplayHelper;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.genericeditor.tests.contributions.MagicHoverProvider;
import org.eclipse.ui.genericeditor.tests.contributions.MarkerResolutionGenerator;
import org.eclipse.ui.part.FileEditorInput;
-import org.eclipse.ui.tests.harness.util.DisplayHelper;
+
+import org.eclipse.ui.workbench.texteditor.tests.ScreenshotTest;
import org.eclipse.ui.texteditor.AbstractTextEditor;
@@ -56,6 +61,9 @@ import org.eclipse.ui.texteditor.AbstractTextEditor;
*/
public class HoverTest {
+ @Rule
+ public TestName testName = new TestName();
+
private AbstractTextEditor editor;
@BeforeClass
@@ -121,12 +129,19 @@ public class HoverTest {
}
private Shell getHoverShell(AbstractInformationControlManager manager) {
- AbstractInformationControl control = null;
- do {
- DisplayHelper.runEventLoop(this.editor.getSite().getShell().getDisplay(), 100);
- control = (AbstractInformationControl)new Accessor(manager, AbstractInformationControlManager.class).get("fInformationControl");
- } while (control == null);
- Shell shell = (Shell)new Accessor(control, AbstractInformationControl.class).get("fShell");
+ AbstractInformationControl[] control = { null };
+ new DisplayHelper() {
+ @Override
+ protected boolean condition() {
+ control[0] = (AbstractInformationControl)new Accessor(manager, AbstractInformationControlManager.class).get("fInformationControl");
+ return control[0] != null;
+ }
+ }.waitForCondition(this.editor.getSite().getShell().getDisplay(), 5000);
+ if (control[0] == null) {
+ ScreenshotTest.takeScreenshot(getClass(), testName.getMethodName(), System.out);
+ fail();
+ }
+ Shell shell = (Shell)new Accessor(control[0], AbstractInformationControl.class).get("fShell");
assertTrue(shell.isVisible());
return shell;
}
@@ -190,7 +205,7 @@ public class HoverTest {
editorTextWidget.getDisplay().setCursorLocation(editorTextWidget.toDisplay(hoverEvent.x, hoverEvent.y));
editorTextWidget.notifyListeners(SWT.MouseHover, hoverEvent);
// Events need to be processed for hover listener to work correctly
- DisplayHelper.runEventLoop(editorTextWidget.getDisplay(), 1000);
+ DisplayHelper.sleep(editorTextWidget.getDisplay(), 1000);
// retrieving hover content
ITextViewer viewer = (ITextViewer)new Accessor(editor, AbstractTextEditor.class).invoke("getSourceViewer", new Object[0]);
AbstractInformationControlManager textHoverManager = (AbstractInformationControlManager)new Accessor(viewer, TextViewer.class).get("fTextHoverManager");
diff --git a/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/ScreenshotTest.java b/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/ScreenshotTest.java
index 1e8a2bb3468..6978d329b03 100644
--- a/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/ScreenshotTest.java
+++ b/org.eclipse.ui.workbench.texteditor.tests/src/org/eclipse/ui/workbench/texteditor/tests/ScreenshotTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2015 IBM Corporation and others.
+ * Copyright (c) 2012, 2017 IBM Corporation 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
@@ -86,6 +86,15 @@ public class ScreenshotTest {
/**
* Takes a screenshot and dumps other debugging information to the given stream.
*
+ * <p>
+ * Workaround for missing {@link junit.framework.TestCase#getName()} in JUnit 4:
+ * </p>
+ *
+ * <pre>
+ * &#64;Rule
+ * public TestName testName = new TestName();
+ * </pre>
+ *
* @param testClass test class that takes the screenshot
* @param name screenshot identifier (e.g. test name)
* @param out print stream to use for diagnostics.
@@ -104,40 +113,8 @@ public class ScreenshotTest {
Display display= PlatformUI.getWorkbench().getDisplay();
- // Wiggle the mouse:
- Event mouseMove= new Event();
- mouseMove.x= 10;
- mouseMove.y= 10;
- display.post(mouseMove);
- runEventQueue();
- mouseMove.x= 20;
- mouseMove.y= 20;
- display.post(mouseMove);
- runEventQueue();
-
// Dump focus control, parents, and shells:
- Control focusControl = display.getFocusControl();
- out.println("FocusControl: ");
- if (focusControl == null) {
- System.out.println(" null!");
- } else {
- StringBuffer indent = new StringBuffer(" ");
- do {
- out.println(indent.toString() + focusControl);
- focusControl = focusControl.getParent();
- indent.append(" ");
- } while (focusControl != null);
- }
- Shell[] shells = display.getShells();
- if (shells.length > 0) {
- out.println("Shells: ");
- for (int i = 0; i < shells.length; i++) {
- Shell shell = shells[i];
- out.print(display.getActiveShell() == shell ? " active, " : " inactive, ");
- out.print((shell.isVisible() ? "visible: " : "invisible: ") + shell);
- out.println(" @ " + shell.getBounds().toString());
- }
- }
+ dumpDisplayState(display, System.out);
// Take a screenshot:
GC gc = new GC(display);
@@ -159,6 +136,42 @@ public class ScreenshotTest {
return filename;
}
+ private static void dumpDisplayState(Display display, PrintStream out) {
+ Control focusControl= display.getFocusControl();
+ dumpControlParentHierarchy(out, "FocusControl", focusControl);
+ Shell[] shells= display.getShells();
+ if (shells.length > 0) {
+ out.println("Shells: ");
+ for (int i= 0; i < shells.length; i++) {
+ Shell shell= shells[i];
+ out.print(display.getActiveShell() == shell ? " active, " : " inactive, ");
+ out.print((shell.isVisible() ? "visible: " : "invisible: ") + shell);
+ out.println(" @ " + shell.getBounds().toString());
+ }
+ }
+ out.println("Client area: " + display.getClientArea());
+ out.println("Cursor location: " + display.getCursorLocation());
+ Control cursorControl= display.getCursorControl();
+ if (focusControl != cursorControl) {
+ dumpControlParentHierarchy(out, "CursorControl", cursorControl);
+ }
+ }
+
+ private static void dumpControlParentHierarchy(PrintStream out, String label, Control control) {
+ out.print(label + ": ");
+ if (control == null) {
+ out.println("<none>");
+ } else {
+ out.println();
+ StringBuilder indent= new StringBuilder(" ");
+ do {
+ out.println(indent.toString() + control);
+ control= control.getParent();
+ indent.append(" ");
+ } while (control != null);
+ }
+ }
+
private static File getJunitReportOutput() {
String[] args= Platform.getCommandLineArgs();
for (int i= 0; i < args.length - 1; i++) {

Back to the top