blob: 984342499741ce328011cc9a2a1cc75ac0123109 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Ericsson
*
* 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.os.linux.core.tests.kernel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.analysis.os.linux.core.kernel.KernelAnalysisModule;
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.threadstatus.ThreadEntryModel;
import org.eclipse.tracecompass.internal.analysis.os.linux.core.threadstatus.ThreadStatusDataProvider;
import org.eclipse.tracecompass.internal.tmf.core.model.filters.FetchParametersUtils;
import org.eclipse.tracecompass.tmf.core.event.TmfEvent;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
import org.eclipse.tracecompass.tmf.core.model.OutputElementStyle;
import org.eclipse.tracecompass.tmf.core.model.filters.SelectionTimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.filters.TimeQueryFilter;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphArrow;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphRowModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphState;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphEntryModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.TimeGraphModel;
import org.eclipse.tracecompass.tmf.core.model.tree.TmfTreeModel;
import org.eclipse.tracecompass.tmf.core.response.ITmfResponse;
import org.eclipse.tracecompass.tmf.core.response.TmfModelResponse;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
import org.junit.Test;
/**
* {@link ThreadStatusDataProvider} test
*
* @author Loic Prieur-Drevon
*/
public class ThreadStatusDataProviderTest {
private static final String KERNEL_ANALYSIS = "testfiles/kernel_analysis/lttng_kernel_analysis.xml";
/**
* Test the {@link ThreadStatusDataProvider} for the XML kernel test trace
*
* @throws TmfTraceException
* If we couldn't open the trace
* @throws IOException
* if an I/O error occurs reading from the expected value file or a
* malformed or unmappable byte sequence is read
*/
@Test
public void testThreadStatusDataProvider() throws TmfTraceException, IOException {
TmfXmlKernelTraceStub trace = new TmfXmlKernelTraceStub();
try {
IPath filePath = Activator.getAbsoluteFilePath(KERNEL_ANALYSIS);
trace.initTrace(null, filePath.toOSString(), TmfEvent.class);
trace.traceOpened(new TmfTraceOpenedSignal(this, trace, null));
KernelAnalysisModule module = TmfTraceUtils.getAnalysisModuleOfClass(trace, KernelAnalysisModule.class, KernelAnalysisModule.ID);
assertNotNull(module);
assertTrue(module.schedule().isOK());
assertTrue(module.waitForCompletion());
ThreadStatusDataProvider provider = new ThreadStatusDataProvider(trace, module);
Map<Long, String> idsToNames = assertAndGetTree(provider);
assertRows(provider, idsToNames);
assertArrows(provider, idsToNames);
} finally {
trace.dispose();
}
}
private static Map<Long, String> assertAndGetTree(ThreadStatusDataProvider provider) throws IOException {
TmfModelResponse<TmfTreeModel<@NonNull TimeGraphEntryModel>> treeResponse = provider.fetchTree(FetchParametersUtils.timeQueryToMap(new TimeQueryFilter(0, Long.MAX_VALUE, 2)), null);
assertNotNull(treeResponse);
assertEquals(ITmfResponse.Status.COMPLETED, treeResponse.getStatus());
TmfTreeModel<@NonNull TimeGraphEntryModel> treeModel = treeResponse.getModel();
assertNotNull(treeModel);
List<@NonNull TimeGraphEntryModel> treeEntries = treeModel.getEntries();
List<String> expectedStrings = Files.readAllLines(Paths.get("testfiles/kernel_analysis/expectedThreadStatusTree"));
assertEquals(expectedStrings.size(), treeEntries.size());
for (int i = 0; i < expectedStrings.size(); i++) {
String expectedString = expectedStrings.get(i);
String[] split = expectedString.split(",");
TimeGraphEntryModel threadEntry = treeEntries.get(i);
// Assert common fields
assertEquals(split[0], threadEntry.getName());
assertEquals(Long.parseLong(split[1]), threadEntry.getStartTime());
assertEquals(Long.parseLong(split[2]), threadEntry.getEndTime());
if (threadEntry instanceof ThreadEntryModel) {
// Verify the thread entry fields
ThreadEntryModel threadEntryModel = (ThreadEntryModel) threadEntry;
assertEquals(Integer.parseInt(split[3]), threadEntryModel.getThreadId());
assertEquals(Integer.parseInt(split[4]), threadEntryModel.getProcessId());
assertEquals(Integer.parseInt(split[5]), threadEntryModel.getParentThreadId());
} else {
// Make sure there is no extra expected fields
assertEquals(3, split.length);
}
}
Map<Long, String> map = new HashMap<>();
for (TimeGraphEntryModel threadModel : treeEntries) {
map.put(threadModel.getId(), threadModel.getName());
}
return map;
}
private static void assertRows(ThreadStatusDataProvider provider, Map<Long, String> idsToNames) throws IOException {
TmfModelResponse<TimeGraphModel> rowResponse = provider.fetchRowModel(FetchParametersUtils.selectionTimeQueryToMap(new SelectionTimeQueryFilter(1, 80, 80, idsToNames.keySet())), null);
assertNotNull(rowResponse);
assertEquals(ITmfResponse.Status.COMPLETED, rowResponse.getStatus());
TimeGraphModel rowModel = rowResponse.getModel();
assertNotNull(rowModel);
List<@NonNull ITimeGraphRowModel> rows = rowModel.getRows();
// ensure row order
rows.sort(Comparator.comparingLong(ITimeGraphRowModel::getEntryID));
List<String> expectedStrings = Files.readAllLines(Paths.get("testfiles/kernel_analysis/expectedThreadStatusRows"));
assertEquals(expectedStrings.size(), rows.size());
for (int i = 0; i < expectedStrings.size(); i++) {
String expectedString = expectedStrings.get(i);
String[] split = expectedString.split(":");
ITimeGraphRowModel row = rows.get(i);
assertEquals(split[0], idsToNames.get(row.getEntryID()));
assertEqualsStates(split[1], row.getStates(), split[0]);
}
}
private static void assertEqualsStates(String string, @NonNull List<@NonNull ITimeGraphState> states, String element) {
String[] stringStates = string.split(",");
for (int i = 0; i < stringStates.length / 4; i++) {
ITimeGraphState state = states.get(i);
assertEquals(element + ": start time at position " + i, Long.parseLong(stringStates[i * 4]), state.getStartTime());
assertEquals(element + ": duration at position " + i, Long.parseLong(stringStates[i * 4 + 1]), state.getDuration());
OutputElementStyle style = state.getStyle();
if (style == null) {
// Expected a value of Long
try {
assertEquals(element + ": value at position " + i, Long.parseLong(stringStates[i * 4 + 2]), state.getValue());
} catch (NumberFormatException e) {
fail(element + ": value at position " + i + ": did not expect a null style");
}
} else {
assertEquals(element + ": value at position " + i, stringStates[i * 4 + 2], style.getParentKey());
}
assertEquals(element + ": label at position " + i, stringStates[i * 4 + 3], String.valueOf(state.getLabel()));
}
}
private static void assertArrows(ThreadStatusDataProvider provider, Map<Long, String> idsToNames) throws IOException {
TmfModelResponse<List<ITimeGraphArrow>> arrowResponse = provider.fetchArrows(FetchParametersUtils.timeQueryToMap(new TimeQueryFilter(1, 80, 80)), null);
assertNotNull(arrowResponse);
assertEquals(ITmfResponse.Status.COMPLETED, arrowResponse.getStatus());
List<ITimeGraphArrow> arrows = arrowResponse.getModel();
assertNotNull(arrows);
List<String> expectedStrings = Files.readAllLines(Paths.get("testfiles/kernel_analysis/expectedThreadStatusArrows"));
assertEquals(expectedStrings.size(), arrows.size());
for (int i = 0; i < expectedStrings.size(); i++) {
String expectedString = expectedStrings.get(i);
String[] split = expectedString.split(",");
ITimeGraphArrow arrow = arrows.get(i);
assertEquals(split[0], idsToNames.get(arrow.getSourceId()));
assertEquals(split[1], idsToNames.get(arrow.getDestinationId()));
assertEquals(Long.parseLong(split[2]), arrow.getStartTime());
assertEquals(Long.parseLong(split[3]), arrow.getDuration());
}
}
}