/******************************************************************************* * Copyright (c) 2015 Ericsson * * 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 *******************************************************************************/ package org.eclipse.tracecompass.analysis.os.linux.core.tests.contextswitch; 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.io.File; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.tracecompass.analysis.os.linux.core.contextswitch.KernelContextSwitchAnalysis; import org.eclipse.tracecompass.analysis.os.linux.core.tests.Activator; import org.eclipse.tracecompass.analysis.os.linux.core.tests.stubs.trace.TmfXmlKernelTraceStub; import org.eclipse.tracecompass.internal.analysis.os.linux.core.kernel.Attributes; import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; import org.eclipse.tracecompass.tmf.core.event.TmfEvent; import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; import org.eclipse.tracecompass.tmf.core.tests.shared.TmfTestHelper; 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; /** * Test suite for the {@link KernelContextSwitchAnalysis} class * * @author Matthew Khouzam */ public class ContextSwitchProviderTest { private static final String CPU_USAGE_FILE = "testfiles/cpu_analysis.xml"; private ITmfTrace fTrace; private KernelContextSwitchAnalysis 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 = new TmfXmlKernelTraceStub(); IPath filePath = Activator.getAbsoluteFilePath(CPU_USAGE_FILE); IStatus status = trace.validate(null, filePath.toOSString()); if (!status.isOK()) { fail(status.getException().getMessage()); } try { trace.initTrace(null, filePath.toOSString(), TmfEvent.class); } catch (TmfTraceException e) { fail(e.getMessage()); } deleteSuppFiles(trace); ((TmfTrace) trace).traceOpened(new TmfTraceOpenedSignal(this, trace, null)); fModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelContextSwitchAnalysis.class, KernelContextSwitchAnalysis.ID); assertNotNull(fModule); fTrace = trace; } /** * Clean up */ @After public void tearDown() { deleteSuppFiles(fTrace); fTrace.dispose(); } /** * Test that the analysis executes without problems */ @Test public void testAnalysisExecution() { /* Make sure the analysis hasn't run yet */ assertNull(fModule.getStateSystem()); /* Execute the analysis */ assertTrue(TmfTestHelper.executeAnalysis(fModule)); assertNotNull(fModule.getStateSystem()); } /** * Test that the state system is returned with the expected results */ @Test public void testReturnedStateSystem() { fModule.schedule(); fModule.waitForCompletion(); ITmfStateSystem ss = fModule.getStateSystem(); assertNotNull(ss); assertEquals(1L, ss.getStartTime()); assertEquals(25L, ss.getCurrentEndTime()); try { int cpusQuark = ss.getQuarkAbsolute(Attributes.CPUS); /* * There should be 2 CPU entries: 0 and 1 and 3 process entries * under each */ List<Integer> cpuQuarks = ss.getSubAttributes(cpusQuark, false); assertEquals(2, cpuQuarks.size()); /* Proc 2 on CPU 0 should run from 1 to 20 seconds */ int proc2Quark = ss.getQuarkAbsolute(Attributes.CPUS, "0"); ITmfStateInterval interval = ss.querySingleState(2L, proc2Quark); assertEquals(1L, interval.getStartTime()); assertEquals(19L, interval.getEndTime()); /* * Query at the end and make sure all processes on all CPU have the * expected values */ List<ITmfStateInterval> state = ss.queryFullState(25L); int quark = ss.getQuarkAbsolute("CPUs", "0"); assertEquals(3L, state.get(quark).getStateValue().unboxLong()); quark = ss.getQuarkAbsolute("CPUs", "1"); assertEquals(5L, state.get(quark).getStateValue().unboxLong()); state = ss.queryFullState(19L); quark = ss.getQuarkAbsolute("CPUs", "0"); assertEquals(1L, state.get(quark).getStateValue().unboxLong()); quark = ss.getQuarkAbsolute("CPUs", "1"); assertEquals(4L, state.get(quark).getStateValue().unboxLong()); } catch (AttributeNotFoundException | StateSystemDisposedException e) { fail(e.getMessage()); } } /** * Test the * {@link KernelContextSwitchAnalysis#getContextSwitchesRange(long, long)} * method. */ @Test public void testUsageInRange() { fModule.schedule(); fModule.waitForCompletion(); /* This range should query the total range */ Map<Integer, Long> expected = new HashMap<>(); expected.put(0, 2L); expected.put(1, 6L); expected.put(-1, 8L); Map<Integer, Long> resultMap = fModule.getContextSwitchesRange(0L, 30L); assertEquals(expected, resultMap); /* Verify a range when a process runs at the start */ expected.clear(); expected.put(0, 1L); expected.put(1, 0L); expected.put(-1, 1L); resultMap = fModule.getContextSwitchesRange(22L, 25L); assertEquals(expected, resultMap); /* Verify a range when a process runs at the end */ expected.clear(); expected.put(0, 0L); expected.put(1, 2L); expected.put(-1, 2L); resultMap = fModule.getContextSwitchesRange(1L, 4L); assertEquals(expected, resultMap); /* Verify a range when a process runs at start and at the end */ expected.clear(); expected.put(0, 0L); expected.put(1, 2L); expected.put(-1, 2L); resultMap = fModule.getContextSwitchesRange(4L, 13L); assertEquals(expected, resultMap); } /** * Test the usage in invalid circumstances */ @Test public void testInvalid() { Map<Integer, Long> resultMap = fModule.getContextSwitchesRange(0L, 30L); assertEquals(Collections.EMPTY_MAP, resultMap); fModule.schedule(); fModule.waitForCompletion(); resultMap = fModule.getContextSwitchesRange(30L, 0L); assertEquals(Collections.EMPTY_MAP, resultMap); resultMap = fModule.getContextSwitchesRange(0L, 0L); assertEquals(Collections.EMPTY_MAP, resultMap); resultMap = fModule.getContextSwitchesRange(-30L, 0L); assertEquals(Collections.EMPTY_MAP, resultMap); } }