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
;
13 import java
.util
.Collection
;
15 import org
.eclipse
.jdt
.annotation
.NonNull
;
16 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
17 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
18 import org
.eclipse
.swtbot
.swt
.finder
.junit
.SWTBotJunit4ClassRunner
;
19 import org
.eclipse
.swtbot
.swt
.finder
.utils
.SWTBotPreferences
;
20 import org
.eclipse
.swtbot
.swt
.finder
.waits
.Conditions
;
21 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotShell
;
22 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotText
;
23 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
28 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
29 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
30 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
31 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.ConditionHelpers
;
32 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotUtils
;
33 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timegraph
.AbstractTimeGraphView
;
34 import org
.eclipse
.ui
.IWorkbenchPart
;
35 import org
.junit
.After
;
36 import org
.junit
.Before
;
37 import org
.junit
.runner
.RunWith
;
40 * Base class to test the responsiveness of any views. The main method of this
41 * class, {@link #runTestWithTrace(String, String, Collection)}, will receive a
42 * collection of view IDs. For each view, the trace under test will be navigated
43 * when only the view is opened (closing all other listed views, all other
44 * opened views will remain opened) and also when all the views are opened
45 * simultaneously. In this last case, it will rename the trace so that events
46 * from when all the views are opened can be listed separately.
48 * @author Geneviève Bastien
50 @RunWith(SWTBotJunit4ClassRunner
.class)
51 public abstract class ViewsResponseTest
{
53 private static final String PROJECT_NAME
= "test";
55 private final @NonNull SWTWorkbenchBot fBot
= new SWTWorkbenchBot();
58 * Specific tests will prepare the workspace for the run. For example,
59 * concrete classes can open perspectives, open views, prepare the layout,
62 protected abstract void prepareWorkspace();
68 public void beforeClass() {
70 SWTBotUtils
.initialize();
71 Thread
.currentThread().setName("SWTBotTest");
72 /* set up for swtbot */
73 SWTBotPreferences
.TIMEOUT
= 60000; /* 60 second timeout */
74 SWTBotPreferences
.KEYBOARD_LAYOUT
= "EN_US";
75 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
76 SWTBotUtils
.closeView("welcome", bot
);
77 /* Prepare the workspace */
79 /* Finish waiting for eclipse to load */
80 SWTBotUtils
.waitForJobs();
83 SWTBotUtils
.createProject(PROJECT_NAME
);
87 * Deletes the project from the workspace
90 public void cleanUp() {
91 /* Close editors and delete project */
92 fBot
.closeAllEditors();
93 SWTBotUtils
.deleteProject(PROJECT_NAME
, fBot
);
96 private void closeAllViews(Collection
<String
> viewIDs
) {
97 viewIDs
.stream().forEach(id
-> {
98 SWTBotUtils
.openView(id
);
99 SWTBotUtils
.closeViewById(id
, fBot
);
104 * This method will be run when all views are still close, but the trace has
105 * been opened. For instance, if any analysis module need to have completed
106 * before the test, it can wait for completion here.
109 * The trace used for this test
111 protected abstract void beforeRunningTest(ITmfTrace trace
);
114 * Run this swtbot with the trace specified at the specified path. The trace
115 * will be navigate for each view ID separately, then, after renaming the
116 * trace, with all the views opened. After this test, all views will be
120 * The full path of the trace to open
122 * The trace type of the trace to open
124 * The IDs of the views to test.
126 protected void runTestWithTrace(String tracePath
, String traceType
, Collection
<String
> viewIDs
) {
127 closeAllViews(viewIDs
);
129 String traceName
= tracePath
.substring(tracePath
.lastIndexOf(File
.separator
, tracePath
.length() - 2) + 1, tracePath
.length() - 1);
130 SWTBotUtils
.openTrace(PROJECT_NAME
, tracePath
, traceType
);
132 // Make sure all the analyses we'll need are done
133 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
134 beforeRunningTest(trace
);
135 SWTBotUtils
.waitForJobs();
139 for (String viewID
: viewIDs
) {
140 SWTBotUtils
.openView(viewID
);
141 view
= fBot
.viewById(viewID
);
143 SWTBotUtils
.closeViewById(viewID
, fBot
);
147 fBot
.closeAllEditors();
149 // If there is only 1 view to test, return
150 if (viewIDs
.size() <= 1) {
152 closeAllViews(viewIDs
);
156 // Open all the views
158 for (String viewID
: viewIDs
) {
159 SWTBotUtils
.openView(viewID
);
161 view
= fBot
.viewById(viewID
);
165 // Rename the trace, so the results appear under another trace and
167 renameTrace(traceName
, traceName
+ " full");
171 fBot
.closeAllEditors();
174 closeAllViews(viewIDs
);
177 private void renameTrace(String oldName
, String newName
) {
179 SWTBotTreeItem traceItem
= SWTBotUtils
.getTraceProjectItem(fBot
, SWTBotUtils
.selectTracesFolder(fBot
, PROJECT_NAME
), oldName
);
181 traceItem
.contextMenu().menu("Rename...").click();
182 final String RENAME_TRACE_DIALOG_TITLE
= "Rename Trace";
183 fBot
.waitUntil(Conditions
.shellIsActive(RENAME_TRACE_DIALOG_TITLE
));
184 SWTBotShell shell
= fBot
.shell(RENAME_TRACE_DIALOG_TITLE
);
185 SWTBotText text
= shell
.bot().textWithLabel("New Trace name:");
186 text
.setText(newName
);
187 shell
.bot().button("OK").click();
188 fBot
.waitUntil(Conditions
.shellCloses(shell
));
189 fBot
.waitWhile(new ConditionHelpers
.ActiveEventsEditor(fBot
, null));
191 SWTBotTreeItem copiedItem
= SWTBotUtils
.getTraceProjectItem(fBot
, SWTBotUtils
.selectTracesFolder(fBot
, PROJECT_NAME
), newName
);
192 copiedItem
.contextMenu().menu("Open").click();
195 } catch (InterruptedException e
) {
197 SWTBotUtils
.waitForJobs();
200 // TODO: Add some vertical scrollings. With eventual 2D queries, that will
201 // be something to test as well
202 private void navigateTrace(SWTBotView view
) {
203 TmfTimeRange originalWindowRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getWindowRange();
204 TmfTimeRange selectionRange
= TmfTraceManager
.getInstance().getCurrentTraceContext().getSelectionRange();
205 IWorkbenchPart part
= view
.getViewReference().getPart(false);
207 // Set the time range to the full trace range
208 ITmfTrace activeTrace
= TmfTraceManager
.getInstance().getActiveTrace();
209 TmfTimeRange fullRange
= new TmfTimeRange(activeTrace
.getStartTime(), activeTrace
.getEndTime());
210 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange
));
211 waitViewReady(part
, selectionRange
, fullRange
.getEndTime());
212 TmfTimeRange windowRange
= fullRange
;
214 // Zoom in 10 times 15 percent of the range and wait for the view to be
216 for (int i
= 0; i
< 10; i
++) {
217 double delta
= (windowRange
.getEndTime().getValue() - windowRange
.getStartTime().getValue()) * 0.15;
218 TmfTimeRange newWindowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos((long) (windowRange
.getStartTime().toNanos() + delta
)), TmfTimestamp
.fromNanos((long) (windowRange
.getEndTime().toNanos() - delta
)));
219 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange
));
220 windowRange
= newWindowRange
;
221 waitViewReady(part
, selectionRange
, newWindowRange
.getEndTime());
224 // At this zoom level, go to the end
225 long scrollTime
= (windowRange
.getEndTime().toNanos() - windowRange
.getStartTime().toNanos()) / 2;
226 windowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos(fullRange
.getEndTime().toNanos() - (2 * scrollTime
)), fullRange
.getEndTime());
227 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange
));
228 waitViewReady(part
, selectionRange
, windowRange
.getEndTime());
230 // Scroll back horizontally half the range at a time
231 for (int i
= 0; i
< 10; i
++) {
232 TmfTimeRange newWindowRange
= new TmfTimeRange(TmfTimestamp
.fromNanos(windowRange
.getStartTime().toNanos() - scrollTime
), TmfTimestamp
.fromNanos(windowRange
.getEndTime().toNanos() - scrollTime
));
233 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, newWindowRange
));
234 windowRange
= newWindowRange
;
235 waitViewReady(part
, selectionRange
, newWindowRange
.getEndTime());
238 // then go all the way back to the beginning
239 windowRange
= new TmfTimeRange(fullRange
.getStartTime(), TmfTimestamp
.fromNanos(fullRange
.getStartTime().toNanos() + scrollTime
));
240 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, windowRange
));
241 waitViewReady(part
, selectionRange
, windowRange
.getEndTime());
243 // and zoom out again
244 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, fullRange
));
245 waitViewReady(part
, selectionRange
, fullRange
.getEndTime());
247 // Reset the original window range
248 TmfSignalManager
.dispatchSignal(new TmfWindowRangeUpdatedSignal(this, originalWindowRange
));
249 waitViewReady(part
, selectionRange
, originalWindowRange
.getEndTime());
252 private void waitViewReady(IWorkbenchPart part
, @NonNull TmfTimeRange selectionRange
, @NonNull ITmfTimestamp visibleTime
) {
253 if (part
instanceof AbstractTimeGraphView
) {
254 fBot
.waitUntil(ConditionHelpers
.timeGraphIsReadyCondition((AbstractTimeGraphView
) part
, selectionRange
, visibleTime
));
256 // TODO Add conditions for other kind of views