/*******************************************************************************
* Copyright (c) 2014, 2015 É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
*
* Contributors:
* Geneviève Bastien - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.analysis.os.linux.core.tests.kernel;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
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.io.File;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelThreadInformationProvider;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.StateValues;
import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.LinuxTestCase;
import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.kernel.KernelAnalysisTestFactory;
import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.ImmutableSet;
/**
* Test analysis-specific methods for the {@link KernelAnalysisModule} class.
*
* @author Geneviève Bastien
*/
public class KernelThreadInformationProviderTest {
private static final @NonNull LinuxTestCase KERNEL_TEST_CASE = KernelAnalysisTestFactory.KERNEL_SCHED;
private ITmfTrace fTrace;
private KernelAnalysisModule fModule;
private static void deleteSuppFiles(ITmfTrace trace) {
/* Remove supplementary files */
File suppDir = new File(TmfTraceManager.getSupplementaryFileDir(trace));
for (File file : suppDir.listFiles()) {
file.delete();
}
}
/**
* Setup the trace for the tests
*/
@Before
public void setUp() {
ITmfTrace trace = KERNEL_TEST_CASE.getKernelTrace();
deleteSuppFiles(trace);
((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null));
IAnalysisModule module = null;
for (IAnalysisModule mod : TmfTraceUtils.getAnalysisModulesOfClass(trace, KernelAnalysisModule.class)) {
module = mod;
}
assertNotNull(module);
module.schedule();
module.waitForCompletion();
fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelAnalysisModule.class, KernelAnalysisModule.ID);
fTrace = trace;
}
/**
* Clean up
*/
@After
public void tearDown() {
deleteSuppFiles(fTrace);
fTrace.dispose();
}
/**
* Test the
* {@link KernelThreadInformationProvider#getThreadIds(KernelAnalysisModule)}
* method
*/
@Test
public void testGetThreadQuarks() {
KernelAnalysisModule module = checkNotNull(fModule);
Collection<Integer> threadIds = KernelThreadInformationProvider.getThreadIds(module);
assertEquals(ImmutableSet.<Integer>of(10,11,20,21,30,100), threadIds);
}
/**
* Test the
* {@link KernelThreadInformationProvider#getThreadOnCpu(KernelAnalysisModule, long, long)}
* method
*/
@Test
public void testGetThreadOnCpu() {
KernelAnalysisModule module = checkNotNull(fModule);
/* Check with invalid timestamps */
Integer tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, -1);
assertNull(tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 90);
assertNull(tid);
/* Check with invalid cpus */
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 2, 20);
assertNull(tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, -1, 20);
assertNull(tid);
/* Check valid values */
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 4);
assertNull(tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 15);
assertNull(tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 15);
assertEquals(Integer.valueOf(11), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 29);
assertEquals(Integer.valueOf(20), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 30);
assertEquals(Integer.valueOf(21), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 59);
assertEquals(Integer.valueOf(11), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 59);
assertEquals(Integer.valueOf(30), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 0, 60);
assertEquals(Integer.valueOf(11), tid);
tid = KernelThreadInformationProvider.getThreadOnCpu(module, 1, 60);
assertEquals(Integer.valueOf(21), tid);
}
/**
* Test the
* {@link KernelThreadInformationProvider#getParentPid(KernelAnalysisModule, Integer, long)}
* method
*/
@Test
public void testGetPpid() {
KernelAnalysisModule module = checkNotNull(fModule);
/* Check with invalid timestamps */
Integer ppid = KernelThreadInformationProvider.getParentPid(module, 11, -1);
assertNull(ppid);
ppid = KernelThreadInformationProvider.getParentPid(module, 11, 90);
assertNull(ppid);
/* Check with invalid cpus */
ppid = KernelThreadInformationProvider.getParentPid(module, -4, 20);
assertNull(ppid);
ppid = KernelThreadInformationProvider.getParentPid(module, 12, 20);
assertNull(ppid);
/* Check values with no parent */
ppid = KernelThreadInformationProvider.getParentPid(module, 10, 20);
assertEquals(Integer.valueOf(0), ppid);
ppid = KernelThreadInformationProvider.getParentPid(module, 30, 60);
assertEquals(Integer.valueOf(0), ppid);
/* Check parent determined at statedump */
ppid = KernelThreadInformationProvider.getParentPid(module, 11, 4);
assertNull(ppid);
ppid = KernelThreadInformationProvider.getParentPid(module, 11, 5);
assertEquals(Integer.valueOf(10), ppid);
/* Check parent after process fork */
ppid = KernelThreadInformationProvider.getParentPid(module, 21, 25);
assertEquals(Integer.valueOf(20), ppid);
ppid = KernelThreadInformationProvider.getParentPid(module, 21, 70);
assertEquals(Integer.valueOf(20), ppid);
}
/**
* Test the {@link KernelThreadInformationProvider#getExecutableName(KernelAnalysisModule, Integer)} method
*/
@Test
public void testGetExecutableName() {
KernelAnalysisModule module = checkNotNull(fModule);
/* Check with invalid threads */
String execName = KernelThreadInformationProvider.getExecutableName(module, 101);
assertNull(execName);
execName = KernelThreadInformationProvider.getExecutableName(module, -2);
assertNull(execName);
/* Check valid value */
execName = KernelThreadInformationProvider.getExecutableName(module, 20);
assertEquals("proc20", execName);
/* Check valid value with process name change in history */
execName = KernelThreadInformationProvider.getExecutableName(module, 21);
assertEquals("proc21", execName);
}
private static void testIntervals(String info, List<ITmfStateInterval> intervals, ITmfStateValue[] values) {
assertEquals(info + " interval count", values.length, intervals.size());
for (int i = 0; i < values.length; i++) {
assertEquals(info + " interval " + i, values[i], intervals.get(i).getStateValue());
}
}
/**
* Test the
* {@link KernelThreadInformationProvider#getStatusIntervalsForThread(KernelAnalysisModule, Integer, long, long, long, IProgressMonitor)}
* method
*/
@Test
public void testGetStatusIntervalsForThread() {
KernelAnalysisModule module = checkNotNull(fModule);
IProgressMonitor monitor = new NullProgressMonitor();
Integer process21 = 21;
Integer process20 = 20;
/* Check invalid time ranges */
List<ITmfStateInterval> intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, -15, -5, 3, monitor);
assertTrue(intervals.isEmpty());
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 90, 1500000000L, 50, monitor);
assertTrue(intervals.isEmpty());
/* Check invalid quarks */
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, -1, 0, 70L, 3, monitor);
assertTrue(intervals.isEmpty());
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, 0, 0, 70L, 3, monitor);
assertTrue(intervals.isEmpty());
/* Check different time ranges and resolutions */
ITmfStateValue[] values = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE,
StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE,
StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 0, 70L, 3, monitor);
testIntervals("tid 21 [0,70,3]", intervals, values);
ITmfStateValue[] values2 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE,
StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 1, 70L, 30, monitor);
testIntervals("tid 21 [0,70,30]", intervals, values2);
ITmfStateValue[] values3 = { StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE,
StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process21, 25, 50L, 3, monitor);
testIntervals("tid 21 [25,50,3]", intervals, values3);
ITmfStateValue[] values4 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_UNKNOWN_VALUE,
StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE, StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 0, 70L, 3, monitor);
testIntervals("tid 20 [0,70,3]", intervals, values4);
ITmfStateValue[] values5 = { TmfStateValue.nullValue(), StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 1, 70L, 30, monitor);
testIntervals("tid 20 [0,70,30]", intervals, values5);
ITmfStateValue[] values6 = { StateValues.PROCESS_STATUS_RUN_USERMODE_VALUE,
StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 25, 50L, 3, monitor);
testIntervals("tid 20 [25,50,3]", intervals, values6);
ITmfStateValue[] values7 = { StateValues.PROCESS_STATUS_WAIT_FOR_CPU_VALUE };
intervals = KernelThreadInformationProvider.getStatusIntervalsForThread(module, process20, 80L, 85L, 3, monitor);
testIntervals("tid 20 [80,85,3]", intervals, values7);
}
}