blob: 60e699674dd723b792fdd5976629c2bc66d645d2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.tracecompass.incubator.callstack.core.tests.callgraph.instrumented;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.incubator.callstack.core.base.ICallStackElement;
import org.eclipse.tracecompass.incubator.callstack.core.callgraph.CallGraph;
import org.eclipse.tracecompass.incubator.callstack.core.callgraph.ICallGraphProvider;
import org.eclipse.tracecompass.incubator.callstack.core.tests.Activator;
import org.eclipse.tracecompass.incubator.callstack.core.tests.flamechart.CallStackTestBase;
import org.eclipse.tracecompass.incubator.callstack.core.tests.stubs.CallGraphAnalysisStub;
import org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.callgraph.AggregatedCalledFunction;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder;
import org.eclipse.tracecompass.statesystem.core.StateSystemFactory;
import org.eclipse.tracecompass.statesystem.core.backend.IStateHistoryBackend;
import org.eclipse.tracecompass.statesystem.core.backend.StateHistoryBackendFactory;
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub;
import org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStubNs;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableList;
/**
* Test the CallGraphAnalysis. This creates a virtual state system in each test
* and tests the aggregation tree returned by the CallGraphAnalysis.
*
* @author Sonia Farrah
*
*/
public class AggregationTreeTest {
private static final String CALLSTACK_FILE = "testfiles/traces/callstack.xml";
private ITmfTrace fTrace;
private static final String QUARK_0 = "0";
private static final String QUARK_1 = "1";
private static final String QUARK_2 = "2";
private static final String QUARK_3 = "3";
private static final Integer SMALL_AMOUNT_OF_SEGMENT = 3;
private static final int LARGE_AMOUNT_OF_SEGMENTS = 1000;
private static @NonNull ITmfStateSystemBuilder createFixture() {
IStateHistoryBackend backend;
backend = StateHistoryBackendFactory.createInMemoryBackend("Test", 0L);
ITmfStateSystemBuilder fixture = StateSystemFactory.newStateSystem(backend);
return fixture;
}
private CallGraphAnalysisStub fCga;
private List<ICallStackElement> getLeafElements(ICallStackElement group) {
if (group.isLeaf()) {
return Collections.singletonList(group);
}
List<ICallStackElement> leafGroups = new ArrayList<>();
group.getChildrenElements().forEach(g -> leafGroups.addAll(getLeafElements(g)));
return leafGroups;
}
private @NonNull List<ICallStackElement> getLeafElements(ICallGraphProvider cga) {
Collection<ICallStackElement> elements = cga.getCallGraph().getElements();
List<ICallStackElement> leafGroups = new ArrayList<>();
for (ICallStackElement group : elements) {
leafGroups.addAll(getLeafElements(group));
}
return leafGroups;
}
/**
* Open a flamegraph
*/
@Before
public void before() {
TmfXmlTraceStub trace = new TmfXmlTraceStubNs();
IPath filePath = Activator.getAbsoluteFilePath(CALLSTACK_FILE);
IStatus status = trace.validate(null, filePath.toOSString());
if (!status.isOK()) {
fail(status.getException().getMessage());
}
try {
trace.initTrace(null, filePath.toOSString(), TmfEvent.class);
} catch (TmfTraceException e) {
fail(e.getMessage());
}
fTrace = trace;
TmfTraceOpenedSignal signal = new TmfTraceOpenedSignal(this, trace, null);
trace.traceOpened(signal);
TmfTraceManager.getInstance().traceOpened(signal);
}
/**
* Dispose the callgraph analysis that has been set
*/
@After
public void disposeCga() {
CallGraphAnalysisStub cga = fCga;
if (cga != null) {
cga.dispose();
}
ITmfTrace trace = fTrace;
if (trace != null) {
TmfTraceManager.getInstance().traceClosed(new TmfTraceClosedSignal(this, trace));
trace.dispose();
}
}
/**
* Test an empty state system.
*/
@Test
public void emptyStateSystemTest() {
ITmfStateSystemBuilder fixture = createFixture();
fixture.closeHistory(1002);
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
Collection<ICallStackElement> threads = getLeafElements(cga);
assertNotNull(threads);
assertEquals("Number of threads found", 0, threads.size());
}
/**
* Test cascade state system. The call stack's structure used in this test
* is shown below:
*
* <pre>
* ________
* ______
* ____
*
* </pre>
*/
@Test
public void cascadeTest() {
ITmfStateSystemBuilder fixture = createFixture();
// Build the state system
long start = 1;
long end = 1001;
int threadQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH);
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CallGraphAnalysisStub.CALLSTACK_PATH);
fixture.updateOngoingState(TmfStateValue.newValueLong(100), threadQuark);
for (int i = 1; i <= SMALL_AMOUNT_OF_SEGMENT; i++) {
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, Integer.toString(i));
long statev = i;
fixture.modifyAttribute(start, (Object) null, quark);
fixture.modifyAttribute(start + i, statev, quark);
fixture.modifyAttribute(end - i, (Object) null, quark);
}
fixture.closeHistory(1002);
// Execute the CallGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
ICallStackElement group = threads.get(0);
CallGraph cg = cga.getCallGraph();
assertNotNull(group);
assertEquals("Number of root functions ", 1, cg.getCallingContextTree(group).size());
assertEquals("Thread id", "Thread", group.getName());
Object[] children = cg.getCallingContextTree(group).toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getCallees().size());
Object @NonNull [] firstFunctionChildren = firstFunction.getCallees().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 1, secondFunction.getCallees().size());
Object @NonNull [] secondFunctionChildren = secondFunction.getCallees().toArray();
AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: Third function", 0, thirdFunction.getCallees().size());
// Test duration
assertEquals("Test first function's duration", 998, firstFunction.getDuration());
assertEquals("Test second function's duration", 996, secondFunction.getDuration());
assertEquals("Test third function's duration", 994, thirdFunction.getDuration());
// Test self time
assertEquals("Test first function's self time", 2, firstFunction.getSelfTime());
assertEquals("Test second function's self time", 2, secondFunction.getSelfTime());
assertEquals("Test third function's self time", 994, thirdFunction.getSelfTime());
// Test number of calls
assertEquals("Test first function's nombre of calls", 1, firstFunction.getNbCalls());
assertEquals("Test second function's nombre of calls", 1, secondFunction.getNbCalls());
assertEquals("Test third function's nombre of calls", 1, thirdFunction.getNbCalls());
}
/**
* Test a state system with a two calls for the same function. The call
* stack's structure used in this test is shown below:
*
* <pre>
* Aggregated tree
* ___ main___ ___ main___
* _1_ _1_ => _1_
* _1_ _1_
* </pre>
*/
@Test
public void treeTest() {
ITmfStateSystemBuilder fixture = createFixture();
// Build the state system
int threadQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH);
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CallGraphAnalysisStub.CALLSTACK_PATH);
fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark);
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
long statev = 0L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, (Object) null, quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = 1L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, (Object) null, quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, (Object) null, quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(30, (Object) null, quark);
fixture.closeHistory(102);
// Execute the CallGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
@NonNull
List<ICallStackElement> threads = getLeafElements(cga);
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread name", "Thread", threads.get(0).getName());
Object[] children = cga.getCallGraph().getCallingContextTree(threads.get(0)).toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getCallees().size());
Object[] firstFunctionChildren = firstFunction.getCallees().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 1, secondFunction.getCallees().size());
Object[] secondFunctionChildren = secondFunction.getCallees().toArray();
AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: Third function", 0, thirdFunction.getCallees().size());
// Test duration
assertEquals("Test first function's duration", 100, firstFunction.getDuration());
assertEquals("Test second function's duration", 80, secondFunction.getDuration());
assertEquals("Test third function's duration", 30, thirdFunction.getDuration());
// Test self time
assertEquals("Test first function's self time", 20, firstFunction.getSelfTime());
assertEquals("Test second function's self time", 50, secondFunction.getSelfTime());
assertEquals("Test third function's self time", 30, thirdFunction.getSelfTime());
// Test number of calls
assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls());
assertEquals("Test second function's number of calls", 2, secondFunction.getNbCalls());
assertEquals("Test third function's number of calls", 1, thirdFunction.getNbCalls());
}
/**
* Test the callees merge. The call stack's structure used in this test is
* shown below:
*
* <pre>
* Aggregated tree
* ___ main___ ___ main___
* _1_ _1_ => _1_
* _2_ _3_ _2_ _3_
* </pre>
*/
@Test
public void mergeFirstLevelCalleesTest() {
ITmfStateSystemBuilder fixture = createFixture();
// Build the state system
int threadQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, "123");
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CallGraphAnalysisStub.CALLSTACK_PATH);
fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark);
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
Long statev = 0L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, (Object) null, quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = 1L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, (Object) null, quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, (Object) null, quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
statev = 2L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(30, (Object) null, quark);
statev = 3L;
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(80, (Object) null, quark);
fixture.closeHistory(102);
// Execute the CallGraphAnalysis
String @NonNull [] tp = { "*" };
String @NonNull [] pp = { CallGraphAnalysisStub.PROCESS_PATH };
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture, ImmutableList.of(pp, tp));
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
CallGraph cg = cga.getCallGraph();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread name", "123", threads.get(0).getName());
assertEquals("Number of root functions ", 1, cg.getCallingContextTree(threads.get(0)).size());
Object[] children = cg.getCallingContextTree(threads.get(0)).toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getCallees().size());
Object[] firstFunctionChildren = firstFunction.getCallees().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 2, secondFunction.getCallees().size());
AggregatedCalledFunction leaf1 = (AggregatedCalledFunction) secondFunction.getCallees().stream()
.filter(acs -> CallStackTestBase.getCallSiteSymbol(acs).resolve(Collections.emptySet()).equals("0x2"))
.findAny().get();
AggregatedCalledFunction leaf2 = (AggregatedCalledFunction) secondFunction.getCallees().stream()
.filter(acs -> CallStackTestBase.getCallSiteSymbol(acs).resolve(Collections.emptySet()).equals("0x3"))
.findAny().get();
assertEquals("Children number: First leaf function", 0, leaf1.getCallees().size());
assertEquals("Children number: Second leaf function", 0, leaf2.getCallees().size());
// Test duration
assertEquals("Test first function's duration", 100, firstFunction.getDuration());
assertEquals("Test second function's duration", 80, secondFunction.getDuration());
assertEquals("Test first leaf's duration", 30, leaf1.getDuration());
assertEquals("Test second leaf's duration", 20, leaf2.getDuration());
// Test self time
assertEquals("Test first function's self time", 20, firstFunction.getSelfTime());
assertEquals("Test second function's self time", 30, secondFunction.getSelfTime());
assertEquals("Test first leaf's self time", 30, leaf1.getSelfTime());
assertEquals("Test second leaf's self time", 20, leaf2.getSelfTime());
// Test number of calls
assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls());
assertEquals("Test second function's number of calls", 2, secondFunction.getNbCalls());
assertEquals("Test first leaf's number of calls", 1, leaf1.getNbCalls());
assertEquals("Test second leaf's number of calls", 1, leaf2.getNbCalls());
}
/**
* Build a call stack example.This call stack's structure is shown below :
*
* <pre>
* ___ main____
* ___1___ _1_
* _2_ _3_ _2_
* _4_ _4_
* </pre>
*/
private static void buildCallStack(ITmfStateSystemBuilder fixture) {
int parentQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH, CallGraphAnalysisStub.CALLSTACK_PATH);
// Create the first function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
Long statev = 0L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, (Object) null, quark);
// Create the first level functions
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = 1L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, (Object) null, quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(100, (Object) null, quark);
// Create the third function
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
statev = 2L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, (Object) null, quark);
statev = 3L;
fixture.modifyAttribute(20, statev, quark);
fixture.modifyAttribute(30, (Object) null, quark);
statev = 2L;
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, (Object) null, quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_3);
statev = 4L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, (Object) null, quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(80, (Object) null, quark);
fixture.closeHistory(102);
}
/**
* Test the merge of The callees children. The call stack's structure used
* in this test is shown below:
*
* <pre>
* Aggregated tree
* ___ main____ ____ main____
* ___1___ _1_ _1_
* _2_ _3_ _2_ => _2_ _3_
* _4_ _4_ _4_
* </pre>
*/
@Test
public void mergeSecondLevelCalleesTest() {
ITmfStateSystemBuilder fixture = createFixture();
buildCallStack(fixture);
// Execute the CallGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
CallGraph cg = cga.getCallGraph();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread name", "Thread", threads.get(0).getName());
assertEquals("Number of root functions ", 1, cg.getCallingContextTree(threads.get(0)).size());
Object[] children = cg.getCallingContextTree(threads.get(0)).toArray();
AggregatedCalledFunction main = (AggregatedCalledFunction) children[0];
assertEquals("Children number: main", 1, main.getCallees().size());
Object[] mainChildren = main.getCallees().toArray();
AggregatedCalledFunction function1 = (AggregatedCalledFunction) mainChildren[0];
assertEquals("Children number: first function", 2, function1.getCallees().size());
AggregatedCalledFunction function2 = (AggregatedCalledFunction) function1.getCallees().stream()
.filter(acs -> CallStackTestBase.getCallSiteSymbol(acs).resolve(Collections.emptySet()).equals("0x2"))
.findAny().get();
AggregatedCalledFunction function3 = (AggregatedCalledFunction) function1.getCallees().stream()
.filter(acs -> CallStackTestBase.getCallSiteSymbol(acs).resolve(Collections.emptySet()).equals("0x3"))
.findAny().get();
assertEquals("Children number: First child", 1, function2.getCallees().size());
assertEquals("Children number: Second child", 0, function3.getCallees().size());
Object[] firstChildCallee = function2.getCallees().toArray();
AggregatedCalledFunction function4 = (AggregatedCalledFunction) firstChildCallee[0];
assertEquals("Children number: leaf function", 0, function4.getCallees().size());
// Test duration
assertEquals("Test main's duration", 100, main.getDuration());
assertEquals("Test first function's duration", 90, function1.getDuration());
assertEquals("Test first child's duration", 40, function2.getDuration());
assertEquals("Test second child's duration", 10, function3.getDuration());
assertEquals("Test leaf's duration", 30, function4.getDuration());
// Test self time
assertEquals("Test main's self time", 10, main.getSelfTime());
assertEquals("Test first function's self time", 40, function1.getSelfTime());
assertEquals("Test first child's self time", 10,
function2.getSelfTime());
assertEquals("Test second child's self time", 10, function3.getSelfTime());
assertEquals("Test leaf's self time", 30, function4.getSelfTime());
// Test number of calls
assertEquals("Test main's number of calls", 1, main.getNbCalls());
assertEquals("Test first function's number of calls", 2, function1.getNbCalls());
assertEquals("Test first child's number of calls", 2, function2.getNbCalls());
assertEquals("Test second child's number of calls", 1, function3.getNbCalls());
assertEquals("Test leaf's number of calls", 2, function4.getNbCalls());
}
/**
* Test state system with a large amount of segments. All segments have the
* same length. The call stack's structure used in this test is shown below:
*
* <pre>
* _____
* _____
* _____
* .....
* </pre>
*/
@Test
public void largeTest() {
ITmfStateSystemBuilder fixture = createFixture();
int parentQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH, CallGraphAnalysisStub.CALLSTACK_PATH);
for (int i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
Long statev = (long) i;
fixture.pushAttribute(0, statev, parentQuark);
}
for (int i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
fixture.popAttribute(10, parentQuark);
}
fixture.closeHistory(11);
// Execute the callGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Thread name", "Thread", threads.get(0).getName());
Object[] children = cga.getCallGraph().getCallingContextTree(threads.get(0)).toArray();
AggregatedCalledFunction parent = (AggregatedCalledFunction) children[0];
for (int i = 1; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
children = parent.getCallees().toArray();
AggregatedCalledFunction child = (AggregatedCalledFunction) children[0];
parent = child;
}
}
/**
* Test mutliRoots state system.This tests if a root function called twice
* will be merged into one function or not. The call stack's structure used
* in this test is shown below:
*
* <pre>
* Aggregated tree
* _1_ _1_ => _1_
* _2_ _3_ _2_ _3_
* </pre>
*/
@Test
public void multiFunctionRootsTest() {
ITmfStateSystemBuilder fixture = createFixture();
int parentQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH, CallGraphAnalysisStub.CALLSTACK_PATH);
// Create the first root function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
Long statev = 1L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(20, (Object) null, quark);
// Create the second root function
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(50, (Object) null, quark);
// Create the first root function's callee
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = 2L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, (Object) null, quark);
// Create the second root function's callee
statev = 3L;
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(40, (Object) null, quark);
fixture.closeHistory(51);
// Execute the callGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
CallGraph cg = cga.getCallGraph();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
ICallStackElement group = threads.get(0);
assertNotNull(group);
assertEquals("Thread id", "Thread", group.getName());
assertEquals("Number of root functions ", 1, cg.getCallingContextTree(group).size());
Object[] children = cg.getCallingContextTree(group).toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 2, firstFunction.getCallees().size());
Object[] firstFunctionChildren = firstFunction.getCallees().toArray();
AggregatedCalledFunction function2 = (AggregatedCalledFunction) firstFunctionChildren[0];
AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[1];
assertEquals("Children number: Second function", 0, function2.getCallees().size());
assertEquals("Children number: Third function", 0, function3.getCallees().size());
// Test duration
assertEquals("Test first function's duration", 40, firstFunction.getDuration());
assertEquals("Test second function's duration", 10, function2.getDuration());
assertEquals("Test third function's duration", 10, function3.getDuration());
// Test self time
assertEquals("Test first function's self time", 20, firstFunction.getSelfTime());
assertEquals("Test second function's self time", 10, function2.getSelfTime());
assertEquals("Test third function's self time", 10, function2.getSelfTime());
// Test number of calls
assertEquals("Test first function's number of calls", 2, firstFunction.getNbCalls());
assertEquals("Test second function's number of calls", 1, function2.getNbCalls());
assertEquals("Test third function's number of calls", 1, function3.getNbCalls());
}
/**
* Test mutliRoots state system. The call stack's structure used in this
* test is shown below:
*
* <pre>
* Aggregated tree
* _0_ _1_ => _0_ _1_
* _2_ _2_ _2_ _2_
*
* </pre>
*/
@Test
public void multiFunctionRootsSecondTest() {
ITmfStateSystemBuilder fixture = createFixture();
int parentQuark = fixture.getQuarkAbsoluteAndAdd(CallGraphAnalysisStub.PROCESS_PATH, CallGraphAnalysisStub.THREAD_PATH, CallGraphAnalysisStub.CALLSTACK_PATH);
// Create the first root function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
Long statev = 0L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(20, (Object) null, quark);
// Create the second root function
statev = 1L;
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(50, (Object) null, quark);
// Create the first root function's callee
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = 2L;
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, (Object) null, quark);
// Create the second root function's callee
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(40, (Object) null, quark);
fixture.closeHistory(51);
// Execute the callGraphAnalysis
CallGraphAnalysisStub cga = new CallGraphAnalysisStub(fixture);
setCga(cga);
assertTrue(cga.iterate());
List<ICallStackElement> threads = getLeafElements(cga);
CallGraph cg = cga.getCallGraph();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread name", "Thread", threads.get(0).getName());
assertEquals("Number of root functions ", 2, cg.getCallingContextTree(threads.get(0)).size());
Object[] children = cg.getCallingContextTree(threads.get(0)).toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) children[1];
assertEquals("Children number: First function", 1, firstFunction.getCallees().size());
assertEquals("Children number: Second function", 1, secondFunction.getCallees().size());
Object[] firstFunctionChildren = firstFunction.getCallees().toArray();
Object[] secondFunctionChildren = secondFunction.getCallees().toArray();
AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[0];
AggregatedCalledFunction function4 = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: third function", 0, function3.getCallees().size());
assertEquals("Children number: fourth function", 0, function4.getCallees().size());
// Test duration
assertEquals("Test second function's duration", 20, firstFunction.getDuration());
assertEquals("Test second function's duration", 20, secondFunction.getDuration());
assertEquals("Test first leaf's duration", 10, function3.getDuration());
assertEquals("Test second leaf's duration", 10, function4.getDuration());
// Test self time
assertEquals("Test first function's self time", 10, firstFunction.getSelfTime());
assertEquals("Test second function's duration", 10, secondFunction.getSelfTime());
assertEquals("Test second function's self time", 10, function3.getSelfTime());
assertEquals("Test second function's self time", 10, function4.getSelfTime());
// Test number of calls
assertEquals("Test first function's number of calls", 1, firstFunction.getNbCalls());
assertEquals("Test first function's number of calls", 1, secondFunction.getNbCalls());
assertEquals("Test third function's number of calls", 1, function3.getNbCalls());
assertEquals("Test third function's number of calls", 1, function4.getNbCalls());
}
/**
* Gets the call graph analysis
* @return the call graph analysis
*/
protected CallGraphAnalysisStub getCga() {
return fCga;
}
private void setCga(CallGraphAnalysisStub cga) {
fCga = cga;
}
/**
* Get a trace for when a trace is needed
*
* @return A trace, that has no relation with the callgraphs of these tests
*/
protected @NonNull ITmfTrace getTrace() {
return Objects.requireNonNull(fTrace);
}
}