Commit | Line | Data |
---|---|---|
3ef48ce1 SF |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 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 | ||
10 | package org.eclipse.tracecompass.analysis.timing.core.tests.flamegraph; | |
11 | ||
12 | import static org.junit.Assert.assertEquals; | |
13 | import static org.junit.Assert.assertNotNull; | |
14 | import static org.junit.Assert.assertTrue; | |
15 | ||
16 | import java.util.Collections; | |
17 | import java.util.List; | |
18 | ||
19 | import org.eclipse.core.runtime.IProgressMonitor; | |
20 | import org.eclipse.core.runtime.NullProgressMonitor; | |
21 | import org.eclipse.jdt.annotation.NonNull; | |
22 | import org.eclipse.jdt.annotation.Nullable; | |
23 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
24 | import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.AggregatedCalledFunction; | |
25 | import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.CallGraphAnalysis; | |
b3282dcf | 26 | import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.ThreadNode; |
3ef48ce1 SF |
27 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; |
28 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; | |
29 | import org.eclipse.tracecompass.statesystem.core.StateSystemFactory; | |
30 | import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend; | |
31 | import org.eclipse.tracecompass.statesystem.core.backend.StateHistoryBackendFactory; | |
32 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
33 | import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect; | |
34 | import org.junit.Test; | |
35 | ||
36 | /** | |
37 | * Test the CallGraphAnalysis.This creates a virtual state system in each test | |
38 | * and tests the aggregation tree returned by the CallGraphAnalysis. | |
39 | * | |
40 | * @author Sonia Farrah | |
41 | * | |
42 | */ | |
43 | public class AggregationTreeTest { | |
44 | ||
45 | private static final @NonNull String PROCESS_PATH = "Processes"; | |
46 | private static final @NonNull String THREAD_PATH = "Thread"; | |
47 | private static final @NonNull String CALLSTACK_PATH = "CallStack"; | |
48 | private static final String QUARK_0 = "0"; | |
49 | private static final String QUARK_1 = "1"; | |
50 | private static final String QUARK_2 = "2"; | |
51 | private static final String QUARK_3 = "3"; | |
52 | private static final Integer SMALL_AMOUNT_OF_SEGMENT = 3; | |
53 | private static final int LARGE_AMOUNT_OF_SEGMENTS = 1000; | |
54 | private static final String @NonNull [] CSP = { CALLSTACK_PATH }; | |
55 | private static final String @NonNull [] PP = { PROCESS_PATH }; | |
56 | private static final String @NonNull [] TP = { THREAD_PATH }; | |
57 | ||
58 | /** | |
59 | * This class is used to make the CallGraphAnalysis's method | |
60 | * iterateOverStateSystem() visible to test | |
61 | */ | |
62 | private class CGAnalysis extends CallGraphAnalysis { | |
63 | ||
64 | @Override | |
65 | protected boolean iterateOverStateSystem(@Nullable ITmfStateSystem ss, String[] threadsPattern, String[] processesPattern, String[] callStackPath, IProgressMonitor monitor) { | |
66 | return super.iterateOverStateSystem(ss, threadsPattern, processesPattern, callStackPath, monitor); | |
67 | } | |
68 | ||
69 | @Override | |
70 | public @NonNull Iterable<@NonNull ISegmentAspect> getSegmentAspects() { | |
71 | return Collections.EMPTY_LIST; | |
72 | } | |
73 | ||
74 | } | |
75 | ||
76 | private static ITmfStateSystemBuilder createFixture() { | |
77 | IStateHistoryBackend backend; | |
78 | backend = StateHistoryBackendFactory.createInMemoryBackend("Test", 0L); | |
79 | ITmfStateSystemBuilder fixture = StateSystemFactory.newStateSystem(backend); | |
80 | return fixture; | |
81 | } | |
82 | ||
89e91a67 MK |
83 | private CGAnalysis fCga; |
84 | ||
3ef48ce1 SF |
85 | /** |
86 | * Test an empty state system. | |
87 | */ | |
88 | @Test | |
89 | public void emptyStateSystemTest() { | |
90 | ITmfStateSystemBuilder fixture = createFixture(); | |
91 | fixture.closeHistory(1002); | |
92 | CGAnalysis cga = new CGAnalysis(); | |
93 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); | |
b3282dcf | 94 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
95 | assertNotNull(threads); |
96 | assertEquals("Number of threads found", 0, threads.size()); | |
97 | } | |
98 | ||
99 | /** | |
100 | * Test cascade state system. The call stack's structure used in this test | |
101 | * is shown below: | |
102 | * | |
103 | * <pre> | |
104 | * ________ | |
105 | * ______ | |
106 | * ____ | |
107 | * | |
108 | * </pre> | |
109 | */ | |
110 | @Test | |
111 | public void cascadeTest() { | |
112 | ITmfStateSystemBuilder fixture = createFixture(); | |
113 | // Build the state system | |
114 | long start = 1; | |
115 | long end = 1001; | |
b3282dcf SF |
116 | int threadQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH); |
117 | int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CALLSTACK_PATH); | |
118 | fixture.updateOngoingState(TmfStateValue.newValueLong(100), threadQuark); | |
3ef48ce1 SF |
119 | for (int i = 1; i <= SMALL_AMOUNT_OF_SEGMENT; i++) { |
120 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, Integer.toString(i)); | |
121 | TmfStateValue statev = TmfStateValue.newValueLong(i); | |
122 | fixture.modifyAttribute(start, TmfStateValue.nullValue(), quark); | |
123 | fixture.modifyAttribute(start + i, statev, quark); | |
124 | fixture.modifyAttribute(end - i, TmfStateValue.nullValue(), quark); | |
125 | } | |
126 | ||
127 | fixture.closeHistory(1002); | |
128 | // Execute the CallGraphAnalysis | |
129 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 130 | setCga(cga); |
3ef48ce1 SF |
131 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
132 | @NonNull | |
b3282dcf | 133 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
134 | // Test the threads generated by the analysis |
135 | assertNotNull(threads); | |
136 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
137 | assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size()); | |
b3282dcf SF |
138 | assertEquals("Thread id", 100, threads.get(0).getId()); |
139 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
140 | Object[] children = threads.get(0).getChildren().toArray(); |
141 | AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0]; | |
142 | assertEquals("Children number: First function", 1, firstFunction.getChildren().size()); | |
143 | Object @NonNull [] firstFunctionChildren = firstFunction.getChildren().toArray(); | |
144 | AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
145 | assertEquals("Children number: Second function", 1, secondFunction.getChildren().size()); | |
146 | Object @NonNull [] secondFunctionChildren = secondFunction.getChildren().toArray(); | |
147 | AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0]; | |
148 | assertEquals("Children number: Third function", 0, thirdFunction.getChildren().size()); | |
149 | // Test links | |
150 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol()); | |
151 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(thirdFunction.getParent()).getSymbol(), secondFunction.getSymbol()); | |
152 | // Test duration | |
153 | assertEquals("Test first function's duration", 998, firstFunction.getDuration()); | |
154 | assertEquals("Test second function's duration", 996, secondFunction.getDuration()); | |
155 | assertEquals("Test third function's duration", 994, thirdFunction.getDuration()); | |
156 | // Test self time | |
157 | assertEquals("Test first function's self time", 2, firstFunction.getSelfTime()); | |
158 | assertEquals("Test second function's self time", 2, secondFunction.getSelfTime()); | |
159 | assertEquals("Test third function's self time", 994, thirdFunction.getSelfTime()); | |
160 | // Test depth | |
161 | assertEquals("Test first function's depth", 0, firstFunction.getDepth()); | |
162 | assertEquals("Test second function's depth", 1, secondFunction.getDepth()); | |
163 | assertEquals("Test third function's depth", 2, thirdFunction.getDepth()); | |
164 | // Test number of calls | |
165 | assertEquals("Test first function's nombre of calls", 1, firstFunction.getNbCalls()); | |
166 | assertEquals("Test second function's nombre of calls", 1, secondFunction.getNbCalls()); | |
167 | assertEquals("Test third function's nombre of calls", 1, thirdFunction.getNbCalls()); | |
168 | } | |
169 | ||
170 | /** | |
171 | * Test a state system with a two calls for the same function. The call | |
172 | * stack's structure used in this test is shown below: | |
173 | * | |
174 | * <pre> | |
175 | * Aggregated tree | |
176 | * ___ main___ ___ main___ | |
177 | * _1_ _1_ => _1_ | |
178 | * _1_ _1_ | |
179 | * </pre> | |
180 | */ | |
181 | @Test | |
182 | public void treeTest() { | |
183 | ITmfStateSystemBuilder fixture = createFixture(); | |
184 | // Build the state system | |
b3282dcf SF |
185 | int threadQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH); |
186 | int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CALLSTACK_PATH); | |
187 | fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark); | |
3ef48ce1 SF |
188 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0); |
189 | TmfStateValue statev = TmfStateValue.newValueLong(0); | |
190 | fixture.modifyAttribute(0, statev, quark); | |
191 | fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark); | |
192 | ||
193 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1); | |
194 | statev = TmfStateValue.newValueLong(1); | |
195 | fixture.modifyAttribute(0, statev, quark); | |
196 | fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark); | |
197 | fixture.modifyAttribute(60, statev, quark); | |
198 | fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark); | |
199 | ||
200 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2); | |
201 | fixture.modifyAttribute(0, statev, quark); | |
202 | fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark); | |
203 | fixture.closeHistory(102); | |
204 | ||
205 | // Execute the CallGraphAnalysis | |
206 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 207 | setCga(cga); |
3ef48ce1 | 208 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
b3282dcf | 209 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
210 | // Test the threads generated by the analysis |
211 | assertNotNull(threads); | |
212 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
b3282dcf SF |
213 | assertEquals("Thread id", -1, threads.get(0).getId()); |
214 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
215 | Object[] children = threads.get(0).getChildren().toArray(); |
216 | AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0]; | |
217 | assertEquals("Children number: First function", 1, firstFunction.getChildren().size()); | |
218 | Object[] firstFunctionChildren = firstFunction.getChildren().toArray(); | |
219 | AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
220 | assertEquals("Children number: Second function", 1, secondFunction.getChildren().size()); | |
221 | Object[] secondFunctionChildren = secondFunction.getChildren().toArray(); | |
222 | AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0]; | |
223 | assertEquals("Children number: Third function", 0, thirdFunction.getChildren().size()); | |
224 | // Test links | |
225 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol()); | |
226 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(thirdFunction.getParent()).getSymbol(), secondFunction.getSymbol()); | |
227 | // Test duration | |
228 | assertEquals("Test first function's duration", 100, firstFunction.getDuration()); | |
229 | assertEquals("Test second function's duration", 80, secondFunction.getDuration()); | |
230 | assertEquals("Test third function's duration", 30, thirdFunction.getDuration()); | |
231 | // Test self time | |
232 | assertEquals("Test first function's self time", 20, firstFunction.getSelfTime()); | |
233 | assertEquals("Test second function's self time", 50, secondFunction.getSelfTime()); | |
234 | assertEquals("Test third function's self time", 30, thirdFunction.getSelfTime()); | |
235 | // Test depth | |
236 | assertEquals("Test first function's depth", 0, firstFunction.getDepth()); | |
237 | assertEquals("Test second function's depth", 1, secondFunction.getDepth()); | |
238 | assertEquals("Test third function's depth", 2, thirdFunction.getDepth()); | |
239 | // Test number of calls | |
240 | assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls()); | |
241 | assertEquals("Test second function's number of calls", 2, secondFunction.getNbCalls()); | |
242 | assertEquals("Test third function's number of calls", 1, thirdFunction.getNbCalls()); | |
243 | } | |
244 | ||
245 | /** | |
246 | * Test the callees merge. The call stack's structure used in this test is | |
247 | * shown below: | |
248 | * | |
249 | * <pre> | |
250 | * Aggregated tree | |
251 | * ___ main___ ___ main___ | |
252 | * _1_ _1_ => _1_ | |
253 | * _2_ _3_ _2_ _3_ | |
254 | * </pre> | |
255 | */ | |
256 | @Test | |
257 | public void mergeFirstLevelCalleesTest() { | |
258 | ITmfStateSystemBuilder fixture = createFixture(); | |
259 | // Build the state system | |
b3282dcf SF |
260 | int threadQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, "123"); |
261 | int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CALLSTACK_PATH); | |
262 | fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark); | |
3ef48ce1 SF |
263 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0); |
264 | TmfStateValue statev = TmfStateValue.newValueLong(0); | |
265 | fixture.modifyAttribute(0, statev, quark); | |
266 | fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark); | |
267 | ||
268 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1); | |
269 | statev = TmfStateValue.newValueLong(1); | |
270 | fixture.modifyAttribute(0, statev, quark); | |
271 | fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark); | |
272 | fixture.modifyAttribute(60, statev, quark); | |
273 | fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark); | |
274 | ||
275 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2); | |
276 | statev = TmfStateValue.newValueLong(2); | |
277 | fixture.modifyAttribute(0, statev, quark); | |
278 | fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark); | |
279 | statev = TmfStateValue.newValueLong(3); | |
280 | fixture.modifyAttribute(60, statev, quark); | |
281 | fixture.modifyAttribute(80, TmfStateValue.nullValue(), quark); | |
282 | fixture.closeHistory(102); | |
283 | ||
284 | // Execute the CallGraphAnalysis | |
285 | CGAnalysis cga = new CGAnalysis(); | |
b3282dcf SF |
286 | String @NonNull [] tp = { "123" }; |
287 | assertTrue(cga.iterateOverStateSystem(fixture, tp, PP, CSP, new NullProgressMonitor())); | |
89e91a67 | 288 | setCga(cga); |
b3282dcf | 289 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
290 | // Test the threads generated by the analysis |
291 | assertNotNull(threads); | |
292 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
b3282dcf SF |
293 | assertEquals("Thread id", 123, threads.get(0).getId()); |
294 | assertEquals("Thread name", "123", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
295 | assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size()); |
296 | Object[] children = threads.get(0).getChildren().toArray(); | |
297 | ||
298 | AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0]; | |
299 | assertEquals("Children number: First function", 1, firstFunction.getChildren().size()); | |
300 | Object[] firstFunctionChildren = firstFunction.getChildren().toArray(); | |
301 | AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
302 | assertEquals("Children number: Second function", 2, secondFunction.getChildren().size()); | |
303 | Object[] secondFunctionChildren = secondFunction.getChildren().toArray(); | |
304 | AggregatedCalledFunction leaf1 = (AggregatedCalledFunction) secondFunctionChildren[0]; | |
305 | AggregatedCalledFunction leaf2 = (AggregatedCalledFunction) secondFunctionChildren[1]; | |
306 | assertEquals("Children number: First leaf function", 0, leaf1.getChildren().size()); | |
307 | assertEquals("Children number: Second leaf function", 0, leaf2.getChildren().size()); | |
308 | // Test links | |
309 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol()); | |
310 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(leaf1.getParent()).getSymbol(), secondFunction.getSymbol()); | |
311 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(leaf2.getParent()).getSymbol(), secondFunction.getSymbol()); | |
312 | // Test duration | |
313 | assertEquals("Test first function's duration", 100, firstFunction.getDuration()); | |
314 | assertEquals("Test second function's duration", 80, secondFunction.getDuration()); | |
315 | assertEquals("Test first leaf's duration", 30, leaf1.getDuration()); | |
316 | assertEquals("Test second leaf's duration", 20, leaf2.getDuration()); | |
317 | // Test self time | |
318 | assertEquals("Test first function's self time", 20, firstFunction.getSelfTime()); | |
319 | assertEquals("Test second function's self time", 30, secondFunction.getSelfTime()); | |
320 | assertEquals("Test first leaf's self time", 30, leaf1.getSelfTime()); | |
321 | assertEquals("Test second leaf's self time", 20, leaf2.getSelfTime()); | |
322 | // Test depth | |
323 | assertEquals("Test first function's depth", 0, firstFunction.getDepth()); | |
324 | assertEquals("Test second function's depth", 1, secondFunction.getDepth()); | |
325 | assertEquals("Test first leaf's depth", 2, leaf1.getDepth()); | |
326 | assertEquals("Test second leaf's depth", 2, leaf2.getDepth()); | |
327 | // Test number of calls | |
328 | assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls()); | |
329 | assertEquals("Test second function's number of calls", 2, secondFunction.getNbCalls()); | |
330 | assertEquals("Test first leaf's number of calls", 1, leaf1.getNbCalls()); | |
331 | assertEquals("Test second leaf's number of calls", 1, leaf2.getNbCalls()); | |
332 | } | |
333 | ||
334 | /** | |
335 | * Build a call stack example.This call stack's structure is shown below : | |
336 | * | |
337 | * <pre> | |
338 | * ___ main____ | |
339 | * ___1___ _1_ | |
340 | * _2_ _3_ _2_ | |
341 | * _4_ _4_ | |
342 | * </pre> | |
343 | */ | |
344 | private static void buildCallStack(ITmfStateSystemBuilder fixture) { | |
345 | int parentQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH); | |
346 | // Create the first function | |
347 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0); | |
348 | TmfStateValue statev = TmfStateValue.newValueLong(0); | |
349 | fixture.modifyAttribute(0, statev, quark); | |
350 | fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark); | |
351 | // Create the first level functions | |
352 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1); | |
353 | statev = TmfStateValue.newValueLong(1); | |
354 | fixture.modifyAttribute(0, statev, quark); | |
355 | fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark); | |
356 | fixture.modifyAttribute(60, statev, quark); | |
357 | fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark); | |
358 | // Create the third function | |
359 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2); | |
360 | statev = TmfStateValue.newValueLong(2); | |
361 | fixture.modifyAttribute(0, statev, quark); | |
362 | fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark); | |
363 | ||
364 | statev = TmfStateValue.newValueLong(3); | |
365 | fixture.modifyAttribute(20, statev, quark); | |
366 | fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark); | |
367 | ||
368 | statev = TmfStateValue.newValueLong(2); | |
369 | fixture.modifyAttribute(60, statev, quark); | |
370 | fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark); | |
371 | ||
372 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_3); | |
373 | statev = TmfStateValue.newValueLong(4); | |
374 | fixture.modifyAttribute(0, statev, quark); | |
375 | fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark); | |
376 | ||
377 | fixture.modifyAttribute(60, statev, quark); | |
378 | fixture.modifyAttribute(80, TmfStateValue.nullValue(), quark); | |
379 | fixture.closeHistory(102); | |
380 | } | |
381 | ||
382 | /** | |
383 | * Test the merge of The callees children. The call stack's structure used | |
384 | * in this test is shown below: | |
385 | * | |
386 | * <pre> | |
387 | * Aggregated tree | |
388 | * ___ main____ ____ main____ | |
389 | * ___1___ _1_ _1_ | |
390 | * _2_ _3_ _2_ => _2_ _3_ | |
391 | * _4_ _4_ _4_ | |
392 | * </pre> | |
393 | */ | |
394 | @Test | |
395 | public void mergeSecondLevelCalleesTest() { | |
396 | ITmfStateSystemBuilder fixture = createFixture(); | |
397 | buildCallStack(fixture); | |
398 | // Execute the CallGraphAnalysis | |
399 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 400 | setCga(cga); |
3ef48ce1 | 401 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
b3282dcf | 402 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
403 | // Test the threads generated by the analysis |
404 | assertNotNull(threads); | |
405 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
b3282dcf SF |
406 | assertEquals("Thread id", -1, threads.get(0).getId()); |
407 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
408 | assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size()); |
409 | Object[] children = threads.get(0).getChildren().toArray(); | |
410 | AggregatedCalledFunction main = (AggregatedCalledFunction) children[0]; | |
411 | assertEquals("Children number: main", 1, main.getChildren().size()); | |
412 | Object[] mainChildren = main.getChildren().toArray(); | |
413 | AggregatedCalledFunction function1 = (AggregatedCalledFunction) mainChildren[0]; | |
414 | assertEquals("Children number: first function", 2, function1.getChildren().size()); | |
415 | Object[] firstFunctionChildren = function1.getChildren().toArray(); | |
416 | AggregatedCalledFunction function2 = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
417 | AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[1]; | |
418 | assertEquals("Children number: First child", 1, function2.getChildren().size()); | |
419 | assertEquals("Children number: Second child", 0, function3.getChildren().size()); | |
420 | Object[] firstChildCallee = function2.getChildren().toArray(); | |
421 | AggregatedCalledFunction function4 = (AggregatedCalledFunction) firstChildCallee[0]; | |
422 | assertEquals("Children number: leaf function", 0, function4.getChildren().size()); | |
423 | // Test links | |
424 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function1.getParent()).getSymbol(), main.getSymbol()); | |
425 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function2.getParent()).getSymbol(), function1.getSymbol()); | |
426 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), function1.getSymbol()); | |
427 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function4.getParent()).getSymbol(), function2.getSymbol()); | |
428 | // Test duration | |
429 | assertEquals("Test main's duration", 100, main.getDuration()); | |
430 | assertEquals("Test first function's duration", 90, function1.getDuration()); | |
431 | assertEquals("Test first child's duration", 40, function2.getDuration()); | |
432 | assertEquals("Test second child's duration", 10, function3.getDuration()); | |
433 | assertEquals("Test leaf's duration", 30, function4.getDuration()); | |
434 | // Test self time | |
435 | assertEquals("Test main's self time", 10, main.getSelfTime()); | |
436 | assertEquals("Test first function's self time", 40, function1.getSelfTime()); | |
437 | assertEquals("Test first child's self time", 10, | |
438 | function2.getSelfTime()); | |
439 | assertEquals("Test second child's self time", 10, function3.getSelfTime()); | |
440 | assertEquals("Test leaf's self time", 30, function4.getSelfTime()); | |
441 | // Test depth | |
442 | assertEquals("Test main function's depth", 0, main.getDepth()); | |
443 | assertEquals("Test first function's depth", 1, function1.getDepth()); | |
444 | assertEquals("Test first child's depth", 2, function2.getDepth()); | |
445 | assertEquals("Test second child's depth", 2, function3.getDepth()); | |
446 | assertEquals("Test leaf's depth", 3, function4.getDepth()); | |
447 | // Test number of calls | |
448 | assertEquals("Test main's number of calls", 1, main.getNbCalls()); | |
449 | assertEquals("Test first function's number of calls", 2, function1.getNbCalls()); | |
450 | assertEquals("Test first child's number of calls", 2, function2.getNbCalls()); | |
451 | assertEquals("Test second child's number of calls", 1, function3.getNbCalls()); | |
452 | assertEquals("Test leaf's number of calls", 2, function4.getNbCalls()); | |
453 | } | |
454 | ||
455 | /** | |
456 | * Test state system with a large amount of segments. All segments have the | |
457 | * same length. The call stack's structure used in this test is shown below: | |
458 | * | |
459 | * <pre> | |
460 | * _____ | |
461 | * _____ | |
462 | * _____ | |
463 | * ..... | |
464 | * </pre> | |
465 | */ | |
466 | @Test | |
467 | public void largeTest() { | |
468 | ITmfStateSystemBuilder fixture = createFixture(); | |
469 | int parentQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH); | |
470 | for (int i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) { | |
471 | TmfStateValue statev = TmfStateValue.newValueLong(i); | |
472 | fixture.pushAttribute(0, statev, parentQuark); | |
473 | } | |
474 | for (int i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) { | |
475 | fixture.popAttribute(10, parentQuark); | |
476 | } | |
477 | fixture.closeHistory(11); | |
478 | // Execute the callGraphAnalysis | |
479 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 480 | setCga(cga); |
3ef48ce1 | 481 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
b3282dcf | 482 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
483 | // Test the threads generated by the analysis |
484 | assertNotNull(threads); | |
b3282dcf SF |
485 | assertEquals("Thread id", -1, threads.get(0).getId()); |
486 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
487 | Object[] children = threads.get(0).getChildren().toArray(); |
488 | AggregatedCalledFunction parent = (AggregatedCalledFunction) children[0]; | |
489 | for (int i = 1; i < LARGE_AMOUNT_OF_SEGMENTS; i++) { | |
490 | children = parent.getChildren().toArray(); | |
491 | AggregatedCalledFunction child = (AggregatedCalledFunction) children[0]; | |
492 | assertEquals("Test parenthood", NonNullUtils.checkNotNull(child.getParent()).getSymbol(), NonNullUtils.checkNotNull(parent.getSymbol())); | |
493 | parent = child; | |
494 | } | |
495 | } | |
496 | ||
497 | /** | |
498 | * Test mutliRoots state system.This tests if a root function called twice | |
499 | * will be merged into one function or not. The call stack's structure used | |
500 | * in this test is shown below: | |
501 | * | |
502 | * <pre> | |
503 | * Aggregated tree | |
504 | * _1_ _1_ => _1_ | |
505 | * _2_ _3_ _2_ _3_ | |
506 | * </pre> | |
507 | */ | |
508 | @Test | |
509 | public void multiFunctionRootsTest() { | |
510 | ITmfStateSystemBuilder fixture = createFixture(); | |
511 | int parentQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH); | |
512 | // Create the first root function | |
513 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0); | |
514 | TmfStateValue statev = TmfStateValue.newValueLong(1); | |
515 | fixture.modifyAttribute(0, statev, quark); | |
516 | fixture.modifyAttribute(20, TmfStateValue.nullValue(), quark); | |
517 | // Create the second root function | |
518 | fixture.modifyAttribute(30, statev, quark); | |
519 | fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark); | |
520 | // Create the first root function's callee | |
521 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1); | |
522 | statev = TmfStateValue.newValueLong(2); | |
523 | fixture.modifyAttribute(0, statev, quark); | |
524 | fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark); | |
525 | // Create the second root function's callee | |
526 | statev = TmfStateValue.newValueLong(3); | |
527 | fixture.modifyAttribute(30, statev, quark); | |
528 | fixture.modifyAttribute(40, TmfStateValue.nullValue(), quark); | |
529 | fixture.closeHistory(51); | |
530 | ||
531 | // Execute the callGraphAnalysis | |
532 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 533 | setCga(cga); |
3ef48ce1 | 534 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
b3282dcf | 535 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
536 | // Test the threads generated by the analysis |
537 | assertNotNull(threads); | |
538 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
b3282dcf SF |
539 | assertEquals("Thread id", -1, threads.get(0).getId()); |
540 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
541 | assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size()); |
542 | Object[] children = threads.get(0).getChildren().toArray(); | |
543 | AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0]; | |
544 | assertEquals("Children number: First function", 2, firstFunction.getChildren().size()); | |
545 | Object[] firstFunctionChildren = firstFunction.getChildren().toArray(); | |
546 | AggregatedCalledFunction function2 = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
547 | AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[1]; | |
548 | assertEquals("Children number: Second function", 0, function2.getChildren().size()); | |
549 | assertEquals("Children number: Third function", 0, function3.getChildren().size()); | |
550 | // Test links | |
551 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function2.getParent()).getSymbol(), firstFunction.getSymbol()); | |
552 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), firstFunction.getSymbol()); | |
553 | // Test duration | |
554 | assertEquals("Test first function's duration", 40, firstFunction.getDuration()); | |
555 | assertEquals("Test second function's duration", 10, function2.getDuration()); | |
556 | assertEquals("Test third function's duration", 10, function3.getDuration()); | |
557 | // Test self time | |
558 | assertEquals("Test first function's self time", 20, firstFunction.getSelfTime()); | |
559 | assertEquals("Test second function's self time", 10, function2.getSelfTime()); | |
560 | assertEquals("Test third function's self time", 10, function2.getSelfTime()); | |
561 | // Test depth | |
562 | assertEquals("Test first function's depth", 0, firstFunction.getDepth()); | |
563 | assertEquals("Test second function's depth", 1, function2.getDepth()); | |
564 | assertEquals("Test third function's depth", 1, function3.getDepth()); | |
565 | // Test number of calls | |
566 | assertEquals("Test first function's number of calls", 2, firstFunction.getNbCalls()); | |
567 | assertEquals("Test second function's number of calls", 1, function2.getNbCalls()); | |
568 | assertEquals("Test third function's number of calls", 1, function3.getNbCalls()); | |
569 | ||
570 | } | |
571 | ||
572 | /** | |
573 | * Test mutliRoots state system. The call stack's structure used in this | |
574 | * test is shown below: | |
575 | * | |
576 | * <pre> | |
577 | * Aggregated tree | |
578 | * _0_ _1_ => _0_ _1_ | |
579 | * _2_ _2_ _2_ _2_ | |
580 | * | |
581 | * </pre> | |
582 | */ | |
583 | @Test | |
584 | public void multiFunctionRootsSecondTest() { | |
585 | ITmfStateSystemBuilder fixture = createFixture(); | |
586 | int parentQuark = fixture.getQuarkAbsoluteAndAdd(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH); | |
587 | // Create the first root function | |
588 | int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0); | |
589 | TmfStateValue statev = TmfStateValue.newValueLong(0); | |
590 | fixture.modifyAttribute(0, statev, quark); | |
591 | fixture.modifyAttribute(20, TmfStateValue.nullValue(), quark); | |
592 | // Create the second root function | |
593 | statev = TmfStateValue.newValueLong(1); | |
594 | fixture.modifyAttribute(30, statev, quark); | |
595 | fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark); | |
596 | // Create the first root function's callee | |
597 | quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1); | |
598 | statev = TmfStateValue.newValueLong(2); | |
599 | fixture.modifyAttribute(0, statev, quark); | |
600 | fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark); | |
601 | // Create the second root function's callee | |
602 | fixture.modifyAttribute(30, statev, quark); | |
603 | fixture.modifyAttribute(40, TmfStateValue.nullValue(), quark); | |
604 | fixture.closeHistory(51); | |
605 | ||
606 | // Execute the callGraphAnalysis | |
607 | CGAnalysis cga = new CGAnalysis(); | |
89e91a67 | 608 | setCga(cga); |
3ef48ce1 | 609 | assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor())); |
b3282dcf | 610 | List<ThreadNode> threads = cga.getThreadNodes(); |
3ef48ce1 SF |
611 | // Test the threads generated by the analysis |
612 | assertNotNull(threads); | |
613 | assertEquals("Number of thread nodes Found", 1, threads.size()); | |
b3282dcf SF |
614 | assertEquals("Thread id", -1, threads.get(0).getId()); |
615 | assertEquals("Thread name", "Thread", threads.get(0).getSymbol()); | |
3ef48ce1 SF |
616 | assertEquals("Number of root functions ", 2, threads.get(0).getChildren().size()); |
617 | Object[] children = threads.get(0).getChildren().toArray(); | |
618 | AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0]; | |
619 | AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) children[1]; | |
620 | ||
621 | assertEquals("Children number: First function", 1, firstFunction.getChildren().size()); | |
622 | assertEquals("Children number: Second function", 1, secondFunction.getChildren().size()); | |
623 | Object[] firstFunctionChildren = firstFunction.getChildren().toArray(); | |
624 | Object[] secondFunctionChildren = secondFunction.getChildren().toArray(); | |
625 | AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[0]; | |
626 | AggregatedCalledFunction function4 = (AggregatedCalledFunction) secondFunctionChildren[0]; | |
627 | ||
628 | assertEquals("Children number: third function", 0, function3.getChildren().size()); | |
629 | assertEquals("Children number: fourth function", 0, function4.getChildren().size()); | |
630 | // Test links | |
631 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), firstFunction.getSymbol()); | |
632 | assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function4.getParent()).getSymbol(), secondFunction.getSymbol()); | |
633 | // Test duration | |
634 | assertEquals("Test second function's duration", 20, firstFunction.getDuration()); | |
635 | assertEquals("Test second function's duration", 20, secondFunction.getDuration()); | |
636 | assertEquals("Test first leaf's duration", 10, function3.getDuration()); | |
637 | assertEquals("Test second leaf's duration", 10, function4.getDuration()); | |
638 | // Test self time | |
639 | assertEquals("Test first function's self time", 10, firstFunction.getSelfTime()); | |
640 | assertEquals("Test second function's duration", 10, secondFunction.getSelfTime()); | |
641 | assertEquals("Test second function's self time", 10, function3.getSelfTime()); | |
642 | assertEquals("Test second function's self time", 10, function4.getSelfTime()); | |
643 | // Test depth | |
644 | assertEquals("Test first function's depth", 0, firstFunction.getDepth()); | |
645 | assertEquals("Test first function's depth", 0, secondFunction.getDepth()); | |
646 | assertEquals("Test third function's depth", 1, function3.getDepth()); | |
647 | assertEquals("Test third function's depth", 1, function4.getDepth()); | |
648 | // Test number of calls | |
649 | assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls()); | |
650 | assertEquals("Test first function's number of calls", 1, secondFunction.getNbCalls()); | |
651 | assertEquals("Test third function's number of calls", 1, function3.getNbCalls()); | |
652 | assertEquals("Test third function's number of calls", 1, function4.getNbCalls()); | |
653 | ||
654 | } | |
89e91a67 MK |
655 | |
656 | /** | |
657 | * Gets the call graph analysis | |
658 | * @return the call graph analysis | |
659 | */ | |
660 | protected CGAnalysis getCga() { | |
661 | return fCga; | |
662 | } | |
663 | ||
664 | private void setCga(CGAnalysis cga) { | |
665 | fCga = cga; | |
666 | } | |
3ef48ce1 | 667 | } |