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
.tmf
.ui
.swtbot
.tests
.viewers
.events
;
15 import static org
.junit
.Assert
.assertEquals
;
18 import java
.io
.IOException
;
19 import java
.util
.HashMap
;
21 import java
.util
.Map
.Entry
;
23 import org
.apache
.log4j
.ConsoleAppender
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.apache
.log4j
.SimpleLayout
;
26 import org
.eclipse
.swt
.graphics
.Point
;
27 import org
.eclipse
.swt
.graphics
.Rectangle
;
28 import org
.eclipse
.swt
.widgets
.Sash
;
29 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
30 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
31 import org
.eclipse
.swtbot
.swt
.finder
.junit
.SWTBotJunit4ClassRunner
;
32 import org
.eclipse
.swtbot
.swt
.finder
.matchers
.WidgetOfType
;
33 import org
.eclipse
.swtbot
.swt
.finder
.utils
.SWTBotPreferences
;
34 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.AbstractSWTBot
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.io
.BufferedRandomAccessFile
;
36 import org
.eclipse
.tracecompass
.tmf
.ui
.project
.wizards
.NewTmfProjectWizard
;
37 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotSash
;
38 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotTimeGraph
;
39 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotUtils
;
40 import org
.eclipse
.tracecompass
.tmf
.ui
.tests
.shared
.WaitUtils
;
41 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.callstack
.CallStackView
;
42 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.histogram
.HistogramView
;
43 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.timechart
.TimeChartView
;
44 import org
.eclipse
.tracecompass
.tmf
.ui
.widgets
.timegraph
.widgets
.TimeGraphControl
;
45 import org
.eclipse
.ui
.IFolderLayout
;
46 import org
.eclipse
.ui
.IPageLayout
;
47 import org
.eclipse
.ui
.IPerspectiveFactory
;
48 import org
.junit
.After
;
49 import org
.junit
.AfterClass
;
50 import org
.junit
.Before
;
51 import org
.junit
.BeforeClass
;
52 import org
.junit
.Test
;
53 import org
.junit
.runner
.RunWith
;
56 * Test common time axis for views
58 * @author Matthew Khouzam
60 @RunWith(SWTBotJunit4ClassRunner
.class)
61 public class TmfAlignTimeAxisTest
{
64 * wait for throttler (2x the throttler time)
66 private static final int SYNC_DELAY
= 1000;
67 private static final String TRACE_START
= "<trace>";
68 private static final String EVENT_BEGIN
= "<event timestamp=\"";
69 private static final String EVENT_MIDDLE
= " \" name=\"event\"><field name=\"field\" value=\"";
70 private static final String EVENT_END
= "\" type=\"int\" />" + "</event>";
71 private static final String TRACE_END
= "</trace>";
73 private static final String PROJET_NAME
= "TestAxisAlignment";
74 private static final int NUM_EVENTS
= 100;
76 * Using a small ratio for the editor so that other views have enough space
77 * to be drawn, even when a low screen resolution is used.
79 private static final float EDITOR_AREA_RATIO
= 0.10f
;
81 /** The Log4j logger instance. */
82 private static final Logger fLogger
= Logger
.getRootLogger();
83 private static SWTWorkbenchBot fBot
;
85 private static String
makeEvent(int ts
, int val
) {
86 return EVENT_BEGIN
+ Integer
.toString(ts
) + EVENT_MIDDLE
+ Integer
.toString(val
) + EVENT_END
+ "\n";
89 private static File fLocation
;
92 * Initialization, creates a temp trace
98 public static void init() throws IOException
{
99 SWTBotUtils
.initialize();
100 Thread
.currentThread().setName("SWTBot Thread"); // for the debugger
101 /* set up for swtbot */
102 SWTBotPreferences
.TIMEOUT
= 20000; /* 20 second timeout */
103 fLogger
.removeAllAppenders();
104 fLogger
.addAppender(new ConsoleAppender(new SimpleLayout()));
105 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
107 SWTBotUtils
.closeView("welcome", bot
);
109 SWTBotUtils
.switchToTracingPerspective();
110 /* finish waiting for eclipse to load */
111 WaitUtils
.waitForJobs();
112 fLocation
= File
.createTempFile("sample", ".xml");
113 try (BufferedRandomAccessFile braf
= new BufferedRandomAccessFile(fLocation
, "rw")) {
114 braf
.writeBytes(TRACE_START
);
115 for (int i
= 0; i
< NUM_EVENTS
; i
++) {
116 braf
.writeBytes(makeEvent(i
* 100, i
% 4));
118 braf
.writeBytes(TRACE_END
);
120 SWTBotUtils
.createProject(PROJET_NAME
);
121 SWTBotUtils
.selectTracesFolder(bot
, PROJET_NAME
);
128 public static void cleanup() {
129 SWTBotUtils
.deleteProject(PROJET_NAME
, new SWTWorkbenchBot());
131 fLogger
.removeAllAppenders();
138 public void before() {
139 SWTBotUtils
.openTrace(PROJET_NAME
, fLocation
.getAbsolutePath(), "org.eclipse.linuxtools.tmf.core.tests.xmlstub");
146 public void after() {
147 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
148 SWTBotUtils
.activeEventsEditor(bot
).close();
149 /* Switch back to Tracing perspective since several tests change the perspective */
150 SWTBotUtils
.switchToTracingPerspective();
151 SWTBotUtils
.closeSecondaryShells(fBot
);
155 * Test 3 views, none overlap, the histogram, callstack and timechart are
156 * aligned. The histogram is moved, we check that the callstack and
160 public void testMoveHistogramOthersFollow() {
161 fBot
= new SWTWorkbenchBot();
162 switchToPerspective(AlignPerspectiveFactory1
.ID
);
163 testAligned(HistogramView
.ID
, CallStackView
.ID
, TimeChartView
.ID
);
167 * Test 3 views, none overlap, the histogram, callstack and timechart are
168 * aligned. The callstack is moved, we check that the histogram and
172 public void testMoveCallstackOthersFollow() {
173 fBot
= new SWTWorkbenchBot();
174 switchToPerspective(AlignPerspectiveFactory1
.ID
);
175 testAligned(CallStackView
.ID
, HistogramView
.ID
, TimeChartView
.ID
);
179 * Test 3 views, overlap on the resizing view. The histogram and timechart
180 * are overlapping, and the callstack is aligned. The histogram is moved, we
181 * check that the callstack follows. The hidden timechart is not checked.
184 public void testOverlappingHistogramMove() {
185 fBot
= new SWTWorkbenchBot();
186 switchToPerspective(AlignPerspectiveFactory2
.ID
);
187 testAligned(HistogramView
.ID
, CallStackView
.ID
);
191 * Test 3 views, overlap on the resizing view. The histogram and timechart
192 * are overlapping, and the callstack is aligned. The callstack is moved, we
193 * check that the histogram follows. The hidden timechart is not checked.
196 public void testOverlappingCallstackMove() {
197 fBot
= new SWTWorkbenchBot();
198 switchToPerspective(AlignPerspectiveFactory2
.ID
);
199 testAligned(CallStackView
.ID
, HistogramView
.ID
);
203 * Test 3 views. No overlap. The histogram and timechart are aligned, but
204 * the callstack is not aligned. The histogram is moved, we check that the
205 * timechart follows and that the callstack does NOT follow.
208 public void testNotOverlappingHistogramMove() {
209 fBot
= new SWTWorkbenchBot();
210 switchToPerspective(AlignPerspectiveFactory3
.ID
);
211 testAligned(HistogramView
.ID
, TimeChartView
.ID
);
212 testNotAligned(HistogramView
.ID
, CallStackView
.ID
);
216 * Test 3 views. No overlap. The histogram and timechart are aligned, but
217 * the callstack is not aligned. The callstack is moved, we check that the
218 * histogram and timechart do NOT follow.
221 public void testNotOverlappingCallstackMove() {
222 fBot
= new SWTWorkbenchBot();
223 switchToPerspective(AlignPerspectiveFactory3
.ID
);
224 testNotAligned(CallStackView
.ID
, HistogramView
.ID
, TimeChartView
.ID
);
227 private static void switchToPerspective(String id
) {
228 // switch to the proper perspective and wait for views to align
229 SWTBotUtils
.switchToPerspective(id
);
230 WaitUtils
.waitForJobs();
231 SWTBotUtils
.delay(SYNC_DELAY
);
234 private static AbstractSWTBot
<?
> getAlignmentControl(String viewId
) {
235 SWTBotView viewBot
= fBot
.viewById(viewId
);
237 case HistogramView
.ID
:
238 case CallStackView
.ID
:
239 return new SWTBotSash(viewBot
.bot().widget(WidgetOfType
.widgetOfType(Sash
.class)));
240 case TimeChartView
.ID
:
241 return new SWTBotTimeGraph(viewBot
.bot().widget(WidgetOfType
.widgetOfType(TimeGraphControl
.class)));
247 private static void testAligned(String masterView
, String
... slaveViews
) {
248 final int offset
= 50;
250 // select alignment controls and get their original alignment positions
251 AbstractSWTBot
<?
> master
= getAlignmentControl(masterView
);
252 int masterOrigin
= getAlignmentPosition(master
);
253 Map
<AbstractSWTBot
<?
>, Integer
> slaveMap
= new HashMap
<>();
254 for (String slaveView
: slaveViews
) {
255 AbstractSWTBot
<?
> slave
= getAlignmentControl(slaveView
);
256 int slaveOrigin
= getAlignmentPosition(slave
);
257 slaveMap
.put(slave
, slaveOrigin
);
260 // change master position
261 setAlignmentPosition(master
, masterOrigin
+ offset
);
263 // check resulting alignment positions, slaves follow
264 assertEquals(masterOrigin
+ offset
, getAlignmentPosition(master
), 2);
265 for (Entry
<AbstractSWTBot
<?
>, Integer
> slave
: slaveMap
.entrySet()) {
266 assertEquals(slave
.getValue() + offset
, getAlignmentPosition(slave
.getKey()), 2);
269 // reset original alignment position
270 setAlignmentPosition(master
, masterOrigin
);
273 private static void testNotAligned(String masterView
, String
... nonSlaveViews
) {
274 final int offset
= 50;
276 // select alignment controls and get their original alignment positions
277 AbstractSWTBot
<?
> master
= getAlignmentControl(masterView
);
278 int masterOrigin
= getAlignmentPosition(master
);
279 Map
<AbstractSWTBot
<?
>, Integer
> nonSlaveMap
= new HashMap
<>();
280 for (String nonSlaveView
: nonSlaveViews
) {
281 AbstractSWTBot
<?
> nonSlave
= getAlignmentControl(nonSlaveView
);
282 int nonSlaveOrigin
= getAlignmentPosition(nonSlave
);
283 nonSlaveMap
.put(nonSlave
, nonSlaveOrigin
);
286 // change master position
287 setAlignmentPosition(master
, masterOrigin
+ offset
);
289 // check resulting alignment positions, non-slaves do not follow
290 assertEquals(masterOrigin
+ offset
, getAlignmentPosition(master
), 2);
291 for (Entry
<AbstractSWTBot
<?
>, Integer
> nonSlave
: nonSlaveMap
.entrySet()) {
292 assertEquals((int) nonSlave
.getValue(), getAlignmentPosition(nonSlave
.getKey()));
295 // reset original alignment position
296 setAlignmentPosition(master
, masterOrigin
);
299 private static int getAlignmentPosition(AbstractSWTBot
<?
> control
) {
300 if (control
instanceof SWTBotSash
) {
301 Rectangle bounds
= ((SWTBotSash
) control
).getBounds();
302 return bounds
.x
+ bounds
.width
/ 2;
303 } else if (control
instanceof SWTBotTimeGraph
) {
304 return ((SWTBotTimeGraph
) control
).getNameSpace();
309 private static void setAlignmentPosition(AbstractSWTBot
<?
> control
, int position
) {
310 if (control
instanceof SWTBotSash
) {
311 SWTBotSash sash
= (SWTBotSash
) control
;
312 Rectangle bounds
= sash
.getBounds();
313 Point dst
= new Point(position
, bounds
.y
+ bounds
.height
/ 2);
315 } else if (control
instanceof SWTBotTimeGraph
) {
316 ((SWTBotTimeGraph
) control
).setNameSpace(position
);
318 // wait for alignment
319 WaitUtils
.waitForJobs();
320 SWTBotUtils
.delay(SYNC_DELAY
);
324 * Histogram, Callstack and timechart aligned but in different sites
326 public static class AlignPerspectiveFactory1
implements IPerspectiveFactory
{
328 /** The Perspective ID */
329 public static final String ID
= "org.eclipse.linuxtools.tmf.test.align.1"; //$NON-NLS-1$
332 public void createInitialLayout(IPageLayout layout
) {
333 if (layout
== null) {
338 layout
.setEditorAreaVisible(true);
341 layout
.setEditorAreaVisible(true);
343 // Create the top left folder
344 IFolderLayout topLeftFolder
= layout
.createFolder("topLeftFolder", IPageLayout
.LEFT
, 0.4f
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
345 topLeftFolder
.addView(IPageLayout
.ID_PROJECT_EXPLORER
);
347 // Create the top right folder
348 IFolderLayout topRightFolder
= layout
.createFolder("topRightFolder", IPageLayout
.BOTTOM
, EDITOR_AREA_RATIO
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
349 topRightFolder
.addView(HistogramView
.ID
);
351 // Create the middle right folder
352 IFolderLayout middleRightFolder
= layout
.createFolder("middleRightFolder", IPageLayout
.BOTTOM
, 0.50f
, "topRightFolder"); //$NON-NLS-1$
353 middleRightFolder
.addView(CallStackView
.ID
);
355 // Create the bottom right folder
356 IFolderLayout bottomRightFolder
= layout
.createFolder("bottomRightFolder", IPageLayout
.BOTTOM
, 0.65f
, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
357 bottomRightFolder
.addView(TimeChartView
.ID
);
359 // Populate menus, etc
360 layout
.addPerspectiveShortcut(ID
);
361 layout
.addNewWizardShortcut(NewTmfProjectWizard
.ID
);
367 * Timechart and Histogram share a site, all views aligned
369 public static class AlignPerspectiveFactory2
implements IPerspectiveFactory
{
371 /** The Perspective ID */
372 public static final String ID
= "org.eclipse.linuxtools.tmf.test.align.2"; //$NON-NLS-1$
375 public void createInitialLayout(IPageLayout layout
) {
376 if (layout
== null) {
381 layout
.setEditorAreaVisible(true);
384 layout
.setEditorAreaVisible(true);
386 // Create the top left folder
387 IFolderLayout topLeftFolder
= layout
.createFolder("topLeftFolder", IPageLayout
.LEFT
, 0.4f
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
388 topLeftFolder
.addView(IPageLayout
.ID_PROJECT_EXPLORER
);
390 // Create the middle right folder
391 IFolderLayout middleRightFolder
= layout
.createFolder("middleRightFolder", IPageLayout
.BOTTOM
, EDITOR_AREA_RATIO
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
392 middleRightFolder
.addView(HistogramView
.ID
);
393 middleRightFolder
.addView(TimeChartView
.ID
);
395 // Create the bottom right folder
396 IFolderLayout bottomRightFolder
= layout
.createFolder("bottomRightFolder", IPageLayout
.BOTTOM
, 0.65f
, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
397 bottomRightFolder
.addView(CallStackView
.ID
);
399 // Populate menus, etc
400 layout
.addPerspectiveShortcut(ID
);
401 layout
.addNewWizardShortcut(NewTmfProjectWizard
.ID
);
407 * Histogram and timechart aligned, callstack not aligned
409 public static class AlignPerspectiveFactory3
implements IPerspectiveFactory
{
411 /** The Perspective ID */
412 public static final String ID
= "org.eclipse.linuxtools.tmf.test.align.3"; //$NON-NLS-1$
415 public void createInitialLayout(IPageLayout layout
) {
416 if (layout
== null) {
421 layout
.setEditorAreaVisible(true);
424 layout
.setEditorAreaVisible(true);
426 // Create the top left folder
427 IFolderLayout topLeftFolder
= layout
.createFolder("topLeftFolder", IPageLayout
.LEFT
, 0.4f
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
428 topLeftFolder
.addView(IPageLayout
.ID_PROJECT_EXPLORER
);
430 IFolderLayout bottomLeftFolder
= layout
.createFolder("bottomLeftFolder", IPageLayout
.BOTTOM
, 0.5f
, "topLeftFolder"); //$NON-NLS-1$
431 bottomLeftFolder
.addView(CallStackView
.ID
);
433 // Create the middle right folder
434 IFolderLayout middleRightFolder
= layout
.createFolder("middleRightFolder", IPageLayout
.BOTTOM
, EDITOR_AREA_RATIO
, IPageLayout
.ID_EDITOR_AREA
); //$NON-NLS-1$
435 middleRightFolder
.addView(HistogramView
.ID
);
437 // Create the bottom right folder
438 IFolderLayout bottomRightFolder
= layout
.createFolder("bottomRightFolder", IPageLayout
.BOTTOM
, 0.65f
, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
439 bottomRightFolder
.addView(TimeChartView
.ID
);
441 // Populate menus, etc
442 layout
.addPerspectiveShortcut(ID
);
443 layout
.addNewWizardShortcut(NewTmfProjectWizard
.ID
);