lttng: Help stabilize some TimeGraphs tests
authorMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Thu, 18 Feb 2016 05:48:58 +0000 (00:48 -0500)
committerMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Fri, 4 Mar 2016 14:29:55 +0000 (09:29 -0500)
When opening the filter dialog for the Control Flow view, it is possible
that view is not populated yet. When this is the case, the controls in
the dialog are disabled.

To fix this, the test now waits until the "timegraphview is ready".
But it was not sufficient to simply call the existing condition. The
isDirty method of AbstractTimeGraphView does not cover the case where
the view is completely empty and nothing has been scheduled to be drawn
yet (Zoom Thread).

To help with this, the isDirty method was improved to cover more cases.
The time range of the time graph control has to match the window time,
which covers the case that the zoom thread has not started but the view
is about to update itself. There was also a race between the time that
the time range is set on the time graph control and the time that the
zoom thread is created; this was addressed by using the dirty counter to
guard this section.

As a future improvement, the filter dialog could be augmented to handle
the Control Flow view being updated while the dialog is up. This is
beyond the scope of stabilizing the test.

To reproduce this failure before the patch, insert a Thread.sleep(5000)
in ControlFlowView.buildEventList, in the while loop. This will delay
the entry list being built, which will increase the duration of the view
being completely empty and not considered dirty yet.

Change-Id: I94038436608f6e1b384b0f90a43bddd08d3651c6
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/66785
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-by: Hudson CI
lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java
lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java
tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/shared/org/eclipse/tracecompass/tmf/ui/swtbot/tests/shared/ConditionHelpers.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java

index 2c5bb77d808426b93e5848d00a547e8a67ba21bf..3f9d876fb7aeb7d306d21ab6f3405b5d2956b0a1 100644 (file)
@@ -17,6 +17,7 @@ import java.io.IOException;
 import org.eclipse.core.runtime.FileLocator;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
 import org.eclipse.swtbot.swt.finder.SWTBot;
@@ -30,10 +31,15 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
 import org.eclipse.tracecompass.internal.tmf.core.Activator;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimePreferencesConstants;
+import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers;
 import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers.SWTBotTestCondition;
 import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
