blob: 9966d8849d7b4ba31e7ea070549301ac8f97994c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2016 Ericsson
* Copyright (c) 2010, 2011 École Polytechnique de Montréal
* Copyright (c) 2010, 2011 Alexandre Montplaisir <alexandre.montplaisir@gmail.com>
*
* 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.lttng2.kernel.core.tests.analysis.kernel.statesystem;
import static org.eclipse.tracecompass.statesystem.core.ITmfStateSystem.INVALID_ATTRIBUTE;
import static org.eclipse.tracecompass.statesystem.core.ITmfStateSystem.ROOT_ATTRIBUTE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.statesystem.core.StateSystemUtils;
import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException;
import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
/**
* Base unit tests for the StateHistorySystem. Extension can be made to test
* different state back-end types or configurations.
*
* @author Alexandre Montplaisir
*/
@SuppressWarnings("javadoc")
public abstract class StateSystemTest {
/** Timeout the tests after 2 minutes */
@Rule
public TestRule timeoutRule = new Timeout(2, TimeUnit.MINUTES);
/** Test trace used for these tests */
protected static final @NonNull CtfTestTrace testTrace = CtfTestTrace.TRACE2;
/** Expected start time of the test trace/state history */
protected static final long startTime = 1331668247314038062L;
/** Expected end time of the state history built from the test trace */
protected static final long endTime = 1331668259054285979L;
/** Offset in the trace + start time of the trace */
protected static final long interestingTimestamp1 = 18670067372290L + 1331649577946812237L;
/** Number of nanoseconds in one second */
private static final long NANOSECS_PER_SEC = 1000000000L;
protected static ITmfStateSystem fixture;
/**
* Test set-up
*/
@Before
public void setUp() {
/* Subclasses should set-up 'fixture' */
assertNotNull(fixture);
}
@Test
public void testFullQuery1() {
List<ITmfStateInterval> list;
ITmfStateInterval interval;
int quark, valueInt;
String valueStr;
try {
list = fixture.queryFullState(interestingTimestamp1);
quark = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
interval = list.get(quark);
valueInt = interval.getStateValue().unboxInt();
assertEquals(1397, valueInt);
quark = fixture.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME);
interval = list.get(quark);
valueStr = interval.getStateValue().unboxStr();
assertEquals("gdbus", valueStr);
quark = fixture.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.SYSTEM_CALL);
interval = list.get(quark);
valueStr = interval.getStateValue().unboxStr();
assertEquals("poll", valueStr);
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
@Test
public void testSingleQuery1() {
long timestamp = interestingTimestamp1;
int quark;
ITmfStateInterval interval;
String valueStr;
try {
quark = fixture.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME);
interval = fixture.querySingleState(timestamp, quark);
valueStr = interval.getStateValue().unboxStr();
assertEquals("gdbus", valueStr);
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
/**
* Test a range query (with no resolution parameter, so all intervals)
*/
@Test
public void testRangeQuery1() {
long time1 = interestingTimestamp1;
long time2 = time1 + 1L * NANOSECS_PER_SEC;
int quark;
List<ITmfStateInterval> intervals;
final ITmfStateSystem ss = fixture;
assertNotNull(ss);
try {
quark = ss.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
intervals = StateSystemUtils.queryHistoryRange(ss, quark, time1, time2);
assertEquals(487, intervals.size()); /* Number of context switches! */
assertEquals(1685, intervals.get(100).getStateValue().unboxInt());
assertEquals(1331668248427681372L, intervals.get(205).getEndTime());
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
/**
* Range query, but with a t2 far off the end of the trace. The result
* should still be valid.
*/
@Test
public void testRangeQuery2() {
List<ITmfStateInterval> intervals;
final ITmfStateSystem ss = fixture;
assertNotNull(ss);
try {
int quark = ss.getQuarkAbsolute(Attributes.CPUS, Integer.toString(0), Attributes.IRQS, "1");
long ts1 = ss.getStartTime(); /* start of the trace */
long ts2 = startTime + 20L * NANOSECS_PER_SEC; /* invalid, but ignored */
intervals = StateSystemUtils.queryHistoryRange(ss, quark, ts1, ts2);
/* Activity of IRQ 1 over the whole trace */
assertEquals(65, intervals.size());
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
/**
* Test a range query with a resolution
*/
@Test
public void testRangeQuery3() {
long time1 = interestingTimestamp1;
long time2 = time1 + 1L * NANOSECS_PER_SEC;
long resolution = 1000000; /* One query every millisecond */
int quark;
List<ITmfStateInterval> intervals;
final ITmfStateSystem ss = fixture;
assertNotNull(ss);
try {
quark = ss.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
intervals = StateSystemUtils.queryHistoryRange(ss, quark, time1, time2, resolution, null);
assertEquals(126, intervals.size()); /* Number of context switches! */
assertEquals(1452, intervals.get(50).getStateValue().unboxInt());
assertEquals(1331668248815698779L, intervals.get(100).getEndTime());
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
/**
* Ask for a time range outside of the trace's range
*/
@Test(expected = TimeRangeException.class)
public void testFullQueryInvalidTime1() throws TimeRangeException,
StateSystemDisposedException {
long ts = startTime + 20L * NANOSECS_PER_SEC;
fixture.queryFullState(ts);
}
@Test(expected = TimeRangeException.class)
public void testFullQueryInvalidTime2() throws TimeRangeException,
StateSystemDisposedException {
long ts = startTime - 20L * NANOSECS_PER_SEC;
fixture.queryFullState(ts);
}
@Test(expected = TimeRangeException.class)
public void testSingleQueryInvalidTime1() throws TimeRangeException {
try {
int quark = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
long ts = startTime + 20L * NANOSECS_PER_SEC;
fixture.querySingleState(ts, quark);
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
@Test(expected = TimeRangeException.class)
public void testSingleQueryInvalidTime2() throws TimeRangeException {
try {
int quark = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
long ts = startTime - 20L * NANOSECS_PER_SEC;
fixture.querySingleState(ts, quark);
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
@Test(expected = TimeRangeException.class)
public void testRangeQueryInvalidTime1() throws TimeRangeException {
final ITmfStateSystem ss = fixture;
assertNotNull(ss);
try {
int quark = ss.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
long ts1 = startTime - 20L * NANOSECS_PER_SEC; /* invalid */
long ts2 = startTime + 1L * NANOSECS_PER_SEC; /* valid */
StateSystemUtils.queryHistoryRange(ss, quark, ts1, ts2);
} catch (AttributeNotFoundException e) {
fail();
} catch (StateSystemDisposedException e) {
fail();
}
}
@Test(expected = TimeRangeException.class)
public void testRangeQueryInvalidTime2() throws TimeRangeException {
final ITmfStateSystem ss = fixture;
assertNotNull(ss);
try {
int quark = ss.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
long ts1 = startTime - 1L * NANOSECS_PER_SEC; /* invalid */
long ts2 = startTime + 20L * NANOSECS_PER_SEC; /* invalid */
StateSystemUtils.queryHistoryRange(ss, quark, ts1, ts2);
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
/**
* Ask for a non-existing attribute
*
* @throws AttributeNotFoundException
*/
@Test(expected = AttributeNotFoundException.class)
public void testQueryInvalidAttribute() throws AttributeNotFoundException {
fixture.getQuarkAbsolute("There", "is", "no", "cow", "level");
}
/**
* Query but with the wrong State Value type
*/
@Test(expected = StateValueTypeException.class)
public void testQueryInvalidValuetype1() throws StateValueTypeException {
List<ITmfStateInterval> list;
ITmfStateInterval interval;
int quark;
try {
list = fixture.queryFullState(interestingTimestamp1);
quark = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
interval = list.get(quark);
/* This is supposed to be an int value */
interval.getStateValue().unboxStr();
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
@Test(expected = StateValueTypeException.class)
public void testQueryInvalidValuetype2() throws StateValueTypeException {
List<ITmfStateInterval> list;
ITmfStateInterval interval;
int quark;
try {
list = fixture.queryFullState(interestingTimestamp1);
quark = fixture.getQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME);
interval = list.get(quark);
/* This is supposed to be a String value */
interval.getStateValue().unboxInt();
} catch (AttributeNotFoundException | StateSystemDisposedException e) {
fail();
}
}
@Test
public void testOptQuarkAbsolute() {
int quark = fixture.optQuarkAbsolute();
assertEquals(ROOT_ATTRIBUTE, quark);
quark = fixture.optQuarkAbsolute(Attributes.THREADS, "1432", Attributes.EXEC_NAME);
assertNotEquals(INVALID_ATTRIBUTE, quark);
assertEquals(Attributes.EXEC_NAME, fixture.getAttributeName(quark));
quark = fixture.optQuarkAbsolute(Attributes.THREADS, "1432", "absent");
assertEquals(INVALID_ATTRIBUTE, quark);
quark = fixture.optQuarkAbsolute(Attributes.THREADS, "absent", Attributes.EXEC_NAME);
assertEquals(INVALID_ATTRIBUTE, quark);
quark = fixture.optQuarkAbsolute("absent", "1432", Attributes.EXEC_NAME);
assertEquals(INVALID_ATTRIBUTE, quark);
}
@Test
public void testOptQuarkRelative() {
int threadsQuark = INVALID_ATTRIBUTE;
try {
threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
} catch (AttributeNotFoundException e) {
fail();
}
assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
int quark = fixture.optQuarkRelative(threadsQuark);
assertEquals(threadsQuark, quark);
quark = fixture.optQuarkRelative(threadsQuark, "1432", Attributes.EXEC_NAME);
assertNotEquals(INVALID_ATTRIBUTE, quark);
assertEquals(Attributes.EXEC_NAME, fixture.getAttributeName(quark));
quark = fixture.optQuarkRelative(threadsQuark, "1432", "absent");
assertEquals(INVALID_ATTRIBUTE, quark);
quark = fixture.optQuarkRelative(threadsQuark, "absent", Attributes.EXEC_NAME);
assertEquals(INVALID_ATTRIBUTE, quark);
}
@Test
public void testFullAttributeName() {
try {
int quark = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
String name = fixture.getFullAttributePath(quark);
assertEquals(name, "CPUs/0/Current_thread");
} catch (AttributeNotFoundException e) {
fail();
}
}
@Test
public void testGetQuarks_begin() {
List<Integer> list = fixture.getQuarks("*", "1577", Attributes.EXEC_NAME);
assertEquals(1, list.size());
}
@Test
public void testGetQuarks_middle() {
List<Integer> list = fixture.getQuarks(Attributes.THREADS, "*", Attributes.EXEC_NAME);
/* Number of different kernel threads in the trace */
assertEquals(169, list.size());
}
@Test
public void testGetQuarks_end() {
List<Integer> list = fixture.getQuarks(Attributes.THREADS, "1577", "*");
/* There should be 4 sub-attributes for this Thread node */
assertEquals(4, list.size());
}
@Test
public void testGetQuarks_middle_end() {
List<Integer> list = fixture.getQuarks(Attributes.THREADS, "*", "*");
/* There should be 716 attributes as not all have a system call or priority at this point*/
assertEquals(716, list.size());
}
@Test
public void testGetQuarks_empty() {
List<Integer> list = fixture.getQuarks();
assertEquals(Arrays.asList(ITmfStateSystem.ROOT_ATTRIBUTE), list);
}
@Test
public void testGetQuarks_relative() {
int threadsQuark = INVALID_ATTRIBUTE;
try {
threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
} catch (AttributeNotFoundException e) {
fail();
}
assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
List<Integer> list = fixture.getQuarks(threadsQuark, "*", Attributes.EXEC_NAME);
/* Number of different kernel threads in the trace */
assertEquals(169, list.size());
}
@Test
public void testGetQuarks_relative_up_wildcard() {
int threadsQuark = INVALID_ATTRIBUTE;
try {
threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
} catch (AttributeNotFoundException e) {
fail();
}
assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
List<Integer> list = fixture.getQuarks(threadsQuark, "..", Attributes.CPUS, "*");
/* There should be 2 CPUs */
assertEquals(2, list.size());
}
@Test
public void testGetQuarks_relative_empty() {
int threadsQuark = INVALID_ATTRIBUTE;
try {
threadsQuark = fixture.getQuarkAbsolute(Attributes.THREADS);
} catch (AttributeNotFoundException e) {
fail();
}
assertNotEquals(INVALID_ATTRIBUTE, threadsQuark);
List<Integer> list = fixture.getQuarks(threadsQuark, new String[0]);
assertEquals(Arrays.asList(threadsQuark), list);
list = fixture.getQuarks(threadsQuark);
assertEquals(Arrays.asList(threadsQuark), list);
}
@Test
public void testGetQuarksNoMatch() {
List<Integer> list = fixture.getQuarks("invalid");
assertEquals(0, list.size());
list = fixture.getQuarks("*", "invalid");
assertEquals(0, list.size());
list = fixture.getQuarks("invalid", "*");
assertEquals(0, list.size());
list = fixture.getQuarks(Attributes.THREADS, "*", "invalid");
assertEquals(0, list.size());
}
// ------------------------------------------------------------------------
// Tests verifying the *complete* results of a full queries
// ------------------------------------------------------------------------
protected long getStartTimes(int idx) {
return TestValues.startTimes[idx];
}
protected long getEndTimes(int idx) {
return TestValues.endTimes[idx];
}
protected ITmfStateValue getStateValues(int idx) {
return TestValues.values[idx];
}
@Test
public void testFullQueryThorough() {
try {
List<ITmfStateInterval> state = fixture.queryFullState(interestingTimestamp1);
assertEquals(TestValues.size, state.size());
for (int i = 0; i < state.size(); i++) {
/* Test each component of the intervals */
assertEquals(getStartTimes(i), state.get(i).getStartTime());
assertEquals(getEndTimes(i), state.get(i).getEndTime());
assertEquals(i, state.get(i).getAttribute());
assertEquals(getStateValues(i), state.get(i).getStateValue());
}
} catch (StateSystemDisposedException e) {
fail();
}
}
@Test
public void testFirstIntervalIsConsidered() {
try {
int quark = fixture.getQuarkAbsolute(Attributes.THREADS, "1397");
List<ITmfStateInterval> list = fixture.queryFullState(1331668248014135800L);
ITmfStateInterval interval = list.get(quark);
assertEquals(1331668247516664825L, interval.getStartTime());
int valueInt = interval.getStateValue().unboxInt();
assertEquals(1, valueInt);
} catch (StateSystemDisposedException | AttributeNotFoundException e) {
fail();
}
}
@Test
public void testParentAttribute() {
String[] path = { "CPUs/0/Current_thread",
"CPUs/0",
"CPUs" };
try {
int q = fixture.getQuarkAbsolute(Attributes.CPUS, "0", Attributes.CURRENT_THREAD);
for (int i = 0; i < path.length; i++) {
String name = fixture.getFullAttributePath(q);
assertEquals(path[i], name);
q = fixture.getParentAttributeQuark(q);
}
assertEquals(ROOT_ATTRIBUTE, q);
q = fixture.getParentAttributeQuark(q);
assertEquals(ROOT_ATTRIBUTE, q);
} catch (AttributeNotFoundException e) {
fail();
}
}
}