| /******************************************************************************* |
| * 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); |
| } |
| |
| } |