@@ -80,6 +86,8 @@ public class ControlFlowViewSortingTest extends KernelTestBase {
     private static final long LTTNG_CONSUMER_BIRTHTIME = 1361214078963717040L;
     private static final String LTTNG_CONSUMER_TID = "4034";
 
+    private static final @NonNull TmfTimestamp TRACE_START_TIME = new TmfTimestamp(1361214078963711320L, ITmfTimestamp.NANOSECOND_SCALE);
+
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
@@ -129,6 +137,8 @@ public class ControlFlowViewSortingTest extends KernelTestBase {
      */
     @Test
     public void testColumnSorting() {
+        fBot.waitUntil(ConditionHelpers.timeGraphIsReadyCondition((AbstractTimeGraphView) fViewBot.getViewReference().getPart(false), new TmfTimeRange(TRACE_START_TIME, TRACE_START_TIME), TRACE_START_TIME));
+
         // Create a known state
         applyFilter();
         final SWTBotTree tree = fViewBot.bot().tree();
index 54799aa5bbcec200636dd64975d17b3df40e957f..ba9e4e7c25d17e069200d545053eb8817013ddb3 100644 (file)
@@ -243,7 +243,7 @@ public class ControlFlowViewTest extends KernelTestBase {
         /* change window range to 1 ms */
         TmfTimeRange range = new TmfTimeRange(START_TIME, START_TIME.normalize(1000000L, ITmfTimestamp.NANOSECOND_SCALE));
         TmfSignalManager.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, range));
-        fBot.waitUntil(ConditionHelpers.windowRange(range));
+        timeGraphIsReadyCondition(new TmfTimeRange(START_TIME, START_TIME));
 
         SWTBotToolbarButton filterButton = fViewBot.toolbarButton("Show View Filters");
         filterButton.click();
index 00a67656442ac297723be4186e7b2d85ab777fa7..29459f2648eb6393a78768e1f8fd830d8be7b3b2 100644 (file)
@@ -489,6 +489,7 @@ public final class ConditionHelpers {
         private @NonNull TmfTimeRange fSelectionRange;
         private @NonNull ITmfTimestamp fVisibleTime;
         private AbstractTimeGraphView fView;
+        private String fFailureMessage;
 
         private TimeGraphIsReadyCondition(AbstractTimeGraphView view, @NonNull TmfTimeRange selectionRange, @NonNull ITmfTimestamp visibleTime) {
             fView = view;
@@ -498,18 +499,28 @@ public final class ConditionHelpers {
 
         @Override
         public boolean test() throws Exception {
-            if (!ConditionHelpers.selectionRange(fSelectionRange).test()) {
+            ICondition selectionRangeCondition = ConditionHelpers.selectionRange(fSelectionRange);
+            if (!selectionRangeCondition.test()) {
+                fFailureMessage = selectionRangeCondition.getFailureMessage();
                 return false;
             }
-            if (!TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange().contains(fVisibleTime)) {
+            @NonNull TmfTimeRange curWindowRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange();
+            if (!curWindowRange.contains(fVisibleTime)) {
+                fFailureMessage = "Current window range " + curWindowRange + " does not contain " + fVisibleTime;
                 return false;
             }
-            return !fView.isDirty();
+
+            if (fView.isDirty()) {
+                fFailureMessage = "Time graph is dirty";
+                return false;
+
+            }
+            return true;
         }
 
         @Override
         public String getFailureMessage() {
-            return "Time graph is not ready";
+            return fFailureMessage;
         }
     }
 
index d54ff4883fd9baaa88ae58f9b864a3b6cd2fa71f..d185edb99a3a8e0111b57216db79ac19aa20579d 100644 (file)
@@ -1680,6 +1680,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 if (fTimeGraphWrapper.isDisposed()) {
                     return;
                 }
+                fDirty.incrementAndGet();
+
                 boolean hasEntries = false;
                 synchronized (fEntryListMap) {
                     fEntryList = fEntryListMap.get(fTrace);
@@ -1758,7 +1760,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 if (!zoomThread) {
                     startZoomThread(startTime, endTime);
                 }
-
+                fDirty.decrementAndGet();
             }
         });
     }
@@ -1814,16 +1816,18 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
      * @since 2.0
      */
     protected final void startZoomThread(long startTime, long endTime) {
+        long clampedStartTime = Math.min(Math.max(startTime, fStartTime), fEndTime);
+        long clampedEndTime = Math.max(Math.min(endTime, fEndTime), fStartTime);
         fDirty.incrementAndGet();
         boolean restart = false;
         if (fZoomThread != null) {
             fZoomThread.cancel();
-            if (fZoomThread.fZoomStartTime == startTime && fZoomThread.fZoomEndTime == endTime) {
+            if (fZoomThread.fZoomStartTime == clampedStartTime && fZoomThread.fZoomEndTime == clampedEndTime) {
                 restart = true;
             }
         }
-        long resolution = Math.max(1, (endTime - startTime) / fDisplayWidth);
-        fZoomThread = createZoomThread(startTime, endTime, resolution, restart);
+        long resolution = Math.max(1, (clampedEndTime - clampedStartTime) / fDisplayWidth);
+        fZoomThread = createZoomThread(clampedStartTime, clampedEndTime, resolution, restart);
         if (fZoomThread != null) {
             fZoomThread.start();
         } else {
@@ -1940,15 +1944,40 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
      * Returns whether or not the time graph view is dirty. The time graph view
      * is considered dirty if it has yet to completely update its model.
      *
+     * This method is meant to be used by tests in order to know when it is safe
+     * to proceed.
+     *
+     * Note: If a trace is smaller than the initial window range (see
+     * {@link ITmfTrace#getInitialRangeOffset}) this method will return true
+     * forever.
+     *
      * @return true if the time graph view has yet to completely update its
      *         model, false otherwise
      * @since 2.0
      */
     public boolean isDirty() {
-        if (fZoomThread == null) {
+        if (fTrace == null) {
             return false;
         }
-        return fDirty.get() != 0 || fZoomThread.getZoomStartTime() != fTimeGraphWrapper.getTimeGraphViewer().getTime0() || fZoomThread.getZoomEndTime() != fTimeGraphWrapper.getTimeGraphViewer().getTime1();
+
+        TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
+        long startTime = ctx.getWindowRange().getStartTime().toNanos();
+        long endTime = ctx.getWindowRange().getEndTime().toNanos();
+
+        // If the time graph control hasn't updated all the way to the end of
+        // the window range then it's dirty. A refresh should happen later.
+        if (fTimeGraphWrapper.getTimeGraphViewer().getTime0() != startTime || fTimeGraphWrapper.getTimeGraphViewer().getTime1() != endTime) {
+            return true;
+        }
+
+        if (fZoomThread == null) {
+            // The zoom thread is null but we might be just about to create it (refresh called).
+            return fDirty.get() != 0;
+        }
+        // Dirty if the zoom thread is not done or if it hasn't zoomed all the
+        // way to the end of the window range. In the latter case, there should be
+        // a subsequent zoom thread that will be triggered.
+        return fDirty.get() != 0 || fZoomThread.getZoomStartTime() != startTime || fZoomThread.getZoomEndTime() != endTime;
     }
 
     private void createColumnSelectionListener(TreeViewer treeViewer) {
This page took 0.029723 seconds and 5 git commands to generate.