Commit | Line | Data |
---|---|---|
efc403bb AM |
1 | /******************************************************************************* |
2 | * Copyright (c) 2012 Ericsson | |
3 | * Copyright (c) 2010, 2011 École Polytechnique de Montréal | |
4 | * Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com> | |
5 | * | |
6 | * All rights reserved. This program and the accompanying materials are | |
7 | * made available under the terms of the Eclipse Public License v1.0 which | |
8 | * accompanies this distribution, and is available at | |
9 | * http://www.eclipse.org/legal/epl-v10.html | |
10 | * | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.lttng2.kernel.core.tests.stateprovider; | |
14 | ||
15 | import static org.junit.Assert.*; | |
16 | ||
17 | import java.io.File; | |
18 | import java.io.FileNotFoundException; | |
19 | import java.io.IOException; | |
20 | import java.io.PrintWriter; | |
21 | import java.util.List; | |
22 | ||
1e4bb526 | 23 | import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; |
efc403bb AM |
24 | import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval; |
25 | import org.eclipse.linuxtools.tmf.core.statesystem.AttributeNotFoundException; | |
26 | import org.eclipse.linuxtools.tmf.core.statesystem.StateHistorySystem; | |
27 | import org.eclipse.linuxtools.tmf.core.statesystem.TimeRangeException; | |
28 | import org.eclipse.linuxtools.tmf.core.statesystem.backend.historytree.HistoryTreeBackend; | |
29 | import org.eclipse.linuxtools.tmf.core.statesystem.helpers.HistoryBuilder; | |
30 | import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateChangeInput; | |
31 | import org.eclipse.linuxtools.tmf.core.statesystem.helpers.IStateHistoryBackend; | |
32 | import org.eclipse.linuxtools.tmf.core.statevalue.StateValueTypeException; | |
dc0f7bfe | 33 | import org.eclipse.linuxtools.internal.lttng2.kernel.core.stateprovider.CtfKernelStateInput; |
6b78e55b | 34 | import org.eclipse.linuxtools.lttng2.kernel.core.trace.Attributes; |
efc403bb AM |
35 | import org.junit.*; |
36 | ||
37 | /** | |
38 | * Unit tests for the StateHistorySystem, which uses a full (non-partial) | |
39 | * history and the non-threaded CTF kernel handler. | |
40 | * | |
41 | * @author alexmont | |
42 | * | |
43 | */ | |
44 | @SuppressWarnings("nls") | |
45 | public class StateSystemFullHistoryTest { | |
46 | ||
ebd67b34 AM |
47 | static File stateFile; |
48 | static File stateFileBenchmark; | |
efc403bb | 49 | |
ebd67b34 AM |
50 | static HistoryBuilder builder; |
51 | static IStateChangeInput input; | |
52 | static IStateHistoryBackend hp; | |
53 | static StateHistorySystem shs; | |
efc403bb | 54 | |
cc2292bd AM |
55 | /* Offset in the trace + start time of the trace */ |
56 | private final static long interestingTimestamp1 = 18670067372290L + 1331649577946812237L; | |
2359ecca | 57 | |
efc403bb AM |
58 | protected static String getTestFileName() { |
59 | return "/tmp/statefile.ht"; //$NON-NLS-1$ | |
60 | } | |
61 | ||
62 | @BeforeClass | |
63 | public static void initialize() { | |
64 | stateFile = new File(getTestFileName()); | |
65 | stateFileBenchmark = new File(getTestFileName() + ".benchmark"); //$NON-NLS-1$ | |
66 | try { | |
dc0f7bfe | 67 | input = new CtfKernelStateInput(CtfTestFiles.getTestTrace()); |
efc403bb AM |
68 | hp = new HistoryTreeBackend(stateFile, input.getStartTime()); |
69 | builder = new HistoryBuilder(input, hp); | |
70 | } catch (Exception e) { | |
71 | e.printStackTrace(); | |
72 | } | |
73 | builder.run(); | |
74 | shs = (StateHistorySystem) builder.getSS(); | |
fee997a5 | 75 | builder.close(); /* Waits for the construction to finish */ |
efc403bb AM |
76 | } |
77 | ||
78 | @AfterClass | |
79 | public static void cleanup() { | |
ebd67b34 AM |
80 | boolean ret1, ret2; |
81 | ret1 = stateFile.delete(); | |
82 | ret2 = stateFileBenchmark.delete(); | |
83 | if ( !(ret1 && ret2) ) { | |
6b78e55b AM |
84 | System.err.println("Error cleaning up during unit testing, " + //$NON-NLS-1$ |
85 | "you might have leftovers state history files in /tmp"); //$NON-NLS-1$ | |
ebd67b34 | 86 | } |
efc403bb AM |
87 | } |
88 | ||
89 | /** | |
90 | * Rebuild independently so we can benchmark it. Too bad JUnit doesn't allow | |
91 | * us to @Test the @BeforeClass... | |
1e4bb526 AM |
92 | * |
93 | * @throws IOException | |
94 | * @throws TmfTraceException | |
efc403bb AM |
95 | */ |
96 | @Test | |
1e4bb526 | 97 | public void testBuild() throws IOException, TmfTraceException { |
efc403bb AM |
98 | HistoryBuilder zebuilder; |
99 | IStateChangeInput zeinput; | |
1e4bb526 | 100 | IStateHistoryBackend zehp = null; |
efc403bb | 101 | |
1e4bb526 AM |
102 | zeinput = new CtfKernelStateInput(CtfTestFiles.getTestTrace()); |
103 | zehp = new HistoryTreeBackend(stateFileBenchmark, zeinput.getStartTime()); | |
104 | zebuilder = new HistoryBuilder(zeinput, zehp); | |
105 | zebuilder.run(); | |
106 | zebuilder.close(); | |
107 | ||
108 | assertEquals(CtfTestFiles.startTime, zehp.getStartTime()); | |
109 | assertEquals(CtfTestFiles.endTime, zehp.getEndTime()); | |
efc403bb AM |
110 | } |
111 | ||
112 | @Test | |
1e4bb526 | 113 | public void testOpenExistingStateFile() throws IOException { |
efc403bb AM |
114 | IStateHistoryBackend hp2 = null; |
115 | StateHistorySystem shs2 = null; | |
1e4bb526 AM |
116 | |
117 | /* 'newStateFile' should have already been created */ | |
118 | hp2 = new HistoryTreeBackend(stateFile); | |
119 | shs2 = new StateHistorySystem(hp2, false); | |
120 | ||
121 | assertNotNull(shs2); | |
122 | assertEquals(CtfTestFiles.startTime, hp2.getStartTime()); | |
123 | assertEquals(CtfTestFiles.endTime, hp2.getEndTime()); | |
efc403bb AM |
124 | } |
125 | ||
126 | @Test | |
127 | public void testFullQuery1() throws StateValueTypeException, | |
128 | AttributeNotFoundException, TimeRangeException { | |
129 | ||
dad01d27 | 130 | List<ITmfStateInterval> list; |
efc403bb | 131 | ITmfStateInterval interval; |
ae54340d | 132 | int quark, quark2, valueInt; |
efc403bb AM |
133 | String valueStr; |
134 | ||
dad01d27 | 135 | list = shs.loadStateAtTime(interestingTimestamp1); |
efc403bb | 136 | |
6b78e55b | 137 | quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dad01d27 | 138 | interval = list.get(quark); |
efc403bb | 139 | valueInt = interval.getStateValue().unboxInt(); |
2359ecca | 140 | assertEquals(1397, valueInt); |
efc403bb | 141 | |
6b78e55b | 142 | quark = shs.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
dad01d27 | 143 | interval = list.get(quark); |
efc403bb | 144 | valueStr = interval.getStateValue().unboxStr(); |
2359ecca | 145 | assertEquals("gdbus", valueStr); |
efc403bb | 146 | |
ae54340d | 147 | /* Query a stack attribute, has to be done in two passes */ |
6b78e55b | 148 | quark = shs.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_MODE_STACK); |
ab9bc51b | 149 | interval = list.get(quark); |
ae54340d AM |
150 | valueInt = interval.getStateValue().unboxInt(); /* The stack depth */ |
151 | quark2 = shs.getQuarkRelative(quark, Integer.toString(valueInt)); | |
ab9bc51b | 152 | interval = list.get(quark2); |
ae54340d AM |
153 | valueStr = interval.getStateValue().unboxStr(); |
154 | assertTrue(valueStr.equals("sys_poll")); | |
efc403bb AM |
155 | } |
156 | ||
157 | @Test | |
158 | public void testFullQuery2() { | |
159 | // | |
160 | } | |
161 | ||
162 | @Test | |
163 | public void testFullQuery3() { | |
164 | // | |
165 | } | |
166 | ||
167 | @Test | |
168 | public void testSingleQuery1() throws AttributeNotFoundException, | |
169 | TimeRangeException, StateValueTypeException { | |
170 | ||
2359ecca | 171 | long timestamp = interestingTimestamp1; |
efc403bb AM |
172 | int quark; |
173 | ITmfStateInterval interval; | |
174 | String valueStr; | |
175 | ||
6b78e55b | 176 | quark = shs.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
efc403bb AM |
177 | interval = shs.querySingleState(timestamp, quark); |
178 | valueStr = interval.getStateValue().unboxStr(); | |
2359ecca | 179 | assertEquals("gdbus", valueStr); |
efc403bb AM |
180 | } |
181 | ||
182 | @Test | |
183 | public void testSingleQuery2() { | |
184 | // | |
185 | } | |
186 | ||
187 | @Test | |
188 | public void testSingleQuery3() { | |
189 | // | |
190 | } | |
191 | ||
ab9bc51b AM |
192 | /** |
193 | * Test a range query (with no resolution parameter, so all intervals) | |
194 | */ | |
efc403bb AM |
195 | @Test |
196 | public void testRangeQuery1() throws AttributeNotFoundException, | |
197 | TimeRangeException, StateValueTypeException { | |
198 | ||
2359ecca | 199 | long time1 = interestingTimestamp1; |
dc0f7bfe | 200 | long time2 = time1 + 1L * CtfTestFiles.NANOSECS_PER_SEC; |
efc403bb AM |
201 | int quark; |
202 | List<ITmfStateInterval> intervals; | |
203 | ||
6b78e55b | 204 | quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
efc403bb | 205 | intervals = shs.queryHistoryRange(quark, time1, time2); |
2359ecca AM |
206 | assertEquals(487, intervals.size()); /* Number of context switches! */ |
207 | assertEquals(1685, intervals.get(100).getStateValue().unboxInt()); | |
cc2292bd | 208 | assertEquals(1331668248427681372L, intervals.get(205).getEndTime()); |
efc403bb AM |
209 | } |
210 | ||
1d3d1293 AM |
211 | /** |
212 | * Range query, but with a t2 far off the end of the trace. | |
213 | * The result should still be valid. | |
214 | */ | |
215 | @Test | |
216 | public void testRangeQuery2() throws TimeRangeException, | |
217 | AttributeNotFoundException { | |
218 | ||
219 | List<ITmfStateInterval> intervals; | |
220 | ||
6b78e55b | 221 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.IRQ_STACK); |
1d3d1293 AM |
222 | long ts1 = shs.getHistoryBackend().getStartTime(); /* start of the trace */ |
223 | long ts2 = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid, but ignored */ | |
224 | ||
225 | intervals = shs.queryHistoryRange(quark, ts1, ts2); | |
226 | ||
227 | /* Nb of IRQs on CPU 0 during the whole trace */ | |
228 | assertEquals(1653, intervals.size()); | |
229 | } | |
230 | ||
ab9bc51b AM |
231 | /** |
232 | * Test a range query with a resolution | |
233 | */ | |
234 | @Test | |
1d3d1293 | 235 | public void testRangeQuery3() throws AttributeNotFoundException, |
ab9bc51b AM |
236 | TimeRangeException, StateValueTypeException { |
237 | ||
238 | long time1 = interestingTimestamp1; | |
dc0f7bfe | 239 | long time2 = time1 + 1L * CtfTestFiles.NANOSECS_PER_SEC; |
ab9bc51b AM |
240 | long resolution = 1000000; /* One query every millisecond */ |
241 | int quark; | |
242 | List<ITmfStateInterval> intervals; | |
243 | ||
6b78e55b | 244 | quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
ab9bc51b AM |
245 | intervals = shs.queryHistoryRange(quark, time1, time2, resolution); |
246 | assertEquals(129, intervals.size()); /* Number of context switches! */ | |
247 | assertEquals(1452, intervals.get(50).getStateValue().unboxInt()); | |
cc2292bd | 248 | assertEquals(1331668248784789238L, intervals.get(100).getEndTime()); |
ab9bc51b AM |
249 | } |
250 | ||
efc403bb AM |
251 | /** |
252 | * Ask for a time range outside of the trace's range | |
253 | * | |
254 | * @throws TimeRangeException | |
255 | */ | |
256 | @Test(expected = TimeRangeException.class) | |
257 | public void testFullQueryInvalidTime1() throws TimeRangeException { | |
dc0f7bfe | 258 | long ts = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; |
2359ecca | 259 | shs.loadStateAtTime(ts); |
efc403bb AM |
260 | |
261 | } | |
262 | ||
263 | @Test(expected = TimeRangeException.class) | |
264 | public void testFullQueryInvalidTime2() throws TimeRangeException { | |
dc0f7bfe | 265 | long ts = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; |
2359ecca | 266 | shs.loadStateAtTime(ts); |
efc403bb AM |
267 | |
268 | } | |
269 | ||
270 | @Test(expected = TimeRangeException.class) | |
271 | public void testSingleQueryInvalidTime1() | |
272 | throws AttributeNotFoundException, TimeRangeException { | |
273 | ||
6b78e55b | 274 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dc0f7bfe | 275 | long ts = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; |
2359ecca | 276 | shs.querySingleState(ts, quark); |
efc403bb AM |
277 | } |
278 | ||
279 | @Test(expected = TimeRangeException.class) | |
280 | public void testSingleQueryInvalidTime2() | |
281 | throws AttributeNotFoundException, TimeRangeException { | |
282 | ||
6b78e55b | 283 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dc0f7bfe | 284 | long ts = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; |
2359ecca | 285 | shs.querySingleState(ts, quark); |
efc403bb AM |
286 | } |
287 | ||
288 | @Test(expected = TimeRangeException.class) | |
289 | public void testRangeQueryInvalidTime1() throws AttributeNotFoundException, | |
290 | TimeRangeException { | |
291 | ||
6b78e55b | 292 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dc0f7bfe AM |
293 | long ts1 = CtfTestFiles.startTime - 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ |
294 | long ts2 = CtfTestFiles.startTime + 1L * CtfTestFiles.NANOSECS_PER_SEC; /* valid */ | |
efc403bb | 295 | |
2359ecca | 296 | shs.queryHistoryRange(quark, ts1, ts2); |
efc403bb AM |
297 | } |
298 | ||
299 | @Test(expected = TimeRangeException.class) | |
300 | public void testRangeQueryInvalidTime2() throws TimeRangeException, | |
301 | AttributeNotFoundException { | |
302 | ||
6b78e55b | 303 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dc0f7bfe AM |
304 | long ts1 = CtfTestFiles.startTime - 1L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ |
305 | long ts2 = CtfTestFiles.startTime + 20L * CtfTestFiles.NANOSECS_PER_SEC; /* invalid */ | |
efc403bb | 306 | |
2359ecca | 307 | shs.queryHistoryRange(quark, ts1, ts2); |
efc403bb AM |
308 | } |
309 | ||
310 | /** | |
311 | * Ask for a non-existing attribute | |
312 | * | |
313 | * @throws AttributeNotFoundException | |
314 | */ | |
315 | @Test(expected = AttributeNotFoundException.class) | |
316 | public void testQueryInvalidAttribute() throws AttributeNotFoundException { | |
317 | ||
318 | shs.getQuarkAbsolute("There", "is", "no", "cow", "level"); | |
319 | } | |
320 | ||
321 | /** | |
322 | * Query but with the wrong State Value type | |
323 | * | |
324 | * @throws StateValueTypeException | |
325 | * @throws AttributeNotFoundException | |
326 | * @throws TimeRangeException | |
327 | */ | |
328 | @Test(expected = StateValueTypeException.class) | |
329 | public void testQueryInvalidValuetype1() throws StateValueTypeException, | |
330 | AttributeNotFoundException, TimeRangeException { | |
dad01d27 | 331 | List<ITmfStateInterval> list; |
efc403bb AM |
332 | ITmfStateInterval interval; |
333 | int quark; | |
334 | ||
dad01d27 | 335 | list = shs.loadStateAtTime(interestingTimestamp1); |
6b78e55b | 336 | quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
dad01d27 | 337 | interval = list.get(quark); |
2359ecca AM |
338 | |
339 | /* This is supposed to be an int value */ | |
340 | interval.getStateValue().unboxStr(); | |
efc403bb AM |
341 | } |
342 | ||
343 | @Test(expected = StateValueTypeException.class) | |
344 | public void testQueryInvalidValuetype2() throws StateValueTypeException, | |
345 | AttributeNotFoundException, TimeRangeException { | |
dad01d27 | 346 | List<ITmfStateInterval> list; |
efc403bb AM |
347 | ITmfStateInterval interval; |
348 | int quark; | |
349 | ||
dad01d27 | 350 | list = shs.loadStateAtTime(interestingTimestamp1); |
6b78e55b | 351 | quark = shs.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME); |
dad01d27 | 352 | interval = list.get(quark); |
2359ecca AM |
353 | |
354 | /* This is supposed to be a String value */ | |
355 | interval.getStateValue().unboxInt(); | |
efc403bb AM |
356 | } |
357 | ||
358 | @Test | |
359 | public void testFullAttributeName() throws AttributeNotFoundException { | |
6b78e55b | 360 | int quark = shs.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD); |
efc403bb | 361 | String name = shs.getFullAttributePath(quark); |
2359ecca | 362 | assertEquals(name, "CPUs/0/Current_thread"); |
efc403bb AM |
363 | } |
364 | ||
6abc2d88 AM |
365 | @Test |
366 | public void testGetQuarks_begin() { | |
6b78e55b | 367 | List<Integer> list = shs.getQuarks("*", "1577", Attributes.EXEC_NAME); |
6abc2d88 AM |
368 | |
369 | assertEquals(1, list.size()); | |
6b78e55b | 370 | assertEquals(Integer.valueOf(398), list.get(0)); |
6abc2d88 AM |
371 | } |
372 | ||
373 | @Test | |
374 | public void testGetQuarks_middle() { | |
6b78e55b | 375 | List<Integer> list = shs.getQuarks(Attributes.THREADS, "*", Attributes.EXEC_NAME); |
6abc2d88 | 376 | |
6b78e55b AM |
377 | assertEquals(Integer.valueOf(18), list.get(4)); |
378 | assertEquals(Integer.valueOf(54), list.get(10)); | |
379 | assertEquals(Integer.valueOf(64), list.get(12)); | |
6abc2d88 AM |
380 | } |
381 | ||
382 | @Test | |
383 | public void testGetQuarks_end() { | |
6b78e55b | 384 | List<Integer> list = shs.getQuarks(Attributes.THREADS, "1577", "*"); |
6abc2d88 AM |
385 | |
386 | assertEquals(3, list.size()); | |
6b78e55b | 387 | assertEquals(Integer.valueOf(398), list.get(1)); |
6abc2d88 AM |
388 | } |
389 | ||
efc403bb AM |
390 | @Test |
391 | public void testDebugPrinting() throws FileNotFoundException { | |
6f04204e AM |
392 | PrintWriter pw = new PrintWriter(new File("/dev/null")); |
393 | shs.debugPrint(pw); | |
394 | pw.close(); | |
efc403bb AM |
395 | } |
396 | } |