1 /*******************************************************************************
2 * Copyright (c) 2016 École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.perf
.views
;
12 import static org
.junit
.Assert
.assertNotNull
;
15 import java
.util
.Collection
;
17 import org
.eclipse
.jdt
.annotation
.NonNull
;
18 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
19 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
20 import org
.eclipse
.swtbot
.swt
.finder
.junit
.SWTBotJunit4ClassRunner
;
21 import org
.eclipse
.swtbot
.swt
.finder
.utils
.SWTBotPreferences
;
22 import org
.eclipse
.swtbot
.swt
.finder
.waits
.Conditions
;
23 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotShell
;
24 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotText
;
25 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
32 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
33 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.ConditionHelpers
;
34 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotUtils
;
35 import org
.eclipse
.tracecompass
.tmf
.ui
.tests
.shared
.WaitUtils
;
36 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
37 import org
.eclipse
.ui
.IWorkbenchPart
;
38 import org
.junit
.After
;
39 import org
.junit
.Before
;
40 import org
.junit
.runner
.RunWith
;
43 * Base class to test the responsiveness of any views. The main method of this
44 * class, {@link #runTestWithTrace(String, String, Collection)}, will receive a
45 * collection of view IDs. For each view, the trace under test will be navigated
46 * when only the view is opened (closing all other listed views, all other
47 * opened views will remain opened) and also when all the views are opened
48 * simultaneously. In this last case, it will rename the trace so that events
49 * from when all the views are opened can be listed separately.
51 * @author Geneviève Bastien
53 @RunWith(SWTBotJunit4ClassRunner
.class)
54 public abstract class ViewsResponseTest
{
56 private static final String PROJECT_NAME
= "test";
58 private final @NonNull SWTWorkbenchBot fBot
= new SWTWorkbenchBot();
61 * Specific tests will prepare the workspace for the run. For example,
62 * concrete classes can open perspectives, open views, prepare the layout,
65 protected abstract void prepareWorkspace();
71 public void beforeClass() {
73 SWTBotUtils
.initialize();
74 Thread
.currentThread().setName("SWTBotTest");
75 /* set up for swtbot */
76 SWTBotPreferences
.TIMEOUT
= 60000; /* 60 second timeout */
77 SWTBotPreferences
.KEYBOARD_LAYOUT
= "EN_US";
78 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
79 SWTBotUtils
.closeView("welcome", bot
);
80 /* Prepare the workspace */
82 /* Finish waiting for eclipse to load */
83 WaitUtils
.waitForJobs();
86 SWTBotUtils
.createProject(PROJECT_NAME
);
90 * Deletes the project from the workspace
93 public void cleanUp() {
94 /* Close editors and delete project */
95 fBot
.closeAllEditors();
96 SWTBotUtils
.deleteProject(PROJECT_NAME
, fBot
);
99 private void closeAllViews(Collection
<String
> viewIDs
) {
100 viewIDs
.stream().forEach(id
-> {
101 SWTBotUtils
.openView(id
);
102 SWTBotUtils
.closeViewById(id
, fBot
);
107 * This method will be run when all views are still close, but the trace has
108 * been opened. For instance, if any analysis module need to have completed
109 * before the test, it can wait for completion here.
112 * The trace used for this test
114 protected abstract void beforeRunningTest(ITmfTrace trace
);
117 * Run this swtbot with the trace specified at the specified path. The trace
118 * will be navigate for each view ID separately, then, after renaming the
119 * trace, with all the views opened. After this test, all views will be
123 * The full path of the trace to open
125 * The trace type of the trace to open
127 * The IDs of the views to test.
129 protected void runTestWithTrace(String tracePath
, String traceType
, Collection
<String
> viewIDs
) {
130 closeAllViews(viewIDs
);
132 String traceName
= tracePath
.substring(tracePath
.lastIndexOf(File
.separator
, tracePath
.length() - 2) + 1, tracePath
.length() - 1);
133 SWTBotUtils
.openTrace(PROJECT_NAME
, tracePath
, traceType
);
135 // Make sure all the analyses we'll need are done
136 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
137 beforeRunningTest(trace
);
138 WaitUtils
.waitForJobs();
142 for (String viewID
: viewIDs
) {
143 SWTBotUtils
.openView(viewID
);
144 view
= fBot
.viewById(viewID
);
146 SWTBotUtils
.closeViewById(viewID
, fBot
);
150 fBot
.closeAllEditors();
152 // If there is only 1 view to test, return
153 if (viewIDs
.size() <= 1) {
155 closeAllViews(viewIDs
);
159 // Open all the views
161 for (String viewID
: viewIDs
) {
162 SWTBotUtils
.openView(viewID
);
164 view
= fBot
.viewById(viewID
);
168 // Rename the trace, so the results appear under another trace and
170 renameTrace(traceName
, traceName
+ " full");
174 fBot
.closeAllEditors();
177 closeAllViews(viewIDs
);
180 private void renameTrace(String oldName
, String newName
) {
182 SWTBotTreeItem traceItem
= SWTBotUtils
.getTraceProjectItem(fBot
, SWTBotUtils
.selectTracesFolder(fBot
, PROJECT_NAME
), oldName
);
184 traceItem
.contextMenu().menu("Rename...").click();
185 final String RENAME_TRACE_DIALOG_TITLE
= "Rename Trace";
186 fBot
.waitUntil(Conditions
.shellIsActive(RENAME_TRACE_DIALOG_TITLE
));
187 SWTBotShell shell
= fBot
.shell(RENAME_TRACE_DIALOG_TITLE
);
188 SWTBotText text
= shell
.bot().textWithLabel("New Trace name:");
189 text
.setText(newName
);
190 shell
.bot().button("OK").click();
191 fBot
.waitUntil(Conditions
.shellCloses(shell
));
192 fBot
.waitWhile(new ConditionHelpers
.ActiveEventsEditor(fBot
, null));
194 SWTBotTreeItem copiedItem
= SWTBotUtils
.getTraceProjectItem(fBot
, SWTBotUtils
.selectTracesFolder(fBot
, PROJECT_NAME
), newName
);
195 copiedItem
.contextMenu().menu("Open").click();
198 } catch (InterruptedException e
) {
200 WaitUtils
.waitForJobs();
203 // TODO: Add some vertical scrollings. With eventual 2D queries, that will
204 // be something to test as well
205 private void navigateTrace(SWTBotView view
) {
206 TmfTimeRange originalWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
207 TmfTimeRange selectionRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange();
208 IWorkbenchPart part
= view
.getViewReference().getPart(false);
210 // Set the time range to the full trace range
211 ITmfTrace activeTrace
= TmfTraceManager
.getInstance().getActiveTrace();
212 assertNotNull(activeTrace
);
213 TmfTimeRange fullRange
= new TmfTimeRange(activeTrace
.getStartTime(), activeTrace
.getEndTime());
214 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange
));
215 waitViewReady(part
, selectionRange
, fullRange
.getEndTime());
216 TmfTimeRange windowRange
= fullRange
;
218 // Zoom in 10 times 15 percent of the range and wait for the view to be
220 for (int i
= 0; i
< 10; i
++) {
221 double delta
= (windowRange
.getEndTime().getValue() - windowRange
.getStartTime().getValue()) * 0.15;
222 TmfTimeRange newWindowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos((long) (windowRange
.getStartTime().toNanos() + delta
)), TmfTimestamp
.fromNanos((long) (windowRange
.getEndTime().toNanos() - delta
)));
223 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange
));
224 windowRange
= newWindowRange
;
225 waitViewReady(part
, selectionRange
, newWindowRange
.getEndTime());
228 // At this zoom level, go to the end
229 long scrollTime
= (windowRange
.getEndTime().toNanos() - windowRange
.getStartTime().toNanos()) / 2;
230 windowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos(fullRange
.getEndTime().toNanos() - (2 * scrollTime
)), fullRange
.getEndTime());
231 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange
));
232 waitViewReady(part
, selectionRange
, windowRange
.getEndTime());
234 // Scroll back horizontally half the range at a time
235 for (int i
= 0; i
< 10; i
++) {
236 TmfTimeRange newWindowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos(windowRange
.getStartTime().toNanos() - scrollTime
), TmfTimestamp
.fromNanos(windowRange
.getEndTime().toNanos() - scrollTime
));
237 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange
));
238 windowRange
= newWindowRange
;
239 waitViewReady(part
, selectionRange
, newWindowRange
.getEndTime());
242 // then go all the way back to the beginning
243 windowRange
= new TmfTimeRange(fullRange
.getStartTime(), TmfTimestamp
.fromNanos(fullRange
.getStartTime().toNanos() + scrollTime
));
244 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange
));
245 waitViewReady(part
, selectionRange
, windowRange
.getEndTime());
247 // and zoom out again
248 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange
));
249 waitViewReady(part
, selectionRange
, fullRange
.getEndTime());
251 // Reset the original window range
252 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, originalWindowRange
));
253 waitViewReady(part
, selectionRange
, originalWindowRange
.getEndTime());
256 private void waitViewReady(IWorkbenchPart part
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
257 if (part
instanceof AbstractTimeGraphView
) {
258 fBot
.waitUntil(ConditionHelpers
.timeGraphIsReadyCondition((AbstractTimeGraphView
) part
, selectionRange
, visibleTime
));
260 // TODO Add conditions for other kind of views