1 /*******************************************************************************
2 * Copyright (c) 2015, 2016 Ericsson
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
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.lttng2
.ust
.ui
.swtbot
.tests
;
15 import static org
.junit
.Assert
.assertArrayEquals
;
16 import static org
.junit
.Assert
.assertEquals
;
17 import static org
.junit
.Assert
.assertNotNull
;
18 import static org
.junit
.Assert
.assertTrue
;
21 import java
.io
.IOException
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Arrays
;
25 import java
.util
.List
;
26 import java
.util
.stream
.Collectors
;
28 import org
.apache
.log4j
.ConsoleAppender
;
29 import org
.apache
.log4j
.Logger
;
30 import org
.apache
.log4j
.SimpleLayout
;
31 import org
.eclipse
.core
.runtime
.FileLocator
;
32 import org
.eclipse
.jdt
.annotation
.NonNull
;
33 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
34 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
35 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
36 import org
.eclipse
.swtbot
.swt
.finder
.junit
.SWTBotJunit4ClassRunner
;
37 import org
.eclipse
.swtbot
.swt
.finder
.utils
.SWTBotPreferences
;
38 import org
.eclipse
.swtbot
.swt
.finder
.waits
.Conditions
;
39 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotShell
;
40 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTable
;
41 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotToolbarButton
;
42 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTree
;
43 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTreeItem
;
44 import org
.eclipse
.tracecompass
.testtraces
.ctf
.CtfTestTrace
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
48 import org
.eclipse
.tracecompass
.tmf
.ctf
.core
.tests
.shared
.CtfTmfTestTraceUtils
;
49 import org
.eclipse
.tracecompass
.tmf
.ui
.dialog
.TmfFileDialogFactory
;
50 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.ConditionHelpers
;
51 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotUtils
;
52 import org
.eclipse
.tracecompass
.tmf
.ui
.tests
.shared
.WaitUtils
;
53 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.callstack
.CallStackView
;
54 import org
.junit
.After
;
55 import org
.junit
.Before
;
56 import org
.junit
.BeforeClass
;
57 import org
.junit
.Test
;
58 import org
.junit
.runner
.RunWith
;
60 import com
.google
.common
.collect
.ImmutableList
;
63 * Test for the Call Stack view in trace compass
65 @RunWith(SWTBotJunit4ClassRunner
.class)
66 public class CallStackViewTest
{
68 private static final String UST_ID
= "org.eclipse.linuxtools.lttng2.ust.tracetype";
70 private static final String PROJECT_NAME
= "TestForCallstack";
72 /** The Log4j logger instance. */
73 private static final Logger fLogger
= Logger
.getRootLogger();
74 private static SWTWorkbenchBot fBot
;
77 * Timestamps of consecutive events in the trace
79 private static final long TIMESTAMPS
[] = new long[] {
94 * Stack frames of consecutive events in the trace
96 private static final String
[] STACK_FRAMES
[] = new String
[][] {
97 { "0x40472b", "0x4045c8", "0x404412", "", "" },
98 { "0x40472b", "0x4045c8", "0x404412", "0x40392b", "" },
99 { "0x40472b", "0x4045c8", "0x404412", "", "" },
100 { "0x40472b", "0x4045c8", "", "", "" },
101 { "0x40472b", "0x4045c8", "0x404412", "", "" },
102 { "0x40472b", "0x4045c8", "0x404412", "0x40392b", "" },
103 { "0x40472b", "0x4045c8", "0x404412", "", "" },
104 { "0x40472b", "0x4045c8", "", "", "" },
105 { "0x40472b", "0x4045c8", "0x404412", "", "" },
106 { "0x40472b", "0x4045c8", "0x404412", "0x40392b", "" },
107 { "0x40472b", "0x4045c8", "0x404412", "", "" },
110 /** Tooltips of the toolbar buttons */
112 private static final @NonNull String ALIGN_VIEWS
= "Align Views";
113 private static final @NonNull String CONFIGURE_SYMBOL_PROVIDERS
= "Configure how the addresses are mapped to function names";
115 private static final @NonNull String SORT_BY_NAME
= "Sort threads by thread name";
116 private static final @NonNull String SORT_BY_ID
= "Sort threads by thread id";
117 private static final @NonNull String SORT_BY_START
= "Sort threads by start time";
119 private static final @NonNull String SHOW_VIEW_FILTERS
= "Show View Filters";
121 private static final @NonNull String RESET_TIME_SCALE
= "Reset the Time Scale to Default";
122 private static final @NonNull String SELECT_PREVIOUS_STATE_CHANGE
= "Select Previous State Change";
123 private static final @NonNull String SELECT_NEXT_STATE_CHANGE
= "Select Next State Change";
125 private static final @NonNull String ADD_BOOKMARK
= "Add Bookmark...";
126 private static final @NonNull String PREVIOUS_MARKER
= "Previous Marker";
127 private static final @NonNull String NEXT_MARKER
= "Next Marker";
129 private static final @NonNull String SELECT_PREVIOUS_ITEM
= "Select Previous Item";
130 private static final @NonNull String SELECT_NEXT_ITEM
= "Select Next Item";
131 private static final @NonNull String ZOOM_IN
= "Zoom In";
132 private static final @NonNull String ZOOM_OUT
= "Zoom Out";
134 private static final String PIN_VIEW
= "Pin View";
135 private static final List
<String
> TOOLBAR_BUTTONS_TOOLTIPS
= ImmutableList
.of(
136 ALIGN_VIEWS
, CONFIGURE_SYMBOL_PROVIDERS
,
138 SORT_BY_NAME
, SORT_BY_ID
, SORT_BY_START
,
142 RESET_TIME_SCALE
, SELECT_PREVIOUS_STATE_CHANGE
, SELECT_NEXT_STATE_CHANGE
,
144 ADD_BOOKMARK
, PREVIOUS_MARKER
, NEXT_MARKER
,
146 SELECT_PREVIOUS_ITEM
, SELECT_NEXT_ITEM
, ZOOM_IN
, ZOOM_OUT
,
154 public static void init() {
155 SWTBotUtils
.initialize();
157 Thread
.currentThread().setName("SWTBot Thread"); // for the debugger
158 /* set up for swtbot */
159 SWTBotPreferences
.TIMEOUT
= 20000; /* 20 second timeout */
160 fLogger
.addAppender(new ConsoleAppender(new SimpleLayout()));
161 fBot
= new SWTWorkbenchBot();
163 SWTBotUtils
.closeView("welcome", fBot
);
165 SWTBotUtils
.switchToTracingPerspective();
166 /* finish waiting for eclipse to load */
167 WaitUtils
.waitForJobs();
171 * Open a trace in an editor
174 public void beforeTest() {
175 SWTBotUtils
.createProject(PROJECT_NAME
);
176 SWTBotTreeItem treeItem
= SWTBotUtils
.selectTracesFolder(fBot
, PROJECT_NAME
);
177 assertNotNull(treeItem
);
178 final CtfTestTrace cygProfile
= CtfTestTrace
.CYG_PROFILE
;
179 final File file
= new File(CtfTmfTestTraceUtils
.getTrace(cygProfile
).getPath());
180 SWTBotUtils
.openTrace(PROJECT_NAME
, file
.getAbsolutePath(), UST_ID
);
181 SWTBotUtils
.openView(CallStackView
.ID
);
182 WaitUtils
.waitForJobs();
189 public void tearDown() {
190 fBot
.closeAllEditors();
191 SWTBotUtils
.deleteProject(PROJECT_NAME
, fBot
);
195 * Test if callstack is populated
198 public void testOpenCallstack() {
199 String node
= "glxgears-cyg-profile";
200 String processName
= "UNKNOWN";
201 String childName
= "glxgears-16073";
202 List
<String
> expected
= ImmutableList
.of("0x40472b", "", "", "", "");
204 SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
206 final SWTBotView viewBot1
= viewBot
;
207 SWTBotTree tree
= viewBot1
.bot().tree();
208 SWTBotTreeItem treeItem
= tree
.getTreeItem(node
).getNode(processName
);
209 assertEquals(childName
, treeItem
.getNodes().get(0));
210 List
<String
> names
= treeItem
.getNode(childName
).getNodes();
211 assertEquals(expected
, names
);
215 * Test check callstack at a time
218 public void testGoToTimeAndCheckStack() {
219 goToTime(TIMESTAMPS
[0]);
221 final SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
223 WaitUtils
.waitForJobs();
224 List
<String
> names
= getVisibleStackFrames(viewBot
);
225 assertArrayEquals(STACK_FRAMES
[0], names
.toArray());
229 * Test check callstack at a time after navigating
232 public void testGoToTimeGoBackAndForthAndCheckStack() {
233 int currentEventOffset
= 0;
234 goToTime(TIMESTAMPS
[currentEventOffset
]);
236 final SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
238 for (int i
= 0; i
< 10; i
++) {
239 viewBot
.toolbarPushButton(SELECT_NEXT_STATE_CHANGE
).click();
240 currentEventOffset
++;
241 fBot
.waitUntil(ConditionHelpers
.selectionInEventsTable(fBot
, TIMESTAMPS
[currentEventOffset
]));
242 WaitUtils
.waitForJobs();
243 assertArrayEquals(STACK_FRAMES
[currentEventOffset
], getVisibleStackFrames(viewBot
).toArray());
247 for (int i
= 0; i
< 2; i
++) {
248 viewBot
.toolbarPushButton(SELECT_PREVIOUS_STATE_CHANGE
).click();
249 currentEventOffset
--;
250 fBot
.waitUntil(ConditionHelpers
.selectionInEventsTable(fBot
, TIMESTAMPS
[currentEventOffset
]));
251 WaitUtils
.waitForJobs();
252 assertArrayEquals(STACK_FRAMES
[currentEventOffset
], getVisibleStackFrames(viewBot
).toArray());
254 // move up and down once to make sure it doesn't explode
255 viewBot
.toolbarPushButton(SELECT_PREVIOUS_ITEM
).click();
256 WaitUtils
.waitForJobs();
257 viewBot
.toolbarPushButton(SELECT_NEXT_ITEM
).click();
258 WaitUtils
.waitForJobs();
260 // Zoom in and out too
261 viewBot
.toolbarPushButton(ZOOM_IN
).click();
262 WaitUtils
.waitForJobs();
263 viewBot
.toolbarPushButton(ZOOM_OUT
).click();
264 WaitUtils
.waitForJobs();
268 * Test check callstack at a time with sorting, the trace is not sortable,
269 * this is a smoke test
272 public void testGoToTimeSortAndCheckStack() {
273 goToTime(TIMESTAMPS
[0]);
274 final SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
276 viewBot
.toolbarToggleButton(SORT_BY_NAME
).click();
277 viewBot
.toolbarToggleButton(SORT_BY_ID
).click();
278 viewBot
.toolbarToggleButton(SORT_BY_START
).click();
280 WaitUtils
.waitForJobs();
281 List
<String
> names
= getVisibleStackFrames(viewBot
);
282 assertArrayEquals(STACK_FRAMES
[0], names
.toArray());
285 private static List
<String
> getVisibleStackFrames(final SWTBotView viewBot
) {
286 SWTBotTree tree
= viewBot
.bot().tree();
287 return Arrays
.stream(tree
.getAllItems())
289 .flatMap(item
-> Arrays
.stream(item
.getItems()))
291 .flatMap(item
-> Arrays
.stream(item
.getItems()))
293 .flatMap(item
-> Arrays
.stream(item
.getItems()))
294 .map(item
-> item
.cell(0))
295 .collect(Collectors
.toList());
298 private static void goToTime(long timestamp
) {
299 SWTBotTable table
= fBot
.activeEditor().bot().table();
301 TmfSignalManager
.dispatchSignal(new TmfSelectionRangeUpdatedSignal(table
.widget
, TmfTimestamp
.fromNanos(timestamp
)));
302 fBot
.waitUntil(ConditionHelpers
.selectionInEventsTable(fBot
, timestamp
));
306 * Test check callstack at a time with function map
308 * @throws IOException
312 public void testGoToTimeAndCheckStackWithNames() throws IOException
{
313 goToTime(TIMESTAMPS
[0]);
314 final SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
316 SWTBotTree tree
= viewBot
.bot().tree();
317 Object mapObj
= CtfTmfTestTraceUtils
.class.getResource("cyg-profile-mapping.txt");
318 assertTrue(mapObj
instanceof URL
);
319 URL mapUrl
= (URL
) mapObj
;
321 String absoluteFile
= FileLocator
.toFileURL(mapUrl
).getFile();
322 TmfFileDialogFactory
.setOverrideFiles(absoluteFile
);
323 viewBot
.toolbarButton("Configure how the addresses are mapped to function names").click();
324 String shellTitle
= "Symbol mapping";
325 fBot
.waitUntil(Conditions
.shellIsActive(shellTitle
));
326 SWTBot shellBot
= fBot
.shell(shellTitle
).bot();
327 SWTBotShell activeShell
= shellBot
.activeShell();
328 shellBot
.radio(1).click();
329 shellBot
.button("Browse...", 1).click();
330 shellBot
.button("OK").click();
331 shellBot
.waitUntil(Conditions
.shellCloses(activeShell
));
332 // FIXME: remove when updates are propagated
333 goToTime(TIMESTAMPS
[0]);
334 WaitUtils
.waitForJobs();
335 List
<String
> names
= new ArrayList
<>();
337 for (SWTBotTreeItem swtBotTreeItem
: tree
.getAllItems()) {
338 for (SWTBotTreeItem items
: swtBotTreeItem
.getItems()) {
339 for (SWTBotTreeItem item
: items
.getItems()) {
340 names
.add(item
.cell(0));
344 List
<String
> functions
= getVisibleStackFrames(viewBot
);
345 assertEquals(ImmutableList
.of("glxgears-16073"), names
);
346 assertEquals(ImmutableList
.of("main", "event_loop", "handle_event", "", ""), functions
);
350 * Test check callstack toolbar buttons
353 public void testCallstackNavigation() {
354 SWTBotView viewBot
= fBot
.viewById(CallStackView
.ID
);
356 List
<String
> buttons
= new ArrayList
<>();
357 for (SWTBotToolbarButton swtBotToolbarButton
: viewBot
.getToolbarButtons()) {
358 buttons
.add(swtBotToolbarButton
.getToolTipText());
360 assertEquals(TOOLBAR_BUTTONS_TOOLTIPS
, buttons
);