tmf: Add waitUntil / condition to tmf.ui.tests
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui.swtbot.tests / src / org / eclipse / tracecompass / tmf / ui / swtbot / tests / viewers / events / TmfAlignTimeAxisTest.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
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 *
9 * Contributors:
10 * Matthew Khouzam - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.tmf.ui.swtbot.tests.viewers.events;
14
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertNotNull;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.Arrays;
21
22 import org.apache.log4j.ConsoleAppender;
23 import org.apache.log4j.Logger;
24 import org.apache.log4j.SimpleLayout;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.custom.SashForm;
27 import org.eclipse.swt.graphics.Point;
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.finders.UIThreadRunnable;
32 import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
33 import org.eclipse.swtbot.swt.finder.results.VoidResult;
34 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
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.SWTBotUtils;
39 import org.eclipse.tracecompass.tmf.ui.tests.shared.WaitUtils;
40 import org.eclipse.tracecompass.tmf.ui.views.callstack.CallStackView;
41 import org.eclipse.tracecompass.tmf.ui.views.histogram.HistogramView;
42 import org.eclipse.tracecompass.tmf.ui.views.timechart.TimeChartView;
43 import org.eclipse.ui.IFolderLayout;
44 import org.eclipse.ui.IPageLayout;
45 import org.eclipse.ui.IPerspectiveFactory;
46 import org.hamcrest.BaseMatcher;
47 import org.hamcrest.Description;
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;
54
55 /**
56 * Test common time axis for views
57 *
58 * @author Matthew Khouzam
59 */
60 @RunWith(SWTBotJunit4ClassRunner.class)
61 public class TmfAlignTimeAxisTest {
62
63 /**
64 * wait for throttler (2x the throttler time)
65 */
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>";
72
73 private static final String PROJET_NAME = "TestAxisAlignment";
74 private static final int NUM_EVENTS = 100;
75 /**
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.
78 */
79 private static final float EDITOR_AREA_RATIO = 0.10f;
80
81 /** The Log4j logger instance. */
82 private static final Logger fLogger = Logger.getRootLogger();
83 private static SWTWorkbenchBot fBot;
84
85 private static String makeEvent(int ts, int val) {
86 return EVENT_BEGIN + Integer.toString(ts) + EVENT_MIDDLE + Integer.toString(val) + EVENT_END + "\n";
87 }
88
89 private static File fLocation;
90 private static final BaseMatcher<Sash> SASH_MATCHER = new SashMatcher();
91
92 /**
93 * Initialization, creates a temp trace
94 *
95 * @throws IOException
96 * should not happen
97 */
98 @BeforeClass
99 public static void init() throws IOException {
100 SWTBotUtils.initialize();
101 Thread.currentThread().setName("SWTBot Thread"); // for the debugger
102 /* set up for swtbot */
103 SWTBotPreferences.TIMEOUT = 20000; /* 20 second timeout */
104 fLogger.removeAllAppenders();
105 fLogger.addAppender(new ConsoleAppender(new SimpleLayout()));
106 SWTWorkbenchBot bot = new SWTWorkbenchBot();
107
108 SWTBotUtils.closeView("welcome", bot);
109
110 SWTBotUtils.switchToTracingPerspective();
111 /* finish waiting for eclipse to load */
112 WaitUtils.waitForJobs();
113 fLocation = File.createTempFile("sample", ".xml");
114 try (BufferedRandomAccessFile braf = new BufferedRandomAccessFile(fLocation, "rw")) {
115 braf.writeBytes(TRACE_START);
116 for (int i = 0; i < NUM_EVENTS; i++) {
117 braf.writeBytes(makeEvent(i * 100, i % 4));
118 }
119 braf.writeBytes(TRACE_END);
120 }
121 SWTBotUtils.createProject(PROJET_NAME);
122 SWTBotUtils.selectTracesFolder(bot, PROJET_NAME);
123 }
124
125 /**
126 * Delete file
127 */
128 @AfterClass
129 public static void cleanup() {
130 SWTBotUtils.deleteProject(PROJET_NAME, new SWTWorkbenchBot());
131 fLocation.delete();
132 fLogger.removeAllAppenders();
133 }
134
135 /**
136 * Open the trace
137 */
138 @Before
139 public void before() {
140 SWTBotUtils.openTrace(PROJET_NAME, fLocation.getAbsolutePath(), "org.eclipse.linuxtools.tmf.core.tests.xmlstub");
141 }
142
143 /**
144 * Close the trace
145 */
146 @After
147 public void after() {
148 SWTWorkbenchBot bot = new SWTWorkbenchBot();
149 SWTBotUtils.activeEventsEditor(bot).close();
150 /* Switch back to Tracing perspective since several tests change the perspective */
151 SWTBotUtils.switchToTracingPerspective();
152 SWTBotUtils.closeSecondaryShells(fBot);
153 }
154
155 /**
156 * Test 3 views, none overlap, the histogram, the callstack and the
157 * timechart are aligned, the histogram is moved, callstack and timechart
158 * follow
159 */
160 @Test
161 public void testMoveHistogramCallstackFollows() {
162 fBot = new SWTWorkbenchBot();
163 SWTBotUtils.switchToPerspective(AlignPerspectiveFactory1.ID);
164 testOverlap(HistogramView.ID, CallStackView.ID);
165 }
166
167 /**
168 * Test 3 views, none overlap, the histogram, the callstack and the
169 * timechart are aligned, the callstack is moved, histogram and timechart
170 * follow
171 */
172 @Test
173 public void testMoveCallstackHistogramFollows() {
174 fBot = new SWTWorkbenchBot();
175 SWTBotUtils.switchToPerspective(AlignPerspectiveFactory1.ID);
176 testOverlap(CallStackView.ID, HistogramView.ID);
177 }
178
179 /**
180 * Test 3 views, overlap on the resizing view. The timechart and callstack
181 * are overlapping. Test that when the histogram moves, the timechart
182 * follows. Hidden views are not tested as their state does not matter until
183 * they are displayed
184 */
185 @Test
186 public void testOverlappingHistogramMove() {
187 fBot = new SWTWorkbenchBot();
188 SWTBotUtils.switchToPerspective(AlignPerspectiveFactory2.ID);
189 testOverlap(HistogramView.ID, CallStackView.ID);
190 }
191
192 /**
193 * Test 3 views, overlap on the resizing view. The timechart and callstack
194 * are overlapping. Test that when the timechart moves, the histogram
195 * follows. Hidden views are not tested as their state does not matter until
196 * they are displayed
197 */
198 @Test
199 public void testOverlappingTimechartMove() {
200 fBot = new SWTWorkbenchBot();
201 SWTBotUtils.switchToPerspective(AlignPerspectiveFactory2.ID);
202 testOverlap(CallStackView.ID, HistogramView.ID);
203 }
204
205 /**
206 * Test 3 views. No overlap. The callstack is not aligned with the
207 * histogram, the histogram is moved, we check that the callstack does NOT
208 * follow
209 */
210 @Test
211 public void testNotOverlappingHistogramMove() {
212 fBot = new SWTWorkbenchBot();
213 testNonOverlap(HistogramView.ID, CallStackView.ID);
214 }
215
216 /**
217 * Test 3 views. No overlap. The callstack is not aligned with the
218 * histogram, the callstack is moved, we check that the histogram does NOT
219 * follow
220 */
221 @Test
222 public void testNotOverlappingCallstackMove() {
223 fBot = new SWTWorkbenchBot();
224 testNonOverlap(CallStackView.ID, HistogramView.ID);
225 }
226
227 private static void testNonOverlap(String vId1, String vId2) {
228 final int offset = 100;
229 // switch to the proper perspective and wait for views to align
230 SWTBotUtils.switchToPerspective(AlignPerspectiveFactory3.ID);
231 WaitUtils.waitForJobs();
232 SWTBotUtils.delay(SYNC_DELAY);
233 // get views
234 SWTBotView masterView = fBot.viewById(vId1);
235 SWTBotView slaveView = fBot.viewById(vId2);
236 final Sash slaveSash = slaveView.bot().widget(SASH_MATCHER, 0);
237 SWTBotSash slaveSashBot = new SWTBotSash(slaveSash, null);
238 Point before = slaveSashBot.getPoint();
239 // move master and wait for slaves to follow
240 drag(masterView, offset);
241 WaitUtils.waitForJobs();
242 SWTBotUtils.delay(SYNC_DELAY);
243 // verify that the slave did not follow
244 assertEquals(before, slaveSashBot.getPoint());
245 // put everything back the way it was
246 drag(masterView, -offset);
247 SWTBotUtils.delay(SYNC_DELAY);
248 }
249
250 private static final class SashMatcher extends BaseMatcher<Sash> {
251 @Override
252 public boolean matches(Object item) {
253 return (item instanceof Sash);
254 }
255
256 @Override
257 public void describeTo(Description description) {
258 }
259 }
260
261 private static final class SashFormMatcher extends BaseMatcher<SashForm> {
262 @Override
263 public boolean matches(Object item) {
264 return (item instanceof SashForm);
265 }
266
267 @Override
268 public void describeTo(Description description) {
269 }
270 }
271
272 /**
273 * Simulate a drag operation using "setWeights"
274 */
275 private static void drag(final SWTBotView view, final int offset) {
276 // this is the final sash form
277 final SashForm sashForm = view.bot().widget(new SashFormMatcher(), 0);
278 assertNotNull(sashForm);
279 // resize widgets using sashform
280 UIThreadRunnable.syncExec(new VoidResult() {
281 @Override
282 public void run() {
283 int[] originalWeights = sashForm.getWeights();
284 int[] newWeights = Arrays.copyOf(originalWeights, originalWeights.length);
285 newWeights[0] += offset;
286 newWeights[1] -= offset;
287 sashForm.setWeights(newWeights);
288 sashForm.getParent().layout();
289 }
290 });
291 // send update signals
292 UIThreadRunnable.syncExec(new VoidResult() {
293 @Override
294 public void run() {
295 sashForm.getChildren()[0].notifyListeners(SWT.Resize, null);
296 sashForm.getChildren()[1].notifyListeners(SWT.Resize, null);
297 /*
298 * This one is the most important, the previous two are added to
299 * be a good citizen, this event (selection) is the one that
300 * triggers an alignment
301 */
302 sashForm.getChildren()[2].notifyListeners(SWT.Selection, null);
303 }
304 });
305 }
306
307 private static void testOverlap(String masterView, String slaveView) {
308 final int offset = 100;
309 final int delta = offset / 2;
310 // wait for the perspective switch to propagate alignments
311 WaitUtils.waitForJobs();
312 SWTBotUtils.delay(SYNC_DELAY);
313 // select master and slave parts to observe
314 SWTBotView masterViewBot = fBot.viewById(masterView);
315 final Sash masterSash = masterViewBot.bot().widget(SASH_MATCHER, 0);
316 SWTBotSash masterSashBot = new SWTBotSash(masterSash, null);
317
318 SWTBotView slaveViewBot = fBot.viewById(slaveView);
319 final Sash slaveSash = slaveViewBot.bot().widget(SASH_MATCHER, 0);
320 SWTBotSash slaveSashBot = new SWTBotSash(slaveSash, null);
321
322 double masterOriginalSashX = masterSashBot.getPoint().x;
323 // check that the views are already aligned
324 assertEquals("Approx align", masterOriginalSashX, slaveSashBot.getPoint().x, delta);
325 // move sash and wait for alignment
326 drag(masterViewBot, offset);
327 WaitUtils.waitForJobs();
328 SWTBotUtils.delay(SYNC_DELAY);
329 // check results
330 double masterNewSashX = masterSashBot.getPoint().x;
331 assertEquals("Approx align", masterNewSashX, slaveSashBot.getPoint().x, delta);
332 assertEquals(masterOriginalSashX, masterNewSashX - offset, delta);
333 // put things back the way they were
334 drag(masterViewBot, -offset);
335 SWTBotUtils.delay(SYNC_DELAY);
336 }
337
338 /**
339 * Histogram, Callstack and timechart aligned but in different sites
340 */
341 public static class AlignPerspectiveFactory1 implements IPerspectiveFactory {
342
343 /** The Perspective ID */
344 public static final String ID = "org.eclipse.linuxtools.tmf.test.align.1"; //$NON-NLS-1$
345
346 @Override
347 public void createInitialLayout(IPageLayout layout) {
348 if (layout == null) {
349 return;
350 }
351
352 // Editor area
353 layout.setEditorAreaVisible(true);
354
355 // Editor area
356 layout.setEditorAreaVisible(true);
357
358 // Create the top left folder
359 IFolderLayout topLeftFolder = layout.createFolder("topLeftFolder", IPageLayout.LEFT, 0.15f, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
360 topLeftFolder.addView(IPageLayout.ID_PROJECT_EXPLORER);
361
362 // Create the top right folder
363 IFolderLayout topRightFolder = layout.createFolder("topRightFolder", IPageLayout.BOTTOM, EDITOR_AREA_RATIO, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
364 topRightFolder.addView(HistogramView.ID);
365
366 // Create the middle right folder
367 IFolderLayout middleRightFolder = layout.createFolder("middleRightFolder", IPageLayout.BOTTOM, 0.50f, "topRightFolder"); //$NON-NLS-1$
368 middleRightFolder.addView(CallStackView.ID);
369
370 // Create the bottom right folder
371 IFolderLayout bottomRightFolder = layout.createFolder("bottomRightFolder", IPageLayout.BOTTOM, 0.65f, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
372 bottomRightFolder.addView(TimeChartView.ID);
373
374 // Populate menus, etc
375 layout.addPerspectiveShortcut(ID);
376 layout.addNewWizardShortcut(NewTmfProjectWizard.ID);
377 }
378
379 }
380
381 /**
382 * Timechart and Histogram share a site, all views aligned
383 */
384 public static class AlignPerspectiveFactory2 implements IPerspectiveFactory {
385
386 /** The Perspective ID */
387 public static final String ID = "org.eclipse.linuxtools.tmf.test.align.2"; //$NON-NLS-1$
388
389 @Override
390 public void createInitialLayout(IPageLayout layout) {
391 if (layout == null) {
392 return;
393 }
394
395 // Editor area
396 layout.setEditorAreaVisible(true);
397
398 // Editor area
399 layout.setEditorAreaVisible(true);
400
401 // Create the top left folder
402 IFolderLayout topLeftFolder = layout.createFolder("topLeftFolder", IPageLayout.LEFT, 0.15f, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
403 topLeftFolder.addView(IPageLayout.ID_PROJECT_EXPLORER);
404
405 // Create the middle right folder
406 IFolderLayout middleRightFolder = layout.createFolder("middleRightFolder", IPageLayout.BOTTOM, EDITOR_AREA_RATIO, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
407 middleRightFolder.addView(HistogramView.ID);
408 middleRightFolder.addView(TimeChartView.ID);
409
410 // Create the bottom right folder
411 IFolderLayout bottomRightFolder = layout.createFolder("bottomRightFolder", IPageLayout.BOTTOM, 0.65f, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
412 bottomRightFolder.addView(CallStackView.ID);
413
414 // Populate menus, etc
415 layout.addPerspectiveShortcut(ID);
416 layout.addNewWizardShortcut(NewTmfProjectWizard.ID);
417 }
418
419 }
420
421 /**
422 * Histogram and timechart aligned, callstack not aligned
423 */
424 public static class AlignPerspectiveFactory3 implements IPerspectiveFactory {
425
426 /** The Perspective ID */
427 public static final String ID = "org.eclipse.linuxtools.tmf.test.align.3"; //$NON-NLS-1$
428
429 @Override
430 public void createInitialLayout(IPageLayout layout) {
431 if (layout == null) {
432 return;
433 }
434
435 // Editor area
436 layout.setEditorAreaVisible(true);
437
438 // Editor area
439 layout.setEditorAreaVisible(true);
440
441 // Create the top left folder
442 IFolderLayout topLeftFolder = layout.createFolder("topLeftFolder", IPageLayout.LEFT, 0.15f, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
443 topLeftFolder.addView(IPageLayout.ID_PROJECT_EXPLORER);
444
445 IFolderLayout bottomLeftFolder = layout.createFolder("bottomLeftFolder", IPageLayout.BOTTOM, 0.5f, "topLeftFolder"); //$NON-NLS-1$
446 bottomLeftFolder.addView(CallStackView.ID);
447
448 // Create the middle right folder
449 IFolderLayout middleRightFolder = layout.createFolder("middleRightFolder", IPageLayout.BOTTOM, EDITOR_AREA_RATIO, IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
450 middleRightFolder.addView(HistogramView.ID);
451
452 // Create the bottom right folder
453 IFolderLayout bottomRightFolder = layout.createFolder("bottomRightFolder", IPageLayout.BOTTOM, 0.65f, "middleRightFolder"); //$NON-NLS-1$ //$NON-NLS-2$
454 bottomRightFolder.addView(TimeChartView.ID);
455
456 // Populate menus, etc
457 layout.addPerspectiveShortcut(ID);
458 layout.addNewWizardShortcut(NewTmfProjectWizard.ID);
459 }
460
461 }
462
463 }
This page took 0.041834 seconds and 5 git commands to generate.