blob: 4285aab0ad9d525443f752ce49201aee9f8a1ef6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 École Polytechnique de Montréal
*
* 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;
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.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.incubator.analysis.core.concepts.AggregatedCallSite;
import org.eclipse.tracecompass.incubator.analysis.core.concepts.ICpuTimeProvider;
import org.eclipse.tracecompass.incubator.analysis.core.model.IHostModel;
import org.eclipse.tracecompass.incubator.analysis.core.model.ModelManager;
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.tests.flamechart.CallStackTestBase;
import org.eclipse.tracecompass.incubator.callstack.core.tests.stubs.CallStackAnalysisStub;
import org.eclipse.tracecompass.incubator.internal.analysis.core.model.CompositeHostModel;
import org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.InstrumentedCallStackElement;
import org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.callgraph.AggregatedCalledFunction;
import org.eclipse.tracecompass.incubator.internal.callstack.core.instrumented.callgraph.CallGraphAnalysis;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.junit.After;
import org.junit.Test;
/**
* Test the callgraph analysis with the call stack trace and module
*
* @author Geneviève Bastien
*/
public class CallGraphWithCallStackAnalysisTest extends CallStackTestBase {
/**
* Clean up the memory
*/
@After
public void cleanUp() {
// Model objects use weak hash map, we garbage-collect here to make sure
// there are no artefacts in memory
System.gc();
}
/**
* Test tha callgraph with a small trace
*/
@Test
public void testCallGraph() {
CallStackAnalysisStub cga = getModule();
CallGraph cg = cga.getCallGraph();
try {
Collection<ICallStackElement> elements = cg.getElements();
for (ICallStackElement group : elements) {
String firstLevelName = group.getName();
switch (firstLevelName) {
case "1":
verifyProcess1(cg, group);
break;
case "5":
verifyProcess5(cg, group);
break;
default:
fail("Unknown process in callstack");
}
}
} finally {
cga.dispose();
}
}
private static void verifyProcess1(CallGraph cg, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = cg.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "2":
assertEquals(2, children.size());
for (AggregatedCallSite child : children) {
assertTrue(child instanceof AggregatedCalledFunction);
AggregatedCalledFunction func = (AggregatedCalledFunction) child;
switch (getCallSiteSymbol(func).resolve(Collections.emptySet())) {
case "op1":
assertEquals(9, func.getDuration());
assertEquals(5, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(1, func.getCallees().size());
AggregatedCalledFunction next = (AggregatedCalledFunction) func.getCallees().iterator().next();
assertNotNull(next);
assertEquals(4, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(1, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
break;
case "op4":
assertEquals(8, func.getDuration());
assertEquals(8, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(0, func.getCallees().size());
break;
default:
fail("Unknown symbol for thread 2" + getCallSiteSymbol(func));
}
}
break;
case "3":
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertEquals("op2", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(17, func.getDuration());
assertEquals(10, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(2, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op3":
assertEquals(1, next.getDuration());
assertEquals(1, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
case "op2":
assertEquals(6, next.getDuration());
assertEquals(6, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
default:
fail("Unknown symbol for thread 2" + getCallSiteSymbol(func));
}
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
private static void verifyProcess5(CallGraph cg, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = cg.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "6": {
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op1", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(19, func.getDuration());
assertEquals(3, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(3, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op2":
{
assertEquals(3, next.getDuration());
assertEquals(2, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
case "op3":
{
assertEquals(5, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op3", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(2, third.getDuration());
assertEquals(2, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op1", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
case "op4":
assertEquals(8, next.getDuration());
assertEquals(8, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op4", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(0, next.getCallees().size());
break;
default:
fail("Unknown symbol for second level of tid 6");
}
}
}
break;
case "7": {
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op5", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(19, func.getDuration());
assertEquals(7, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(1, func.getCallees().size());
// Verify children
Iterator<AggregatedCallSite> iterator = func.getCallees().iterator();
AggregatedCalledFunction next = (AggregatedCalledFunction) iterator.next();
assertNotNull(next);
assertEquals(12, next.getDuration());
assertEquals(11, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(3, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
private CallGraphAnalysis getCallGraphModule() throws TmfAnalysisException {
CallGraphAnalysis cga = new CallGraphAnalysis(Objects.requireNonNull(getModule()));
cga.setId(getModule().getId());
cga.setTrace(getTrace());
cga.schedule();
cga.waitForCompletion();
return cga;
}
/**
* Test a callgraph with a callstack that provides CPU times
*
* @throws TmfAnalysisException
* Propagates exceptions
*/
@Test
public void testCallGraphWithCpuTime() throws TmfAnalysisException {
IHostModel model = ModelManager.getModelFor(getTrace().getHostId());
// Assign it to a variable because the model uses weak hash map, we
// don't want it garbage-collected before the end of the test.
ICpuTimeProvider cpuTimeProvider = new ICpuTimeProvider() {
@Override
public long getCpuTime(int tid, long start, long end) {
// TID 7 was out of CPU from 3 to 4
if (tid == 7) {
long beginTime = Math.max(start, 3);
long endTime = Math.min(end, 4);
if (endTime - beginTime > 0) {
return (end - start) - (endTime - beginTime);
}
}
// TID 3 was out of CPU from 8 to 11
if (tid == 3) {
long beginTime = Math.max(start, 8);
long endTime = Math.min(end, 11);
if (endTime - beginTime > 0) {
return (end - start) - (endTime - beginTime);
}
}
// TID 2 was out of CPU from 13 to 18
if (tid == 2) {
long beginTime = Math.max(start, 13);
long endTime = Math.min(end, 18);
if (endTime - beginTime > 0) {
return (end - start) - (endTime - beginTime);
}
}
return end - start;
}
@Override
public @NonNull Collection<@NonNull String> getHostIds() {
return Collections.singleton("callstack.xml");
}
};
((CompositeHostModel) model).setCpuTimeProvider(cpuTimeProvider);
CallGraphAnalysis cga = getCallGraphModule();
CallGraph callGraph = cga.getCallGraph();
try {
Collection<ICallStackElement> groups = callGraph.getElements();
for (ICallStackElement group : groups) {
String firstLevelName = group.getName();
switch (firstLevelName) {
case "1":
// Make sure the symbol key is correctly resolved
verifyProcess1CpuTime(callGraph, group);
break;
case "5":
// Make sure the symbol key is correctly resolved
verifyProcess5CpuTime(callGraph, group);
break;
default:
fail("Unknown process in callstack");
}
}
} finally {
cga.dispose();
}
}
private static void verifyProcess1CpuTime(CallGraph callGraph, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = callGraph.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "2":
assertEquals(2, children.size());
for (AggregatedCallSite child : children) {
assertTrue(child instanceof AggregatedCalledFunction);
AggregatedCalledFunction func = (AggregatedCalledFunction) child;
switch (getCallSiteSymbol(func).resolve(Collections.emptySet())) {
case "op1":
assertEquals(9, func.getDuration());
assertEquals(5, func.getSelfTime());
assertEquals(9, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(1, func.getCallees().size());
AggregatedCalledFunction next = (AggregatedCalledFunction) func.getCallees().iterator().next();
assertNotNull(next);
assertEquals(4, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(4, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(1, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(1, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
break;
case "op4":
assertEquals(8, func.getDuration());
assertEquals(8, func.getSelfTime());
assertEquals(3, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(0, func.getCallees().size());
break;
default:
fail("Unknown symbol for thread 2: " + getCallSiteSymbol(func));
}
}
break;
case "3":
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertEquals("op2", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(17, func.getDuration());
assertEquals(10, func.getSelfTime());
assertEquals(14, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(2, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op3":
assertEquals(1, next.getDuration());
assertEquals(1, next.getSelfTime());
assertEquals(1, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
case "op2":
assertEquals(6, next.getDuration());
assertEquals(6, next.getSelfTime());
assertEquals(3, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
default:
fail("Unknown symbol for thread 3: " + getCallSiteSymbol(func));
}
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
private static void verifyProcess5CpuTime(CallGraph callGraph, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = callGraph.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "6": {
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op1", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(19, func.getDuration());
assertEquals(3, func.getSelfTime());
assertEquals(19, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(3, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op2":
{
assertEquals(3, next.getDuration());
assertEquals(2, next.getSelfTime());
assertEquals(3, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(1, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
case "op3":
{
assertEquals(5, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(5, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op3", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(2, third.getDuration());
assertEquals(2, third.getSelfTime());
assertEquals(2, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op1", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
case "op4":
assertEquals(8, next.getDuration());
assertEquals(8, next.getSelfTime());
assertEquals(8, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op4", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(0, next.getCallees().size());
break;
default:
fail("Unknown symbol for second level of tid 6: " + getCallSiteSymbol(next));
}
}
}
break;
case "7": {
/*
* pid1 --- tid2 1e1 ------------- 10x1 12e4------------20x |
* 3e2-------7x | 4e3--5x |-- tid3 3e2
* --------------------------------20x 5e3--6x 7e2--------13x
*
* pid5 --- tid6 1e1 -----------------------------------20x |
* 2e3 ---------7x 12e4------------20x | 4e1--6x |-- tid7 1e5
* -----------------------------------20x 2e2 +++ 6x 9e2 ++++
* 13x 15e2 ++ 19x 10e3 + 11x
*/
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op5", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(19, func.getDuration());
assertEquals(7, func.getSelfTime());
assertEquals(18, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(1, func.getCallees().size());
// Verify children
Iterator<AggregatedCallSite> iterator = func.getCallees().iterator();
AggregatedCalledFunction next = (AggregatedCalledFunction) iterator.next();
assertNotNull(next);
assertEquals(12, next.getDuration());
assertEquals(11, next.getSelfTime());
assertEquals(11, next.getCpuTime());
assertEquals(3, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(1, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
/**
* Test the callgraph for a time selection, with a small trace
*/
@Test
public void testSelectionCallGraph() {
CallStackAnalysisStub cga = getModule();
CallGraph cg = cga.getCallGraph(TmfTimestamp.fromNanos(1), TmfTimestamp.fromNanos(10));
try {
Collection<ICallStackElement> elements = cg.getElements();
for (ICallStackElement group : elements) {
String firstLevelName = group.getName();
switch (firstLevelName) {
case "1":
verifyProcess1Selection(cg, group);
break;
case "5":
verifyProcess5Selection(cg, group);
break;
default:
fail("Unknown process in callstack");
}
}
// Test that another call to the callgraph returns the exact same object
CallGraph cg2 = cga.getCallGraph(TmfTimestamp.fromNanos(1), TmfTimestamp.fromNanos(10));
assertTrue(cg == cg2);
} finally {
cga.dispose();
}
}
private static void verifyProcess1Selection(CallGraph cg, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = cg.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "2":
assertEquals(1, children.size());
for (AggregatedCallSite child : children) {
assertTrue(child instanceof AggregatedCalledFunction);
AggregatedCalledFunction func = (AggregatedCalledFunction) child;
switch (getCallSiteSymbol(func).resolve(Collections.emptySet())) {
case "op1":
assertEquals(9, func.getDuration());
assertEquals(5, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(1, func.getCallees().size());
AggregatedCalledFunction next = (AggregatedCalledFunction) func.getCallees().iterator().next();
assertNotNull(next);
assertEquals(4, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(1, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
break;
default:
fail("Unknown symbol for thread 2" + getCallSiteSymbol(func));
}
}
break;
case "3":
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertEquals("op2", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(7, func.getDuration());
assertEquals(3, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(1, func.getProcessId());
assertEquals(2, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op3":
assertEquals(1, next.getDuration());
assertEquals(1, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
case "op2":
assertEquals(3, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(1, next.getProcessId());
assertEquals(0, next.getCallees().size());
break;
default:
fail("Unknown symbol for thread 2" + getCallSiteSymbol(func));
}
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
private static void verifyProcess5Selection(CallGraph cg, ICallStackElement element) {
Collection<ICallStackElement> secondLevels = element.getChildrenElements();
assertEquals(2, secondLevels.size());
for (ICallStackElement secondLevel : secondLevels) {
assertTrue(secondLevel instanceof InstrumentedCallStackElement);
assertTrue(secondLevel.isLeaf());
String secondLevelName = secondLevel.getName();
Collection<AggregatedCallSite> children = cg.getCallingContextTree(secondLevel);
switch (secondLevelName) {
case "6": {
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op1", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(9, func.getDuration());
assertEquals(2, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(2, func.getCallees().size());
for (AggregatedCallSite nextChild : func.getCallees()) {
assertTrue(nextChild instanceof AggregatedCalledFunction);
AggregatedCalledFunction next = (AggregatedCalledFunction) nextChild;
switch (getCallSiteSymbol(next).resolve(Collections.emptySet())) {
case "op2":
{
assertEquals(2, next.getDuration());
assertEquals(1, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(1, third.getDuration());
assertEquals(1, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op3", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
case "op3":
{
assertEquals(5, next.getDuration());
assertEquals(3, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(1, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op3", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(1, next.getCallees().size());
AggregatedCalledFunction third = (AggregatedCalledFunction) next.getCallees().iterator().next();
assertNotNull(third);
assertEquals(2, third.getDuration());
assertEquals(2, third.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, third.getCpuTime());
assertEquals(1, third.getNbCalls());
assertEquals(5, third.getProcessId());
assertEquals("op1", getCallSiteSymbol(third).resolve(Collections.emptySet()));
assertEquals(0, third.getCallees().size());
}
break;
default:
fail("Unknown symbol for second level of tid 6");
}
}
}
break;
case "7": {
assertEquals(1, children.size());
AggregatedCalledFunction func = (AggregatedCalledFunction) children.iterator().next();
assertNotNull(func);
assertEquals("op5", getCallSiteSymbol(func).resolve(Collections.emptySet()));
assertEquals(9, func.getDuration());
assertEquals(4, func.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, func.getCpuTime());
assertEquals(1, func.getNbCalls());
assertEquals(5, func.getProcessId());
assertEquals(1, func.getCallees().size());
// Verify children
Iterator<AggregatedCallSite> iterator = func.getCallees().iterator();
AggregatedCalledFunction next = (AggregatedCalledFunction) iterator.next();
assertNotNull(next);
assertEquals(5, next.getDuration());
assertEquals(5, next.getSelfTime());
assertEquals(IHostModel.TIME_UNKNOWN, next.getCpuTime());
assertEquals(2, next.getNbCalls());
assertEquals(5, next.getProcessId());
assertEquals("op2", getCallSiteSymbol(next).resolve(Collections.emptySet()));
assertEquals(0, next.getCallees().size());
}
break;
default:
fail("Unknown process in callstack: " + secondLevelName);
}
}
}
}