/*******************************************************************************
* 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.analysis.timing.core.tests.flamegraph;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.AggregatedCalledFunction;
import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.CallGraphAnalysis;
import org.eclipse.tracecompass.internal.analysis.timing.core.callgraph.ThreadNode;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
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.segment.ISegmentAspect;
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 @NonNull String PROCESS_PATH = "Processes";
private static final @NonNull String THREAD_PATH = "Thread";
private static final @NonNull String CALLSTACK_PATH = "CallStack";
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 final String @NonNull [] CSP = { CALLSTACK_PATH };
private static final String @NonNull [] PP = { PROCESS_PATH };
private static final String @NonNull [] TP = { THREAD_PATH };
/**
* This class is used to make the CallGraphAnalysis's method
* iterateOverStateSystem() visible to test
*/
private class CGAnalysis extends CallGraphAnalysis {
private final class HelloAspect implements ISegmentAspect {
@Override
public @NonNull String getName() {
return "aspect name";
}
@Override
public @NonNull String getHelpText() {
return "aspect help";
}
@Override
public @Nullable Comparator<?> getComparator() {
return null;
}
@Override
public @Nullable Object resolve(@NonNull ISegment segment) {
return "Hello";
}
}
@Override
protected boolean iterateOverStateSystem(@Nullable ITmfStateSystem ss, String[] threadsPattern, String[] processesPattern, String[] callStackPath, IProgressMonitor monitor) {
return super.iterateOverStateSystem(ss, threadsPattern, processesPattern, callStackPath, monitor);
}
@Override
public @NonNull Iterable<@NonNull ISegmentAspect> getSegmentAspects() {
ImmutableList<@NonNull ISegmentAspect> aspectList = ImmutableList.of(new HelloAspect());
assertNotNull(aspectList);
return aspectList;
}
}
private static ITmfStateSystemBuilder createFixture() {
IStateHistoryBackend backend;
backend = StateHistoryBackendFactory.createInMemoryBackend("Test", 0L);
ITmfStateSystemBuilder fixture = StateSystemFactory.newStateSystem(backend);
return fixture;
}
private CGAnalysis fCga;
/**
* Test an empty state system.
*/
@Test
public void emptyStateSystemTest() {
ITmfStateSystemBuilder fixture = createFixture();
fixture.closeHistory(1002);
CGAnalysis cga = new CGAnalysis();
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
assertNotNull(threads);
assertEquals("Number of threads found", 0, threads.size());
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH);
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, 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));
TmfStateValue statev = TmfStateValue.newValueLong(i);
fixture.modifyAttribute(start, TmfStateValue.nullValue(), quark);
fixture.modifyAttribute(start + i, statev, quark);
fixture.modifyAttribute(end - i, TmfStateValue.nullValue(), quark);
}
fixture.closeHistory(1002);
// Execute the CallGraphAnalysis
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
@NonNull
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size());
assertEquals("Thread id", 100, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getChildren().size());
Object @NonNull [] firstFunctionChildren = firstFunction.getChildren().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 1, secondFunction.getChildren().size());
Object @NonNull [] secondFunctionChildren = secondFunction.getChildren().toArray();
AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: Third function", 0, thirdFunction.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(thirdFunction.getParent()).getSymbol(), secondFunction.getSymbol());
// 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 depth
assertEquals("Test first function's depth", 0, firstFunction.getDepth());
assertEquals("Test second function's depth", 1, secondFunction.getDepth());
assertEquals("Test third function's depth", 2, thirdFunction.getDepth());
// 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());
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH);
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CALLSTACK_PATH);
fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark);
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
TmfStateValue statev = TmfStateValue.newValueLong(0);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = TmfStateValue.newValueLong(1);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark);
fixture.closeHistory(102);
// Execute the CallGraphAnalysis
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread id", -1, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getChildren().size());
Object[] firstFunctionChildren = firstFunction.getChildren().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 1, secondFunction.getChildren().size());
Object[] secondFunctionChildren = secondFunction.getChildren().toArray();
AggregatedCalledFunction thirdFunction = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: Third function", 0, thirdFunction.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(thirdFunction.getParent()).getSymbol(), secondFunction.getSymbol());
// 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 depth
assertEquals("Test first function's depth", 0, firstFunction.getDepth());
assertEquals("Test second function's depth", 1, secondFunction.getDepth());
assertEquals("Test third function's depth", 2, thirdFunction.getDepth());
// 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());
cga.dispose();
}
/**
* 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(PROCESS_PATH, "123");
int parentQuark = fixture.getQuarkRelativeAndAdd(threadQuark, CALLSTACK_PATH);
fixture.updateOngoingState(TmfStateValue.newValueDouble(0.001), threadQuark);
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
TmfStateValue statev = TmfStateValue.newValueLong(0);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = TmfStateValue.newValueLong(1);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
statev = TmfStateValue.newValueLong(2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark);
statev = TmfStateValue.newValueLong(3);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(80, TmfStateValue.nullValue(), quark);
fixture.closeHistory(102);
// Execute the CallGraphAnalysis
CGAnalysis cga = new CGAnalysis();
String @NonNull [] tp = { "123" };
assertTrue(cga.iterateOverStateSystem(fixture, tp, PP, CSP, new NullProgressMonitor()));
setCga(cga);
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread id", 123, threads.get(0).getId());
assertEquals("Thread name", "123", threads.get(0).getSymbol());
assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 1, firstFunction.getChildren().size());
Object[] firstFunctionChildren = firstFunction.getChildren().toArray();
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) firstFunctionChildren[0];
assertEquals("Children number: Second function", 2, secondFunction.getChildren().size());
Object[] secondFunctionChildren = secondFunction.getChildren().toArray();
AggregatedCalledFunction leaf1 = (AggregatedCalledFunction) secondFunctionChildren[0];
AggregatedCalledFunction leaf2 = (AggregatedCalledFunction) secondFunctionChildren[1];
assertEquals("Children number: First leaf function", 0, leaf1.getChildren().size());
assertEquals("Children number: Second leaf function", 0, leaf2.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(secondFunction.getParent()).getSymbol(), firstFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(leaf1.getParent()).getSymbol(), secondFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(leaf2.getParent()).getSymbol(), secondFunction.getSymbol());
// 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 depth
assertEquals("Test first function's depth", 0, firstFunction.getDepth());
assertEquals("Test second function's depth", 1, secondFunction.getDepth());
assertEquals("Test first leaf's depth", 2, leaf1.getDepth());
assertEquals("Test second leaf's depth", 2, leaf2.getDepth());
// 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());
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH);
// Create the first function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
TmfStateValue statev = TmfStateValue.newValueLong(0);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark);
// Create the first level functions
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = TmfStateValue.newValueLong(1);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(100, TmfStateValue.nullValue(), quark);
// Create the third function
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_2);
statev = TmfStateValue.newValueLong(2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark);
statev = TmfStateValue.newValueLong(3);
fixture.modifyAttribute(20, statev, quark);
fixture.modifyAttribute(30, TmfStateValue.nullValue(), quark);
statev = TmfStateValue.newValueLong(2);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(90, TmfStateValue.nullValue(), quark);
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_3);
statev = TmfStateValue.newValueLong(4);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark);
fixture.modifyAttribute(60, statev, quark);
fixture.modifyAttribute(80, TmfStateValue.nullValue(), 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
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread id", -1, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction main = (AggregatedCalledFunction) children[0];
assertEquals("Children number: main", 1, main.getChildren().size());
Object[] mainChildren = main.getChildren().toArray();
AggregatedCalledFunction function1 = (AggregatedCalledFunction) mainChildren[0];
assertEquals("Children number: first function", 2, function1.getChildren().size());
Object[] firstFunctionChildren = function1.getChildren().toArray();
AggregatedCalledFunction function2 = (AggregatedCalledFunction) firstFunctionChildren[0];
AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[1];
assertEquals("Children number: First child", 1, function2.getChildren().size());
assertEquals("Children number: Second child", 0, function3.getChildren().size());
Object[] firstChildCallee = function2.getChildren().toArray();
AggregatedCalledFunction function4 = (AggregatedCalledFunction) firstChildCallee[0];
assertEquals("Children number: leaf function", 0, function4.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function1.getParent()).getSymbol(), main.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function2.getParent()).getSymbol(), function1.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), function1.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function4.getParent()).getSymbol(), function2.getSymbol());
// 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 depth
assertEquals("Test main function's depth", 0, main.getDepth());
assertEquals("Test first function's depth", 1, function1.getDepth());
assertEquals("Test first child's depth", 2, function2.getDepth());
assertEquals("Test second child's depth", 2, function3.getDepth());
assertEquals("Test leaf's depth", 3, function4.getDepth());
// 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());
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH);
for (int i = 0; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
TmfStateValue statev = TmfStateValue.newValueLong(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
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Thread id", -1, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction parent = (AggregatedCalledFunction) children[0];
for (int i = 1; i < LARGE_AMOUNT_OF_SEGMENTS; i++) {
children = parent.getChildren().toArray();
AggregatedCalledFunction child = (AggregatedCalledFunction) children[0];
assertEquals("Test parenthood", NonNullUtils.checkNotNull(child.getParent()).getSymbol(), NonNullUtils.checkNotNull(parent.getSymbol()));
parent = child;
}
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH);
// Create the first root function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
TmfStateValue statev = TmfStateValue.newValueLong(1);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(20, TmfStateValue.nullValue(), quark);
// Create the second root function
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark);
// Create the first root function's callee
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = TmfStateValue.newValueLong(2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark);
// Create the second root function's callee
statev = TmfStateValue.newValueLong(3);
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(40, TmfStateValue.nullValue(), quark);
fixture.closeHistory(51);
// Execute the callGraphAnalysis
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread id", -1, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
assertEquals("Number of root functions ", 1, threads.get(0).getChildren().size());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
assertEquals("Children number: First function", 2, firstFunction.getChildren().size());
Object[] firstFunctionChildren = firstFunction.getChildren().toArray();
AggregatedCalledFunction function2 = (AggregatedCalledFunction) firstFunctionChildren[0];
AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[1];
assertEquals("Children number: Second function", 0, function2.getChildren().size());
assertEquals("Children number: Third function", 0, function3.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function2.getParent()).getSymbol(), firstFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), firstFunction.getSymbol());
// 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 depth
assertEquals("Test first function's depth", 0, firstFunction.getDepth());
assertEquals("Test second function's depth", 1, function2.getDepth());
assertEquals("Test third function's depth", 1, function3.getDepth());
// 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());
cga.dispose();
}
/**
* 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(PROCESS_PATH, THREAD_PATH, CALLSTACK_PATH);
// Create the first root function
int quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_0);
TmfStateValue statev = TmfStateValue.newValueLong(0);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(20, TmfStateValue.nullValue(), quark);
// Create the second root function
statev = TmfStateValue.newValueLong(1);
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(50, TmfStateValue.nullValue(), quark);
// Create the first root function's callee
quark = fixture.getQuarkRelativeAndAdd(parentQuark, QUARK_1);
statev = TmfStateValue.newValueLong(2);
fixture.modifyAttribute(0, statev, quark);
fixture.modifyAttribute(10, TmfStateValue.nullValue(), quark);
// Create the second root function's callee
fixture.modifyAttribute(30, statev, quark);
fixture.modifyAttribute(40, TmfStateValue.nullValue(), quark);
fixture.closeHistory(51);
// Execute the callGraphAnalysis
CGAnalysis cga = new CGAnalysis();
setCga(cga);
assertTrue(cga.iterateOverStateSystem(fixture, TP, PP, CSP, new NullProgressMonitor()));
List<ThreadNode> threads = cga.getThreadNodes();
// Test the threads generated by the analysis
assertNotNull(threads);
assertEquals("Number of thread nodes Found", 1, threads.size());
assertEquals("Thread id", -1, threads.get(0).getId());
assertEquals("Thread name", "Thread", threads.get(0).getSymbol());
assertEquals("Number of root functions ", 2, threads.get(0).getChildren().size());
Object[] children = threads.get(0).getChildren().toArray();
AggregatedCalledFunction firstFunction = (AggregatedCalledFunction) children[0];
AggregatedCalledFunction secondFunction = (AggregatedCalledFunction) children[1];
assertEquals("Children number: First function", 1, firstFunction.getChildren().size());
assertEquals("Children number: Second function", 1, secondFunction.getChildren().size());
Object[] firstFunctionChildren = firstFunction.getChildren().toArray();
Object[] secondFunctionChildren = secondFunction.getChildren().toArray();
AggregatedCalledFunction function3 = (AggregatedCalledFunction) firstFunctionChildren[0];
AggregatedCalledFunction function4 = (AggregatedCalledFunction) secondFunctionChildren[0];
assertEquals("Children number: third function", 0, function3.getChildren().size());
assertEquals("Children number: fourth function", 0, function4.getChildren().size());
// Test links
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function3.getParent()).getSymbol(), firstFunction.getSymbol());
assertEquals("Test parenthood ", NonNullUtils.checkNotNull(function4.getParent()).getSymbol(), secondFunction.getSymbol());
// 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 depth
assertEquals("Test first function's depth", 0, firstFunction.getDepth());
assertEquals("Test first function's depth", 0, secondFunction.getDepth());
assertEquals("Test third function's depth", 1, function3.getDepth());
assertEquals("Test third function's depth", 1, function4.getDepth());
// 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());
cga.dispose();
}
/**
* Gets the call graph analysis
* @return the call graph analysis
*/
protected CGAnalysis getCga() {
return fCga;
}
private void setCga(CGAnalysis cga) {
fCga = cga;
}
}