blob: e1582b80623ab8024cf43c30e63a34d3c6bd4e85 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 EfficiOS Inc., Alexandre Montplaisir
*
* 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.ust.core.tests.analysis.debuginfo;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoAnalysisModule;
import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryAspect;
import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoBinaryFile;
import org.eclipse.tracecompass.lttng2.ust.core.analysis.debuginfo.UstDebugInfoLoadedBinaryFile;
import org.eclipse.tracecompass.lttng2.ust.core.tests.shared.LttngUstTestTraceUtils;
import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstEvent;
import org.eclipse.tracecompass.lttng2.ust.core.trace.LttngUstTrace;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType;
import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
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.Iterables;
import com.google.common.collect.Lists;
/**
* Tests for the {@link UstDebugInfoAnalysisModule}
*
* @author Alexandre Montplaisir
*/
public class UstDebugInfoAnalysisModuleTest {
private static final @NonNull CtfTestTrace REAL_TEST_TRACE = CtfTestTrace.DEBUG_INFO4;
private static final @NonNull CtfTestTrace SYNTH_EXEC_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_EXEC;
private static final @NonNull CtfTestTrace SYNTH_TWO_PROCESSES_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_TWO_PROCESSES;
private static final @NonNull CtfTestTrace SYNTH_BUILDID_DEBUGLINK_TRACE = CtfTestTrace.DEBUG_INFO_SYNTH_BUILDID_DEBUGLINK;
private static final @NonNull CtfTestTrace INVALID_TRACE = CtfTestTrace.CYG_PROFILE;
private UstDebugInfoAnalysisModule fModule;
/**
* Test setup
*/
@Before
public void setup() {
fModule = new UstDebugInfoAnalysisModule();
}
/**
* Test cleanup
*/
@After
public void tearDown() {
fModule.dispose();
fModule = null;
}
/**
* Test for {@link UstDebugInfoAnalysisModule#getAnalysisRequirements()}
*/
@Test
public void testGetAnalysisRequirements() {
Iterable<TmfAbstractAnalysisRequirement> requirements = fModule.getAnalysisRequirements();
assertNotNull(requirements);
assertTrue(Iterables.isEmpty(requirements));
}
/**
* Test that the analysis can execute on a valid trace.
*/
@Test
public void testCanExecute() {
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(REAL_TEST_TRACE);
assertTrue(fModule.canExecute(trace));
LttngUstTestTraceUtils.dispose(REAL_TEST_TRACE);
}
/**
* Test that the analysis correctly refuses to execute on an invalid trace
* (LTTng-UST < 2.8 in this case).
*/
@Test
public void testCannotExcecute() {
LttngUstTrace invalidTrace = LttngUstTestTraceUtils.getTrace(INVALID_TRACE);
assertFalse(fModule.canExecute(invalidTrace));
LttngUstTestTraceUtils.dispose(INVALID_TRACE);
}
private void executeModule(ITmfTrace trace) {
assertNotNull(trace);
try {
fModule.setTrace(trace);
} catch (TmfAnalysisException e) {
fail();
}
fModule.schedule();
fModule.waitForCompletion();
}
/**
* Test that basic execution of the module works well.
*/
@Test
public void testExecution() {
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(REAL_TEST_TRACE);
executeModule(trace);
ITmfStateSystem ss = fModule.getStateSystem();
assertNotNull(ss);
LttngUstTestTraceUtils.dispose(REAL_TEST_TRACE);
}
/**
* Test that the binary callsite aspect resolves correctly for some
* user-defined tracepoints in the trace.
*
* These should be available even without the binaries with debug symbols
* being present on the system.
*/
@Test
public void testBinaryCallsites() {
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(REAL_TEST_TRACE);
/*
* Fake a "trace opened" signal, so that the relevant analyses are
* started.
*/
TmfTraceOpenedSignal signal = new TmfTraceOpenedSignal(this, trace, null);
TmfSignalManager.dispatchSignal(signal);
UstDebugInfoAnalysisModule module = TmfTraceUtils.getAnalysisModuleOfClass(trace, UstDebugInfoAnalysisModule.class, UstDebugInfoAnalysisModule.ID);
assertNotNull(module);
module.waitForCompletion();
/* Send a request to get the 3 events we are interested in */
List<@NonNull LttngUstEvent> events = new ArrayList<>();
TmfEventRequest request = new TmfEventRequest(LttngUstEvent.class, 31, 1, ExecutionType.FOREGROUND) {
@Override
public void handleData(ITmfEvent event) {
super.handleData(event);
events.add((LttngUstEvent) event);
}
};
trace.sendRequest(request);
try {
request.waitForCompletion();
} catch (InterruptedException e) {
fail(e.getMessage());
}
/* Tests that the aspects are resolved correctly */
final UstDebugInfoBinaryAspect aspect = UstDebugInfoBinaryAspect.INSTANCE;
String actual = checkNotNull(aspect.resolve(events.get(0))).toString();
String expected = "/home/simark/src/babeltrace/tests/debug-info-data/libhello_so+0x14d4";
assertEquals(expected, actual);
LttngUstTestTraceUtils.dispose(REAL_TEST_TRACE);
}
/**
* Test the analysis with a test trace doing an "exec" system call.
*/
@Test
public void testExec() {
UstDebugInfoLoadedBinaryFile matchingFile, expected;
int vpid = 1337;
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(SYNTH_EXEC_TRACE);
executeModule(trace);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo", null, null, false);
matchingFile = fModule.getMatchingFile(4000000, vpid, 0x400100);
assertEquals(expected, matchingFile);
expected = null;
matchingFile = fModule.getMatchingFile(8000000, vpid, 0x400100);
assertEquals(expected, matchingFile);
expected = new UstDebugInfoLoadedBinaryFile(0x500000, "/tmp/bar", null, null, false);
matchingFile = fModule.getMatchingFile(9000000, vpid, 0x500100);
assertEquals(expected, matchingFile);
LttngUstTestTraceUtils.dispose(SYNTH_EXEC_TRACE);
}
/**
* Test the analysis with a test trace with two processes doing a statedump
* simultaneously.
*/
@Test
public void testTwoProcesses() {
UstDebugInfoLoadedBinaryFile matchingFile, expected;
int vpid1 = 1337;
int vpid2 = 2001;
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(SYNTH_TWO_PROCESSES_TRACE);
executeModule(trace);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "/tmp/debuglink1", false);
matchingFile = fModule.getMatchingFile(11000000, vpid1, 0x400100);
assertEquals(expected, matchingFile);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/bar", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "/tmp/debuglink2", false);
matchingFile = fModule.getMatchingFile(12000000, vpid2, 0x400100);
assertEquals(expected, matchingFile);
LttngUstTestTraceUtils.dispose(SYNTH_TWO_PROCESSES_TRACE);
}
/**
* Test the analysis with a trace with debug_link information.
*/
@Test
public void testBuildIDDebugLink() {
UstDebugInfoLoadedBinaryFile matchingFile, expected;
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(SYNTH_BUILDID_DEBUGLINK_TRACE);
executeModule(trace);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_nn", null, null, false);
matchingFile = fModule.getMatchingFile(17000000, 1337, 0x400100);
assertEquals(expected, matchingFile);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_yn", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", null, false);
matchingFile = fModule.getMatchingFile(18000000, 1338, 0x400100);
assertEquals(expected, matchingFile);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_ny", null, "/tmp/debug_link1", false);
matchingFile = fModule.getMatchingFile(19000000, 1339, 0x400100);
assertEquals(expected, matchingFile);
expected = new UstDebugInfoLoadedBinaryFile(0x400000, "/tmp/foo_yy", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "/tmp/debug_link2", false);
matchingFile = fModule.getMatchingFile(20000000, 1340, 0x400100);
assertEquals(expected, matchingFile);
LttngUstTestTraceUtils.dispose(SYNTH_BUILDID_DEBUGLINK_TRACE);
}
/**
* Test the {@link UstDebugInfoAnalysisModule#getAllBinaries} method.
*/
@Test
public void testGetAllBinaries() {
LttngUstTrace trace = LttngUstTestTraceUtils.getTrace(REAL_TEST_TRACE);
executeModule(trace);
List<UstDebugInfoBinaryFile> actualBinaries = Lists.newArrayList(fModule.getAllBinaries());
List<UstDebugInfoBinaryFile> expectedBinaries = Lists.newArrayList(
new UstDebugInfoBinaryFile("/home/simark/src/babeltrace/tests/debug-info-data/libhello_so",
"cdd98cdd87f7fe64c13b6daad553987eafd40cbb", null, true),
new UstDebugInfoBinaryFile("/home/simark/src/babeltrace/tests/debug-info-data/test",
"0683255d2cf219c33cc0efd6039db09ccc4416d7", null, false),
new UstDebugInfoBinaryFile("[linux-vdso.so.1]", null, null, false),
new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust-dl.so.0.0.0",
"39c035014cc02008d6884fcb1be4e020cc820366", null, true),
new UstDebugInfoBinaryFile("/usr/lib/libdl-2.23.so",
"db3f9be9f4ebe9e2a21e4ae0b4ef7165d40fdfef", null, true),
new UstDebugInfoBinaryFile("/usr/lib/libc-2.23.so",
"946025a5cad7b5f2dfbaebc6ebd1fcc004349b48", null, true),
new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust.so.0.0.0",
"405b0b15daa73eccb88076247ba30356c00d3b92", null, true),
new UstDebugInfoBinaryFile("/usr/local/lib/liblttng-ust-tracepoint.so.0.0.0",
"62c028aad38adb5e0910c527d522e8c86a0a3344", null, true),
new UstDebugInfoBinaryFile("/usr/lib/librt-2.23.so",
"aba676bda7fb6adb71e100159915504e1a0c17e6", null, true),
new UstDebugInfoBinaryFile("/usr/lib/liburcu-bp.so.4.0.0",
"b9dfadea234107f8453bc636fc160047e0c01b7a", null, true),
new UstDebugInfoBinaryFile("/usr/lib/liburcu-cds.so.4.0.0",
"420527f6dacc762378d9fa7def54d91c80a6c87e", null, true),
new UstDebugInfoBinaryFile("/usr/lib/libpthread-2.23.so",
"d91ed99c8425b7ce5da5bb750662a91038e02a78", null, true),
new UstDebugInfoBinaryFile("/usr/lib/ld-2.23.so",
"524eff0527e923e4adc4be9db1ef7475607b92e8", null, true),
new UstDebugInfoBinaryFile("/usr/lib/liburcu-common.so.4.0.0",
"f279a6d46a2b846e15e7abd99cfe9fbe8d7f8295", null, true));
Comparator<UstDebugInfoBinaryFile> comparator = Comparator.comparing(UstDebugInfoBinaryFile::getFilePath);
actualBinaries.sort(comparator);
expectedBinaries.sort(comparator);
/* Highlights failures more easily */
for (int i = 0; i < expectedBinaries.size(); i++) {
assertEquals(expectedBinaries.get(i), actualBinaries.get(i));
}
assertEquals(actualBinaries, expectedBinaries);
LttngUstTestTraceUtils.dispose(REAL_TEST_TRACE);
}
}