From: Marc-Andre Laperle Date: Thu, 18 Feb 2016 05:48:58 +0000 (-0500) Subject: lttng: Help stabilize some TimeGraphs tests X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=f149d124fd171582343d98e2982b136a93d32d1e;p=deliverable%2Ftracecompass.git lttng: Help stabilize some TimeGraphs tests 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 Reviewed-on: https://git.eclipse.org/r/66785 Reviewed-by: Patrick Tasse Tested-by: Patrick Tasse Reviewed-by: Hudson CI --- diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java index 2c5bb77d80..3f9d876fb7 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewSortingTest.java @@ -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(); diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java index 54799aa5bb..ba9e4e7c25 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java @@ -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(); diff --git a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/shared/org/eclipse/tracecompass/tmf/ui/swtbot/tests/shared/ConditionHelpers.java b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/shared/org/eclipse/tracecompass/tmf/ui/swtbot/tests/shared/ConditionHelpers.java index 00a6765644..29459f2648 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/shared/org/eclipse/tracecompass/tmf/ui/swtbot/tests/shared/ConditionHelpers.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui.swtbot.tests/shared/org/eclipse/tracecompass/tmf/ui/swtbot/tests/shared/ConditionHelpers.java @@ -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; } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java index d54ff4883f..d185edb99a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java @@ -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) {