| /******************************************************************************* |
| * 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"); |
| // } |
| // } |
| // } |
| } |