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
.analysis
.os
.linux
.ui
.swtbot
.tests
.latency
;
15 import static org
.junit
.Assert
.assertEquals
;
16 import static org
.junit
.Assert
.assertNotNull
;
17 import static org
.junit
.Assert
.assertNull
;
18 import static org
.junit
.Assert
.assertTrue
;
19 import static org
.junit
.Assert
.fail
;
21 import java
.io
.BufferedReader
;
22 import java
.io
.ByteArrayOutputStream
;
24 import java
.io
.FileReader
;
25 import java
.io
.IOException
;
26 import java
.lang
.reflect
.InvocationTargetException
;
27 import java
.lang
.reflect
.Method
;
28 import java
.util
.ArrayList
;
29 import java
.util
.Arrays
;
30 import java
.util
.List
;
31 import java
.util
.Random
;
32 import java
.util
.stream
.Collectors
;
34 import org
.apache
.log4j
.ConsoleAppender
;
35 import org
.apache
.log4j
.Logger
;
36 import org
.apache
.log4j
.SimpleLayout
;
37 import org
.eclipse
.core
.runtime
.FileLocator
;
38 import org
.eclipse
.jdt
.annotation
.NonNull
;
39 import org
.eclipse
.swtbot
.eclipse
.finder
.SWTWorkbenchBot
;
40 import org
.eclipse
.swtbot
.eclipse
.finder
.widgets
.SWTBotView
;
41 import org
.eclipse
.swtbot
.swt
.finder
.SWTBot
;
42 import org
.eclipse
.swtbot
.swt
.finder
.finders
.UIThreadRunnable
;
43 import org
.eclipse
.swtbot
.swt
.finder
.junit
.SWTBotJunit4ClassRunner
;
44 import org
.eclipse
.swtbot
.swt
.finder
.results
.BoolResult
;
45 import org
.eclipse
.swtbot
.swt
.finder
.results
.Result
;
46 import org
.eclipse
.swtbot
.swt
.finder
.utils
.SWTBotPreferences
;
47 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotMenu
;
48 import org
.eclipse
.swtbot
.swt
.finder
.widgets
.SWTBotTable
;
49 import org
.eclipse
.tracecompass
.analysis
.timing
.ui
.views
.segmentstore
.table
.AbstractSegmentStoreTableView
;
50 import org
.eclipse
.tracecompass
.analysis
.timing
.ui
.views
.segmentstore
.table
.AbstractSegmentStoreTableViewer
;
51 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.ui
.views
.latency
.SystemCallLatencyView
;
52 import org
.eclipse
.tracecompass
.segmentstore
.core
.BasicSegment
;
53 import org
.eclipse
.tracecompass
.testtraces
.ctf
.CtfTestTrace
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
55 import org
.eclipse
.tracecompass
.tmf
.ui
.dialog
.TmfFileDialogFactory
;
56 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.ConditionHelpers
;
57 import org
.eclipse
.tracecompass
.tmf
.ui
.swtbot
.tests
.shared
.SWTBotUtils
;
58 import org
.eclipse
.tracecompass
.tmf
.ui
.tests
.shared
.WaitUtils
;
59 import org
.eclipse
.ui
.IViewPart
;
60 import org
.eclipse
.ui
.IViewReference
;
61 import org
.eclipse
.ui
.PlatformUI
;
62 import org
.eclipse
.ui
.WorkbenchException
;
63 import org
.junit
.After
;
64 import org
.junit
.Before
;
65 import org
.junit
.BeforeClass
;
66 import org
.junit
.Ignore
;
67 import org
.junit
.Test
;
68 import org
.junit
.runner
.RunWith
;
71 * Tests of the latency table
73 * @author Matthew Khouzam
75 @RunWith(SWTBotJunit4ClassRunner
.class)
76 public class SystemCallLatencyTableAnalysisTest
{
78 private static final String TRACE_TYPE
= "org.eclipse.linuxtools.lttng2.kernel.tracetype";
79 private static final String PROJECT_NAME
= "test";
80 private static final String VIEW_ID
= SystemCallLatencyView
.ID
;
81 private static final String TRACING_PERSPECTIVE_ID
= "org.eclipse.linuxtools.tmf.ui.perspective";
83 /** The Log4j logger instance. */
84 private static final Logger fLogger
= Logger
.getRootLogger();
85 private SystemCallLatencyView fLatencyView
;
86 private AbstractSegmentStoreTableViewer fTable
;
92 public static void beforeClass() {
94 SWTBotUtils
.initialize();
95 Thread
.currentThread().setName("SWTBotTest");
96 /* set up for swtbot */
97 SWTBotPreferences
.TIMEOUT
= 20000; /* 20 second timeout */
98 SWTBotPreferences
.KEYBOARD_LAYOUT
= "EN_US";
99 fLogger
.removeAllAppenders();
100 fLogger
.addAppender(new ConsoleAppender(new SimpleLayout(), ConsoleAppender
.SYSTEM_OUT
));
101 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
102 final List
<SWTBotView
> openViews
= bot
.views();
103 for (SWTBotView view
: openViews
) {
104 if (view
.getTitle().equals("Welcome")) {
106 bot
.waitUntil(ConditionHelpers
.ViewIsClosed(view
));
109 /* Switch perspectives */
110 switchTracingPerspective();
111 /* Finish waiting for eclipse to load */
112 WaitUtils
.waitForJobs();
117 * Opens a latency table
120 public void createTable() {
124 SWTBotUtils
.openView(VIEW_ID
);
125 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
126 SWTBotView viewBot
= bot
.viewById(VIEW_ID
);
127 final IViewReference viewReference
= viewBot
.getViewReference();
128 IViewPart viewPart
= UIThreadRunnable
.syncExec(new Result
<IViewPart
>() {
130 public IViewPart
run() {
131 return viewReference
.getView(true);
134 assertNotNull(viewPart
);
135 if (!(viewPart
instanceof SystemCallLatencyView
)) {
136 fail("Could not instanciate view");
138 fLatencyView
= (SystemCallLatencyView
) viewPart
;
139 fTable
= fLatencyView
.getSegmentStoreViewer();
140 assertNotNull(fTable
);
147 public void closeTable() {
148 final SWTWorkbenchBot swtWorkbenchBot
= new SWTWorkbenchBot();
149 SWTBotView viewBot
= swtWorkbenchBot
.viewById(VIEW_ID
);
153 private static void switchTracingPerspective() {
154 final Exception retE
[] = new Exception
[1];
155 if (!UIThreadRunnable
.syncExec(new BoolResult() {
157 public Boolean
run() {
159 PlatformUI
.getWorkbench().showPerspective(TRACING_PERSPECTIVE_ID
,
160 PlatformUI
.getWorkbench().getActiveWorkbenchWindow());
161 } catch (WorkbenchException e
) {
168 fail(retE
[0].getMessage());
177 public void climbTest() {
178 List
<@NonNull BasicSegment
> fixture
= new ArrayList
<>();
179 for (int i
= 0; i
< 100; i
++) {
180 fixture
.add(new BasicSegment(i
, 2 * i
));
183 assertNotNull(fTable
);
184 fTable
.updateModel(fixture
);
185 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
186 SWTBot bot
= new SWTBot();
187 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
188 tableBot
.header("Duration").click();
189 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
190 tableBot
.header("Duration").click();
191 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "99", 0, 2));
198 public void decrementingTest() {
199 List
<@NonNull BasicSegment
> fixture
= new ArrayList
<>();
200 for (int i
= 100; i
>= 0; i
--) {
201 fixture
.add(new BasicSegment(i
, 2 * i
));
203 assertNotNull(fTable
);
204 fTable
.updateModel(fixture
);
205 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
206 SWTBot bot
= new SWTBot();
207 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "100", 0, 2));
208 tableBot
.header("Duration").click();
209 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
210 tableBot
.header("Duration").click();
211 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "100", 0, 2));
218 public void smallTest() {
219 List
<@NonNull BasicSegment
> fixture
= new ArrayList
<>();
220 for (int i
= 1; i
>= 0; i
--) {
221 fixture
.add(new BasicSegment(i
, 2 * i
));
223 assertNotNull(fTable
);
224 fTable
.updateModel(fixture
);
225 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
226 SWTBot bot
= new SWTBot();
227 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "1", 0, 2));
228 tableBot
.header("Duration").click();
229 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
230 tableBot
.header("Duration").click();
231 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "1", 0, 2));
238 public void largeTest() {
239 final int size
= 1000000;
240 BasicSegment
[] fixture
= new BasicSegment
[size
];
241 for (int i
= 0; i
< size
; i
++) {
242 fixture
[i
] = (new BasicSegment(i
, 2 * i
));
244 assertNotNull(fTable
);
245 fTable
.updateModel(fixture
);
246 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
247 SWTBot bot
= new SWTBot();
248 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
249 tableBot
.header("Duration").click();
250 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
251 tableBot
.header("Duration").click();
252 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "999,999", 0, 2));
259 public void noiseTest() {
260 Random rnd
= new Random();
262 final int size
= 1000000;
263 BasicSegment
[] fixture
= new BasicSegment
[size
];
264 for (int i
= 0; i
< size
; i
++) {
265 int start
= Math
.abs(rnd
.nextInt(100000000));
266 int end
= start
+ Math
.abs(rnd
.nextInt(1000000));
267 fixture
[i
] = (new BasicSegment(start
, end
));
269 assertNotNull(fTable
);
270 fTable
.updateModel(fixture
);
271 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
272 SWTBot bot
= new SWTBot();
273 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "894,633", 0, 2));
274 tableBot
.header("Duration").click();
275 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
276 tableBot
.header("Duration").click();
277 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "999,999", 0, 2));
281 * Test gaussian noise
284 public void gaussianNoiseTest() {
285 Random rnd
= new Random();
287 List
<@NonNull BasicSegment
> fixture
= new ArrayList
<>();
288 for (int i
= 1; i
<= 1000000; i
++) {
289 int start
= Math
.abs(rnd
.nextInt(100000000));
290 final int delta
= Math
.abs(rnd
.nextInt(1000));
291 int end
= start
+ delta
* delta
;
292 fixture
.add(new BasicSegment(start
, end
));
294 assertNotNull(fTable
);
295 fTable
.updateModel(fixture
);
296 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
297 SWTBot bot
= new SWTBot();
298 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "400,689", 0, 2));
299 tableBot
.header("Duration").click();
300 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "0", 0, 2));
301 tableBot
.header("Duration").click();
302 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "998,001", 0, 2));
306 * Test creating a tsv
308 * @throws NoSuchMethodException
309 * Error creating the tsv
310 * @throws IOException
311 * no such file or the file is locked.
315 public void testWriteToTsv() throws NoSuchMethodException
, IOException
{
317 List
<@NonNull BasicSegment
> fixture
= new ArrayList
<>();
318 for (int i
= 1; i
<= 20; i
++) {
321 int end
= start
+ delta
* delta
;
322 fixture
.add(new BasicSegment(start
, end
));
324 assertNotNull(fTable
);
325 fTable
.updateModel(fixture
);
326 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
327 SWTBot bot
= new SWTBot();
328 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "1", 0, 2));
329 SWTWorkbenchBot swtWorkbenchBot
= new SWTWorkbenchBot();
330 SWTBotView viewBot
= swtWorkbenchBot
.viewById(VIEW_ID
);
331 List
<String
> actionResult
= Arrays
.asList(testToTsv(viewBot
));
332 String absolutePath
= TmfTraceManager
.getTemporaryDirPath() + File
.separator
+ "syscallLatencyTest.testWriteToTsv.tsv";
333 TmfFileDialogFactory
.setOverrideFiles(absolutePath
);
334 SWTBotMenu menuBot
= viewBot
.viewMenu().menu("Export to TSV");
336 assertTrue(menuBot
.isEnabled());
337 assertTrue(menuBot
.isVisible());
340 try (BufferedReader br
= new BufferedReader(new FileReader(absolutePath
))) {
341 List
<String
> lines
= br
.lines().collect(Collectors
.toList());
342 assertEquals("Both reads", actionResult
, lines
);
345 new File(absolutePath
).delete();
350 private String
[] testToTsv(SWTBotView view
) throws NoSuchMethodException
{
351 ByteArrayOutputStream os
= new ByteArrayOutputStream();
353 Class
<@NonNull AbstractSegmentStoreTableView
> clazz
= AbstractSegmentStoreTableView
.class;
354 Method method
= clazz
.getDeclaredMethod("exportToTsv", java
.io
.OutputStream
.class);
355 method
.setAccessible(true);
356 final Exception
[] except
= new Exception
[1];
357 UIThreadRunnable
.syncExec(() -> {
359 method
.invoke(fLatencyView
, os
);
360 } catch (IllegalAccessException
| IllegalArgumentException
| InvocationTargetException e
) {
364 assertNull(except
[0]);
365 @SuppressWarnings("null")
366 String
[] lines
= String
.valueOf(os
).split(System
.getProperty("line.separator"));
367 assertNotNull(lines
);
368 assertEquals("number of lines", 21, lines
.length
);
369 assertEquals("header", "Start Time\tEnd Time\tDuration", lines
[0]);
370 // not a straight up string compare due to time zones. Kathmandu and
371 // Eucla have 15 minute time zones.
372 assertTrue("line 1", lines
[1].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s001\\t\\d\\d:\\d\\d:00.000 000 002\\t1"));
373 assertTrue("line 2", lines
[2].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s002\\t\\d\\d:\\d\\d:00.000 000 006\\t4"));
374 assertTrue("line 3", lines
[3].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s003\\t\\d\\d:\\d\\d:00.000 000 012\\t9"));
375 assertTrue("line 4", lines
[4].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s004\\t\\d\\d:\\d\\d:00.000 000 020\\t16"));
376 assertTrue("line 5", lines
[5].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s005\\t\\d\\d:\\d\\d:00.000 000 030\\t25"));
377 assertTrue("line 6", lines
[6].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s006\\t\\d\\d:\\d\\d:00.000 000 042\\t36"));
378 assertTrue("line 7", lines
[7].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s007\\t\\d\\d:\\d\\d:00.000 000 056\\t49"));
379 assertTrue("line 8", lines
[8].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s008\\t\\d\\d:\\d\\d:00.000 000 072\\t64"));
380 assertTrue("line 9", lines
[9].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s009\\t\\d\\d:\\d\\d:00.000 000 090\\t81"));
381 assertTrue("line 10", lines
[10].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s010\\t\\d\\d:\\d\\d:00.000 000 110\\t100"));
382 assertTrue("line 11", lines
[11].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s011\\t\\d\\d:\\d\\d:00.000 000 132\\t121"));
383 assertTrue("line 12", lines
[12].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s012\\t\\d\\d:\\d\\d:00.000 000 156\\t144"));
384 assertTrue("line 13", lines
[13].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s013\\t\\d\\d:\\d\\d:00.000 000 182\\t169"));
385 assertTrue("line 14", lines
[14].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s014\\t\\d\\d:\\d\\d:00.000 000 210\\t196"));
386 assertTrue("line 15", lines
[15].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s015\\t\\d\\d:\\d\\d:00.000 000 240\\t225"));
387 assertTrue("line 16", lines
[16].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s016\\t\\d\\d:\\d\\d:00.000 000 272\\t256"));
388 assertTrue("line 17", lines
[17].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s017\\t\\d\\d:\\d\\d:00.000 000 306\\t289"));
389 assertTrue("line 18", lines
[18].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s018\\t\\d\\d:\\d\\d:00.000 000 342\\t324"));
390 assertTrue("line 19", lines
[19].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s019\\t\\d\\d:\\d\\d:00.000 000 380\\t361"));
391 assertTrue("line 20", lines
[20].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s020\\t\\d\\d:\\d\\d:00.000 000 420\\t400"));
396 * Test with an actual trace, this is more of an integration test than a
397 * unit test. This test is a slow one too. If some analyses are not well
398 * configured, this test will also generates null pointer exceptions. These
399 * are will be logged.
401 * @throws IOException
405 public void testWithTrace() throws IOException
{
407 tracePath
= FileLocator
.toFileURL(CtfTestTrace
.ARM_64_BIT_HEADER
.getTraceURL()).getPath();
408 SWTWorkbenchBot bot
= new SWTWorkbenchBot();
409 SWTBotView view
= bot
.viewById(VIEW_ID
);
411 bot
.waitUntil(ConditionHelpers
.ViewIsClosed(view
));
412 SWTBotUtils
.createProject(PROJECT_NAME
);
413 SWTBotUtils
.openTrace(PROJECT_NAME
, tracePath
, TRACE_TYPE
);
414 WaitUtils
.waitForJobs();
416 WaitUtils
.waitForJobs();
417 SWTBotTable tableBot
= new SWTBotTable(fTable
.getTableViewer().getTable());
418 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "24,100", 0, 2));
419 tableBot
.header("Duration").click();
420 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "1,000", 0, 2));
421 tableBot
.header("Duration").click();
422 bot
.waitUntil(ConditionHelpers
.isTableCellFilled(tableBot
, "5,904,091,700", 0, 2));
423 bot
.closeAllEditors();
424 SWTBotUtils
.deleteProject(PROJECT_NAME
, bot
);