blob: 14874764f0d21b604427a0fe891aab1305e8f338 [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 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.analysis.profiling.core.tests.flamechart;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.profiling.core.base.IProfilingGroupDescriptor;
import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackAnalysis;
import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackSeries;
import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackStateProvider;
import org.eclipse.tracecompass.analysis.profiling.core.tests.CallStackTestBase;
import org.eclipse.tracecompass.analysis.profiling.core.tests.data.CallStackTestData;
import org.eclipse.tracecompass.analysis.profiling.core.tests.data.TestDataBigCallStack;
import org.eclipse.tracecompass.analysis.profiling.core.tests.data.TestDataSmallCallStack;
import org.eclipse.tracecompass.analysis.profiling.core.tests.stubs.CallStackAnalysisStub;
import org.eclipse.tracecompass.internal.analysis.profiling.core.callstack.InstrumentedGroupDescriptor;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.IntervalInfo;
import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.StateSystemTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* Test the call stack provider and callstack analysis for state system
* callstacks. This class specifically tests the content of the state system
* built from the {@link CallStackAnalysis} and the
* {@link CallStackStateProvider}
*
* @author Geneviève Bastien
*/
@RunWith(Parameterized.class)
public class CallStackStateSystemTest extends CallStackTestBase {
/**
* Get the traces on which to run the benchmark
*
* @return The arrays of parameters
*/
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> getParameters() {
return Arrays.asList(new Object[][] {
{ "Small trace", new TestDataSmallCallStack() },
{ "Big trace", new TestDataBigCallStack() },
});
}
/**
* Constructor
*
* @param name
* The name of this test
* @param data
* The test data
*/
public CallStackStateSystemTest(String name, CallStackTestData data) {
super(data);
}
/**
* Test that the module as a callstack provider produces the same results as
* the callstack analysis module under it
*/
@Test
public void testCallStackProvider() {
CallStackAnalysisStub module = getModule();
assertNotNull(module);
// There should be only 1 callstack series
CallStackSeries callstack = module.getCallStackSeries();
assertNotNull(callstack);
// Get the patterns for each level of the callstack
List<String[]> patterns = module.getPatterns();
assertEquals(2, patterns.size());
// Check each level of the callstack. Make sure the path in the series
// correspond to the expected path
IProfilingGroupDescriptor nextLevel = callstack.getRootGroup();
assertTrue(nextLevel instanceof InstrumentedGroupDescriptor);
String[] subPattern = ((InstrumentedGroupDescriptor) nextLevel).getSubPattern();
assertArrayEquals(patterns.get(0), subPattern);
nextLevel = nextLevel.getNextGroup();
assertTrue(nextLevel instanceof InstrumentedGroupDescriptor);
subPattern = ((InstrumentedGroupDescriptor) nextLevel).getSubPattern();
assertArrayEquals(patterns.get(1), subPattern);
nextLevel = nextLevel.getNextGroup();
assertNull(nextLevel);
}
/**
* Test the content of the callstack state system built from the state
* provider
*
* @throws AttributeNotFoundException
* Exception thrown by test
*/
@Test
public void testCallStackContent() throws AttributeNotFoundException {
// The javadoc of getModule() contains the expected structure of the
// callstack
CallStackAnalysisStub module = getModule();
assertNotNull(module);
// There should be 1 callstack series
CallStackSeries callstack = module.getCallStackSeries();
assertNotNull(callstack);
ITmfStateSystem ss = module.getStateSystem();
assertNotNull(ss);
List<String[]> patterns = module.getPatterns();
CallStackTestData traceData = getTraceData();
// Get the process quarks (first level)
List<Integer> quarks = ss.getQuarks(patterns.get(0));
assertEquals("Number of processes", traceData.getNumberOfProcesses(), quarks.size());
int actualStackCount = 0;
for (Integer processQuark : quarks) {
// Get the threads under this process (second level)
List<Integer> threadQuarks = ss.getQuarks(processQuark, patterns.get(1));
assertEquals("Number of processes", 2, threadQuarks.size());
for (Integer threadQuark : threadQuarks) {
int csQuark = ss.getQuarkRelative(threadQuark, CallStackAnalysis.CALL_STACK);
List<Integer> subAttributes = ss.getSubAttributes(csQuark, false);
actualStackCount += subAttributes.size();
}
}
Set<@NonNull IntervalInfo> stateSystemIntervals = traceData.toStateSystemInterval(patterns.get(0)[0]);
assertEquals("Number of callstack data elements", stateSystemIntervals.size(), actualStackCount);
StateSystemTestUtils.testIntervals(ss, stateSystemIntervals);
}
// private void verifyProcess(ITmfStateSystem ss, int pid, CallStackSeries
// callstack, List<Integer> threadQuarks) throws AttributeNotFoundException
// {
// for (Integer threadQuark : threadQuarks) {
// verifyThread(ss, pid, Integer.parseInt(ss.getAttributeName(threadQuark)),
// threadQuark, callstack);
// }
// }
//
// private void verifyThread(ITmfStateSystem ss, int pid, int tid, Integer
// threadQuark, CallStackSeries callstack) throws AttributeNotFoundException
// {
// int csQuark = ss.getQuarkRelative(threadQuark,
// CallStackAnalysis.CALL_STACK);
// String[] csPathArray = ss.getFullAttributePathArray(csQuark);
// List<String> pathList = new ArrayList<>();
// pathList.addAll(Arrays.asList(csPathArray));
//
// }
//
// private static void verifyProcess1(ITmfStateSystem ss, CallStackSeries
// callstack, List<Integer> threadQuarks) throws AttributeNotFoundException
// {
// for (Integer threadQuark : threadQuarks) {
// int csQuark = ss.getQuarkRelative(threadQuark,
// CallStackAnalysis.CALL_STACK);
// String[] csPathArray = ss.getFullAttributePathArray(csQuark);
// List<String> pathList = new ArrayList<>();
// pathList.addAll(Arrays.asList(csPathArray));
// switch (ss.getAttributeName(threadQuark)) {
// case "2": {
// List<Integer> subAttributes = ss.getSubAttributes(csQuark, false);
// assertEquals(3, subAttributes.size());
// List<ITmfStateInterval> expected = new ArrayList<>();
// // Check the first depth level of thread 2
// pathList.add("1");
// expected.add(new StateIntervalStub(1, 9,
// TmfStateValue.newValueString("op1")));
// expected.add(new StateIntervalStub(10, 11, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(12, 19,
// TmfStateValue.newValueString("op4")));
// expected.add(new StateIntervalStub(20, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the second depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("2");
// expected.clear();
// expected.add(new StateIntervalStub(1, 2, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(3, 6,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(7, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the third depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("3");
// expected.clear();
// expected.add(new StateIntervalStub(1, 3, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(4, 4,
// TmfStateValue.newValueString("op3")));
// expected.add(new StateIntervalStub(5, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// }
// break;
// case "3": {
// List<Integer> subAttributes = ss.getSubAttributes(csQuark, false);
// assertEquals(2, subAttributes.size());
// List<ITmfStateInterval> expected = new ArrayList<>();
// // Check the first depth level of thread 3
// pathList.add("1");
// expected.add(new StateIntervalStub(1, 2, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(3, 19,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(20, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the second depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("2");
// expected.clear();
// expected.add(new StateIntervalStub(1, 4, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(5, 5,
// TmfStateValue.newValueString("op3")));
// expected.add(new StateIntervalStub(6, 6, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(7, 12,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(13, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
// }
// break;
// default:
// fail("Unknown thread child of process 5");
// }
// }
// }
//
// private static void verifyProcess5(ITmfStateSystem ss, CallStackSeries
// callstack, List<Integer> threadQuarks) throws AttributeNotFoundException
// {
// for (Integer threadQuark : threadQuarks) {
// int csQuark = ss.getQuarkRelative(threadQuark,
// CallStackAnalysis.CALL_STACK);
// String[] csPathArray = ss.getFullAttributePathArray(csQuark);
// List<String> pathList = new ArrayList<>();
// pathList.addAll(Arrays.asList(csPathArray));
// switch (ss.getAttributeName(threadQuark)) {
// case "6": {
// List<Integer> subAttributes = ss.getSubAttributes(csQuark, false);
// assertEquals(3, subAttributes.size());
// List<ITmfStateInterval> expected = new ArrayList<>();
// // Check the first depth level of thread 6
// pathList.add("1");
// expected.add(new StateIntervalStub(1, 19,
// TmfStateValue.newValueString("op1")));
// expected.add(new StateIntervalStub(20, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the second depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("2");
// expected.clear();
// expected.add(new StateIntervalStub(1, 1, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(2, 6,
// TmfStateValue.newValueString("op3")));
// expected.add(new StateIntervalStub(7, 7, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(8, 10,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(11, 11, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(12, 19,
// TmfStateValue.newValueString("op4")));
// expected.add(new StateIntervalStub(20, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the third depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("3");
// expected.clear();
// expected.add(new StateIntervalStub(1, 3, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(4, 5,
// TmfStateValue.newValueString("op1")));
// expected.add(new StateIntervalStub(6, 8, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(9, 9,
// TmfStateValue.newValueString("op3")));
// expected.add(new StateIntervalStub(10, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
// }
// break;
// case "7": {
// List<Integer> subAttributes = ss.getSubAttributes(csQuark, false);
// assertEquals(3, subAttributes.size());
// List<ITmfStateInterval> expected = new ArrayList<>();
// // Check the first depth level of thread 7
// pathList.add("1");
// expected.add(new StateIntervalStub(1, 19,
// TmfStateValue.newValueString("op5")));
// expected.add(new StateIntervalStub(20, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the second depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("2");
// expected.clear();
// expected.add(new StateIntervalStub(1, 1, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(2, 5,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(6, 8, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(9, 12,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(13, 14, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(15, 18,
// TmfStateValue.newValueString("op2")));
// expected.add(new StateIntervalStub(19, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
//
// // Check the third depth level
// pathList.remove(pathList.size() - 1);
// pathList.add("3");
// expected.clear();
// expected.add(new StateIntervalStub(1, 9, TmfStateValue.nullValue()));
// expected.add(new StateIntervalStub(10, 10,
// TmfStateValue.newValueString("op3")));
// expected.add(new StateIntervalStub(11, 20, TmfStateValue.nullValue()));
// StateSystemTestUtils.testIntervalForAttributes(ss, expected,
// pathList.toArray(new String[pathList.size()]));
// }
// break;
// default:
// fail("Unknown thread child of process 5");
// }
// }
// }
}