Skip to content

Commit

Permalink
callstack: Add initial test classes from Incubator
Browse files Browse the repository at this point in the history
Start test-covering this new callstack plugin being brought from
Incubator. More tests should come then, likely including SWTBot ones.

The included CallStackStateSystemTest happens to cover CallStackSeries.

Next to cover are LttngUstCallStackAnalysis{Requirement}, followed by
sub-packages classes, still based on Incubator coverage first.

As in Incubator, skip package-info.java for this root package, as it
introduces many Eclipse build errors with the current implementation.

Have CallStackStateSystemTest import o.e.t.a.profiling.core.callstack's
CallStackStateProvider instead of Incubator's, unlike its originating
Incubator counterpart. This is because all is needed for now is this
link from its javadoc.

Change-Id: Ifba4de6f660f6546420063b42d427f912ff79ea9
Signed-off-by: Marco Miller <marco.miller@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/c/tracecompass/org.eclipse.tracecompass/+/199681
Tested-by: Trace Compass Bot <tracecompass-bot@eclipse.org>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
  • Loading branch information
marco-miller committed Mar 31, 2023
1 parent 87026f9 commit eda2ffe
Show file tree
Hide file tree
Showing 11 changed files with 1,219 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,20 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Activator: org.eclipse.tracecompass.analysis.callstack.core.tests.ActivatorTest
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: org.eclipse.tracecompass.analysis.callstack.core.tests
Require-Bundle: org.eclipse.core.runtime,
Require-Bundle: org.eclipse.core.resources,
org.eclipse.core.runtime,
org.eclipse.jdt.annotation;bundle-version="[2.0.0,3.0.0)";resolution:=optional,
org.eclipse.tracecompass.analysis.callstack.core,
org.eclipse.tracecompass.analysis.os.linux.core,
org.eclipse.tracecompass.analysis.profiling.core,
org.eclipse.tracecompass.analysis.timing.core,
org.eclipse.tracecompass.common.core,
org.eclipse.tracecompass.datastore.core,
org.eclipse.tracecompass.segmentstore.core,
org.eclipse.tracecompass.statesystem.core.tests,
org.eclipse.tracecompass.tmf.core,
org.eclipse.tracecompass.tmf.core.tests,
org.junit
Export-Package: org.eclipse.tracecompass.analysis.callstack.core.tests,
org.eclipse.tracecompass.analysis.callstack.core.tests.stubs
Import-Package: com.google.common.collect
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ bin.includes = META-INF/,\
.,\
about.html,\
plugin.properties,\
plugin.xml
plugin.xml,\
testfiles/
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<!-- TODO extension
<extension
point="org.eclipse.linuxtools.tmf.core.analysis">
</extension -->
<module
analysis_module="org.eclipse.tracecompass.analysis.callstack.core.tests.stubs.CallStackAnalysisStub"
id="org.eclipse.tracecompass.analysis.callstack.core.tests.stub"
name="Test Callstack (new)">
<tracetype
class="org.eclipse.tracecompass.tmf.tests.stubs.trace.xml.TmfXmlTraceStub">
</tracetype>
</module>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*******************************************************************************
* Copyright (c) 2017 É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.callstack.core.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;

import java.util.Iterator;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.callstack.core.tests.stubs.CallStackAnalysisStub;
import org.eclipse.tracecompass.segmentstore.core.ISegment;
import org.eclipse.tracecompass.segmentstore.core.ISegmentStore;
import org.junit.Test;

import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;

/**
* Test the callstack analysis as a segment store
*
* @author Geneviève Bastien
*/
public class CallStackSegmentStoreTest extends CallStackTestBase {

/**
* Test the callstack data using the callstack object
*/
@Test
public void testSeriesSegmentStoreIterator() {
CallStackAnalysisStub module = getModule();
assertNotNull(module);

ISegmentStore<@NonNull ISegment> segmentStore = module.getSegmentStore();
assertNotNull(segmentStore);

Iterator<@NonNull ISegment> iterator = segmentStore.iterator();
assertEquals("Segment store iterator count", 18, Iterators.size(iterator));
assertEquals("Segment store size", 18, segmentStore.size());
assertFalse(segmentStore.isEmpty());
}

/**
* Test the segment store's intersecting query methods
*/
@Test
public void testIntersectingSegmentStore() {
CallStackAnalysisStub module = getModule();
assertNotNull(module);

ISegmentStore<@NonNull ISegment> segmentStore = module.getSegmentStore();
assertNotNull(segmentStore);

// Test with some boundaries: all elements that start or end at 10
// should be included
Iterable<@NonNull ISegment> elements = segmentStore.getIntersectingElements(10L);
assertEquals("Intersecting 10", 9, Iterables.size(elements));

elements = segmentStore.getIntersectingElements(10L, 15L);
assertEquals("Between 10 and 15", 12, Iterables.size(elements));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
/*******************************************************************************
* 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.callstack.core.tests;

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 static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.tracecompass.analysis.callstack.core.tests.stubs.CallStackAnalysisStub;
import org.eclipse.tracecompass.analysis.profiling.core.callstack.CallStackStateProvider;
import org.eclipse.tracecompass.internal.analysis.callstack.core.CallStackSeries;
import org.eclipse.tracecompass.internal.analysis.callstack.core.base.ICallStackGroupDescriptor;
import org.eclipse.tracecompass.internal.analysis.callstack.core.instrumented.InstrumentedCallStackAnalysis;
import org.eclipse.tracecompass.internal.analysis.callstack.core.instrumented.InstrumentedGroupDescriptor;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.StateIntervalStub;
import org.eclipse.tracecompass.statesystem.core.tests.shared.utils.StateSystemTestUtils;
import org.junit.Test;

/**
* 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 InstrumentedCallStackAnalysis} and the
* {@link CallStackStateProvider} (o.e.t.a.profiling.core.callstack one for now)
*
* @author Geneviève Bastien
*/
public class CallStackStateSystemTest extends CallStackTestBase {

/**
* 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
ICallStackGroupDescriptor 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
*/
@SuppressWarnings("null")
@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();

// Get the process quarks (first level)
List<Integer> quarks = ss.getQuarks(patterns.get(0));
assertEquals("Number of processes", 2, quarks.size());

for (Integer processQuark : quarks) {
// Get the threads under this process (second level)
List<Integer> threadQuarks = ss.getQuarks(processQuark, patterns.get(1));
switch (ss.getAttributeName(processQuark)) {
case "1":
verifyProcess1(ss, threadQuarks);
break;
case "5":
verifyProcess5(ss, threadQuarks);
break;
default:
fail("Unknown process in callstack");
}
}
}

@SuppressWarnings("null")
private static void verifyProcess1(ITmfStateSystem ss, List<Integer> threadQuarks) throws AttributeNotFoundException {
for (Integer threadQuark : threadQuarks) {
int csQuark = ss.getQuarkRelative(threadQuark, InstrumentedCallStackAnalysis.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");
}
}
}

@SuppressWarnings("null")
private static void verifyProcess5(ITmfStateSystem ss, List<Integer> threadQuarks) throws AttributeNotFoundException {
for (Integer threadQuark : threadQuarks) {
int csQuark = ss.getQuarkRelative(threadQuark, InstrumentedCallStackAnalysis.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");
}
}
}
}
Loading

0 comments on commit eda2ffe

Please sign in to comment.