1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 472765: more complete tests for source path mapping

Add some more tests for source path mappings to ensure that the upcoming
change of using gdb's set substitute-path does not regress any issues.

Change-Id: I9067c8859293c3332439679cb1f663e36a4cc34e
Signed-off-by: Jonah Graham <jonah@kichwacoders.com>
This commit is contained in:
Jonah Graham 2016-01-06 16:04:12 +00:00 committed by Gerrit Code Review @ Eclipse.org
parent 59d0f15afe
commit cedcf7655b
14 changed files with 807 additions and 74 deletions

View file

@ -106,7 +106,10 @@ public interface ISourceFinder {
* is in OS specific format, along the lines of what {@link IPath#toOSString()} would return. Note
* that by "on the host machine", we simply mean a specification that is <i>accessible by the host
* machine</i>. The file may be on a network drive, e.g., and thus not really be "local".
* @deprecated This method is unused in CDT code base. Use {@link #toLocalPath(String)} or request
* undeprecating on the cdt-dev mailing list.
*/
@Deprecated
public String toLocalPath(IAdaptable launch, String compilationPath);
/**

View file

@ -66,6 +66,7 @@ public class MIFrame {
buffer.append(",addr=\"" + addr + "\""); //$NON-NLS-1$//$NON-NLS-2$
buffer.append(",func=\"" + func + "\""); //$NON-NLS-1$//$NON-NLS-2$
buffer.append(",file=\"" + file + "\""); //$NON-NLS-1$//$NON-NLS-2$
buffer.append(",fullname=\"" + fullname + "\""); //$NON-NLS-1$//$NON-NLS-2$
buffer.append(",line=\"").append(line).append('"'); //$NON-NLS-1$
buffer.append(",args=["); //$NON-NLS-1$
for (int i = 0; i < args.length; i++) {

View file

@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.launch,
org.eclipse.cdt.gdb,
org.eclipse.cdt.dsf.gdb,
org.eclipse.core.variables
org.eclipse.core.variables,
org.easymock
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ClassPath: .

View file

@ -1,22 +1,44 @@
BINDIR = ../bin
BUILDDIR = ../build
BUILD2DIR = ../build2
SRC_C = $(wildcard *.c)
SRC_CXX = $(wildcard *.cc)
# We rebuild everything whenever one of the headers change
HEADERS = $(wildcard *.h)
# These Source Lookup tests compile in a different directory than the directory
# the source is in. This allows to test source lookup.
SOURCELOOKUP_BINS = $(BINDIR)/SourceLookupAC.exe $(BINDIR)/SourceLookupAN.exe $(BINDIR)/SourceLookupRC.exe $(BINDIR)/SourceLookupRN.exe
# These tests are for running against older GDBs which require compatibilty flags
# for GCC debug info, see OLDDWARFFLAGS below
SOURCELOOKUP_BINS += $(BINDIR)/SourceLookupDwarf2AC.exe $(BINDIR)/SourceLookupDwarf2AN.exe $(BINDIR)/SourceLookupDwarf2RC.exe $(BINDIR)/SourceLookupDwarf2RN.exe
# Use .exe extension so that files are named the same way in Linux and Windows.
BINS = $(patsubst %.c,$(BINDIR)/%.exe,$(SRC_C)) $(patsubst %.cc,$(BINDIR)/%.exe,$(SRC_CXX))
BINS += $(SOURCELOOKUP_BINS)
# This source lookup exe (like the default SourceLookup.exe) compiles from non-relocated source.
BINS += $(BINDIR)/SourceLookupDwarf2.exe
COREFILE = $(BINDIR)/core
CC = gcc
CXX = g++
# Uncomment the OLDDWARFFLAGS to run newer GCC against older GDB
# OLDDWARFFLAGS = -gdwarf-2 -gstrict-dwarf
CFLAGS = -g3 -O0 $(OLDDWARFFLAGS)
CXXFLAGS = -g3 -O0 $(OLDDWARFFLAGS)
# As of the time of writing, using GCC 4.8.4 OLDDWARFFLAGS is required:
# for -> because:
# GDB <= 7.1 -> does not work at all because "Dwarf Error: wrong version in compilation unit header (is 4, should be 2)"
# GDB <= 7.4 -> fails some tests because files are not resolved the same way by GDB.
# With OLDDWARFFLAGS SourceLookupRC returns file="SourceLookup.cc" in frame info even if SourceLookup.cc is not found
# Without OLDDWARFFLAGS SourceLookupRC the file field in the frame info is left out if SourceLookup.cc is not found
# For running tests on recent GDBs (> 7.5), OLDDWARFFLAGS should remain unset.
OLDDWARFFLAGS = -gdwarf-2 -gstrict-dwarf
# Older compilers versions (like 4.3.4 used on CDT Hudson machine) don't have -gstrict-dwarf
OLDDWARFFLAGS_CHECKED := $(shell $(CXX) $(OLDDWARFFLAGS) -x c++ /dev/null -c -o /dev/null > /dev/null 2>&1 && echo $(OLDDWARFFLAGS) || echo "")
# By default only SourceLookup tests take into account OLDDWARFFLAGS, if testing any other tests
# with older GDBs, adding OLDDWARFFLAGS to the compilation flags is necessary.
CFLAGS = -g3 -O0
CXXFLAGS = -g3 -O0
# Don't try to use pthread on Windows
# The OS environment variable exists on Windows
@ -36,9 +58,6 @@ all: $(BINS) $(COREFILE)
$(BINDIR):
$(MKDIR) $@
$(BUILDDIR):
$(MKDIR) $@
$(BINDIR)/%.exe: %.c $(HEADERS) Makefile | $(BINDIR)
$(CC) $(CFLAGS) -o $@ $<
@ -50,11 +69,40 @@ $(COREFILE): $(BINDIR)/ExpressionTestApp.exe Makefile | $(BINDIR)
gdb -nx --batch -ex 'b testLocals' -ex 'run' --ex 'next 16' \
-ex 'gcore ../bin/core' $(BINDIR)/ExpressionTestApp.exe > /dev/null
# Compile sourcelookup once with old dwarf flags
$(BINDIR)/SourceLookupDwarf2.exe: SourceLookup.cc $(HEADERS) Makefile | $(BINDIR)
$(CXX) $(CXXFLAGS) $(OLDDWARFFLAGS_CHECKED) -o $@ $<
# Compile a source file from an alternate directory
$(BINDIR)/SourceLookup.exe: SourceLookup.cc $(HEADERS) Makefile | $(BINDIR) $(BUILDDIR)
# This is aiming to represent the different ways that the path to a source
# file can be recorded in debug information. See comments on each one
# for the intention
ABSOLUTE_NONCANONICAL_BUILDDIR=$(shell $(MKDIR) $(BUILD2DIR) ; cd $(BUILD2DIR) ; pwd)/$(BUILDDIR)
ABSOLUTE_CANONICAL_BUILDDIR=$(shell $(MKDIR) $(BUILDDIR) ; cd $(BUILDDIR) ; pwd)
$(SOURCELOOKUP_BINS): SourceLookup.cc $(HEADERS) Makefile | $(BINDIR)
@echo "Building test executables with"
$(CXX) --version | head -1
# Set up the "build" environment, this gets cleaned up at the end to simulate
# a user moving a project's source and needing source lookup to file it
$(MKDIR) $(BUILDDIR)
$(MKDIR) $(BUILD2DIR)
cp SourceLookup.cc $(BUILDDIR)/SourceLookup.cc
cd $(BUILDDIR) && $(CXX) $(CXXFLAGS) -o $@ SourceLookup.cc
rm $(BUILDDIR)/SourceLookup.cc
# Absolute and canonical path
cd $(BUILDDIR) && $(CXX) $(CXXFLAGS) -o $(BINDIR)/SourceLookupAC.exe $(ABSOLUTE_CANONICAL_BUILDDIR)/SourceLookup.cc
cd $(BUILDDIR) && $(CXX) $(CXXFLAGS) $(OLDDWARFFLAGS_CHECKED) -o $(BINDIR)/SourceLookupDwarf2AC.exe $(ABSOLUTE_CANONICAL_BUILDDIR)/SourceLookup.cc
# Absolute and non-canonical path (contains ..)
cd $(BUILD2DIR) && $(CXX) $(CXXFLAGS) -o $(BINDIR)/SourceLookupAN.exe $(ABSOLUTE_NONCANONICAL_BUILDDIR)/SourceLookup.cc
cd $(BUILD2DIR) && $(CXX) $(CXXFLAGS) $(OLDDWARFFLAGS_CHECKED) -o $(BINDIR)/SourceLookupDwarf2AN.exe $(ABSOLUTE_NONCANONICAL_BUILDDIR)/SourceLookup.cc
# Relative and canonical path
cd $(BUILDDIR) && $(CXX) $(CXXFLAGS) -o $(BINDIR)/SourceLookupRC.exe SourceLookup.cc
cd $(BUILDDIR) && $(CXX) $(CXXFLAGS) $(OLDDWARFFLAGS_CHECKED) -o $(BINDIR)/SourceLookupDwarf2RC.exe SourceLookup.cc
# Relative and non-canonical path (contains ..)
cd $(BUILD2DIR) && $(CXX) $(CXXFLAGS) -o $(BINDIR)/SourceLookupRN.exe $(BUILDDIR)/SourceLookup.cc
cd $(BUILD2DIR) && $(CXX) $(CXXFLAGS) $(OLDDWARFFLAGS_CHECKED) -o $(BINDIR)/SourceLookupDwarf2RN.exe $(BUILDDIR)/SourceLookup.cc
# Cleanup: We must remove the source file used for all the SourceLookup*.exe compilation so that the
# SourceLookup logic is forced to look elsewhere to find it, i.e., in the src/ directory.
$(RM) $(BUILDDIR)/SourceLookup.cc
$(RMDIR) $(BUILDDIR) $(BUILD2DIR)
clean:
$(RM) -r $(BINDIR) $(BUILDDIR)
$(RM) -r $(BINDIR) $(BUILDDIR) $(BUILD2DIR)

View file

@ -11,6 +11,9 @@
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.framework;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
@ -39,11 +42,13 @@ import org.eclipse.cdt.dsf.service.DsfSession.SessionStartedListener;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
@ -204,8 +209,31 @@ public class BaseTestCase {
}
}
/**
* Make sure we are starting with a clean/known state. That means no
* existing launches or launch configurations.
*/
public void removeTeminatedLaunchesBeforeTest() throws CoreException {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunch[] launches = launchManager.getLaunches();
for (ILaunch launch : launches) {
if (!launch.isTerminated()) {
fail("Something has gone wrong, there is an unterminated launch from a previous test!");
}
}
if (launches.length > 0) {
launchManager.removeLaunches(launches);
}
ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations();
for (ILaunchConfiguration launchConfiguration : launchConfigurations) {
launchConfiguration.delete();
}
}
@Before
public void doBeforeTest() throws Exception {
removeTeminatedLaunchesBeforeTest();
setLaunchAttributes();
doLaunch();
}
@ -379,6 +407,12 @@ public class BaseTestCase {
public void doAfterTest() throws Exception {
if (fLaunch != null) {
fLaunch.terminate();
// Give a few seconds to allow the launch to terminate
int waitCount = 100;
while (!fLaunch.isTerminated() && --waitCount > 0) {
Thread.sleep(TestsPlugin.massageTimeout(100));
}
assertTrue("Launch failed to terminate before timeout", fLaunch.isTerminated());
fLaunch = null;
}
}

View file

@ -66,6 +66,7 @@ public class CommandTimeoutTest extends BaseTestCase {
@Override
public void doBeforeTest() throws Exception {
removeTeminatedLaunchesBeforeTest();
setLaunchAttributes();
// Can't run the launch right away because each test needs to first set some
// parameters. The individual tests will be responsible for starting the launch.

View file

@ -68,6 +68,7 @@ public class LaunchConfigurationAndRestartTest extends BaseTestCase {
@Override
public void doBeforeTest() throws Exception {
removeTeminatedLaunchesBeforeTest();
setLaunchAttributes();
// Can't run the launch right away because each test needs to first set some
// parameters. The individual tests will be responsible for starting the launch.

View file

@ -70,6 +70,7 @@ public class PostMortemCoreTest extends BaseTestCase {
@Override
public void doBeforeTest() throws Exception {
removeTeminatedLaunchesBeforeTest();
setLaunchAttributes();
// Can't run the launch right away because each test needs to first set some
// parameters. The individual tests will be responsible for starting the launch.

View file

@ -10,8 +10,12 @@
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@ -24,76 +28,214 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.core.ISourceFinder;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.debug.core.CDIDebugModel;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.sourcelookup.AbsolutePathSourceContainer;
import org.eclipse.cdt.debug.core.sourcelookup.CProjectSourceContainer;
import org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer;
import org.eclipse.cdt.debug.core.sourcelookup.ProgramRelativePathSourceContainer;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.debug.internal.core.sourcelookup.MapEntrySourceContainer;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
import org.eclipse.cdt.tests.dsf.gdb.framework.AsyncCompletionWaitor;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseTestCase;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_6_6.SourceLookupTest_6_6;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_5.SourceLookupTest_7_5;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointListener;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer;
import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests that interaction with source lookups works as expected.
*
* All of these tests use a program (SourceLookup.exe) that was built from
* sources that have moved. At build time source was ../build/SourceLookup.cc,
* but now is ../src/SourceLookup.cc.
* All of these tests use one of SourceLookup*.exe that was built from a file
* that was "moved" since build time. At build time the SourceLookup.cc file was
* located in the {@link #BUILD_PATH} directory, but it is now located in the
* {@link BaseTestCase#SOURCE_PATH} directory.
*
* TODO: Missing features and tests:
* The wild card in SourceLookup*.exe can be one of the following to cover the
* different effective types of source lookups that need to be done depending on
* how the program was compiled. Each of these options produces different debug
* information about where to find the source file. See the Makefile for more
* information.
* <ul>
* <li><b>AC</b>: Absolute and Canonical path (no ../ in path passed to GCC)
* </li>
* <li><b>AN</b>: Absolute and Non-Canonical path (a ../ in path passed to GCC)
* </li>
* <li><b>RC</b>: Relative and Canonical path (no ../ in path passed to GCC)
* </li>
* <li><b>RN</b>: Relative and Non-Canonical path (a ../ in path passed to GCC)
* </li>
* <li><b>No suffix</b>: Compilation that does not need mapping to be found
* </ul>
* In addition, there can also be a <b>Dwarf2</b> in the name. That means it is
* designed to run with GDB <= 7.4, see comment in Makefile for OLDDWARFFLAGS.
*
* - Update source lookup path in running session (i.e. simulate behaviour of
* CSourceNotFoundEditor)
* The result of the variations on compilation arguments means that some of the
* tests are parameterised.
*
* - Ensure breakpoints are inserted properly. This needs to be done by creating
* platform breakpoints and checking they are installed correctly.
* Some of the CDT source lookup features require newer versions of GDB than
* others, therefore the relevant tests are ignored as needed in the subclasses
* of {@link SourceLookupTest}.
*/
@RunWith(BackgroundRunner.class)
public class SourceLookupTest extends BaseTestCase {
protected static final String BUILD_PATH = "data/launch/build/";
protected static final String EXEC_NAME = "SourceLookup.exe"; //$NON-NLS-1$
protected static final String BUILD2_PATH = "data/launch/build2/";
protected static final String SOURCE_NAME = "SourceLookup.cc"; //$NON-NLS-1$
protected static final int SOURCE_LINE = 15;
/** Compiled with absolute and canonical path to SourceLookup.cc */
protected String EXEC_AC_NAME;
/** Compiled with absolute and non-canonical path to SourceLookup.cc */
protected String EXEC_AN_NAME;
/** Compiled with relative and canonical path to SourceLookup.cc */
protected String EXEC_RC_NAME;
/** Compiled with relative and non-canonical path to SourceLookup.cc */
protected String EXEC_RN_NAME;
/**
* File compiled with SourceLookup.cc in the src directory, so GDB resolves
* it without help.
*/
protected String EXEC_NAME;
/**
* For version of GDB <= 7.4 we need to use the strict dwarf2 flags. See
* comment in Makefile on OLDDWARFFLAGS. Also see
* {@link SourceLookupTest_6_6#setExeNames()} which sets up the old exes and
* {@link SourceLookupTest_7_5#setExeNames()} which restores them.
*/
protected void setExeNames() {
EXEC_AC_NAME = "SourceLookupAC.exe"; //$NON-NLS-1$
EXEC_AN_NAME = "SourceLookupAN.exe"; //$NON-NLS-1$
EXEC_RC_NAME = "SourceLookupRC.exe"; //$NON-NLS-1$
EXEC_RN_NAME = "SourceLookupRN.exe"; //$NON-NLS-1$
EXEC_NAME = "SourceLookup.exe"; //$NON-NLS-1$
}
protected static final String SOURCE_ABSPATH = new File(SOURCE_PATH).getAbsolutePath();
protected static final String BUILD_ABSPATH = new File(BUILD_PATH).getAbsolutePath();
/** This path matches the non-canonical path used to build the *N.exe's */
protected static final String BUILD_NONCANONICAL_PATH = new File(new File(BUILD2_PATH).getAbsolutePath(),
"../build/").toString();
/**
* Map entry for non-canonical build dirs
*/
protected MapEntrySourceContainer fMapEntrySourceContainerN = new MapEntrySourceContainer(
new Path(BUILD_NONCANONICAL_PATH), new Path(SOURCE_ABSPATH));
/**
* Map entry for canonical build dirs
*/
protected MapEntrySourceContainer fMapEntrySourceContainerC = new MapEntrySourceContainer(new Path(BUILD_ABSPATH),
new Path(SOURCE_ABSPATH));
protected AsyncCompletionWaitor fBreakpointInstalledWait = new AsyncCompletionWaitor();
protected IBreakpointListener fBreakpointListener = new IBreakpointListener() {
@Override
public void breakpointAdded(IBreakpoint breakpoint) {
}
@Override
public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
}
@Override
public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
if (breakpoint instanceof ICBreakpoint) {
try {
if (((ICBreakpoint) breakpoint).isInstalled()) {
fBreakpointInstalledWait.waitFinished();
}
} catch (CoreException e) {
}
}
}
};
@Override
public void doBeforeTest() throws Exception {
setLaunchAttributes();
// source lookup attributes are custom per test, so delay launch until
// they are setup
}
@Override
protected void setLaunchAttributes() {
removeTeminatedLaunchesBeforeTest();
IBreakpointManager manager = DebugPlugin.getDefault().getBreakpointManager();
manager.addBreakpointListener(fBreakpointListener);
setExeNames();
super.setLaunchAttributes();
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EXEC_PATH + EXEC_NAME);
// executable and source lookup attributes are custom per test,
// so delay launch until they are setup
}
/**
* Test with only default source locators on, that the source file was not
* found when stopped at main by any of GDB directly, with the source lookup
* director, or via the ISourceLookup service.
* Remove any platform breakpoints that have been created.
*/
@Test
public void defaultSourceLookup() throws Throwable {
doLaunch();
@Override
public void doAfterTest() throws Exception {
super.doAfterTest();
IBreakpointManager manager = DebugPlugin.getDefault().getBreakpointManager();
IBreakpoint[] breakpoints = manager.getBreakpoints();
manager.removeBreakpoints(breakpoints, true);
manager.removeBreakpointListener(fBreakpointListener);
}
protected void doLaunch(String programName) throws Exception {
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, programName);
super.doLaunch();
}
@Override
protected void doLaunch() throws Exception {
throw new RuntimeException("Within this test you must use doLaunch(String) to setup program");
}
/**
* Return true if file refers to the real source file.
*/
protected boolean fileExists(String file) {
if (!file.endsWith(SOURCE_NAME))
return false;
return Files.exists(Paths.get(file));
}
/**
* Custom assertion that neither GDB nor the Source Locator found the source
* file.
*/
protected void assertSourceNotFound() throws Throwable {
// Check file name as returned from back end
IFrameDMData frameData = SyncUtil.getFrameData(0, 0);
assertFalse("GDB Unexpectedly located the source", Files.exists(Paths.get(frameData.getFile())));
assertFalse("GDB Unexpectedly located the source", fileExists(frameData.getFile()));
// Check file as resolved by source lookup director
ISourceLookupDirector director = (ISourceLookupDirector) getGDBLaunch().getSourceLocator();
@ -112,6 +254,56 @@ public class SourceLookupTest extends BaseTestCase {
}
}
/**
* Custom assertion that GDB did not find the source, but the Source Locator
* found the source file.
*/
protected void assertSourceFoundByDirectorOnly() throws Throwable {
// Check file name as returned from back end
IFrameDMData frameData = SyncUtil.getFrameData(0, 0);
assertFalse("GDB Unexpectedly located the source", fileExists(frameData.getFile()));
// Check file as resolved by source lookup director
ISourceLookupDirector director = (ISourceLookupDirector) getGDBLaunch().getSourceLocator();
IFrameDMContext frameDmc = SyncUtil.getStackFrame(0, 0);
Object sourceElement = director.getSourceElement(frameDmc);
assertTrue("Source locator failed to find source", sourceElement instanceof IStorage);
// Check file as resolved by ISourceLookup service
sourceElement = SyncUtil.getSource(frameData.getFile());
assertTrue("Source Lookup service failed to find source", sourceElement instanceof IStorage);
}
/**
* Custom assertion that GDB and the Source Locator found the source file.
*/
protected void assertSourceFound() throws Throwable {
// Check file name as returned from back end
IFrameDMData frameData = SyncUtil.getFrameData(0, 0);
assertTrue("GDB failed to find source", fileExists(frameData.getFile()));
// Check file as resolved by source lookup director
ISourceLookupDirector director = (ISourceLookupDirector) getGDBLaunch().getSourceLocator();
IFrameDMContext frameDmc = SyncUtil.getStackFrame(0, 0);
Object sourceElement = director.getSourceElement(frameDmc);
assertTrue("Source locator failed to find source", sourceElement instanceof IStorage);
// Check file as resolved by ISourceLookup service
sourceElement = SyncUtil.getSource(frameData.getFile());
assertTrue("Source Lookup service failed to find source", sourceElement instanceof IStorage);
}
/**
* Test with only default source locators on, that the source file was not
* found when stopped at main by any of GDB directly, with the source lookup
* director, or via the ISourceLookup service.
*/
@Test
public void defaultSourceLookup() throws Throwable {
doLaunch(EXEC_PATH + EXEC_RC_NAME);
assertSourceNotFound();
}
protected AbstractSourceLookupDirector setSourceContainer(ISourceContainer container) throws CoreException {
AbstractSourceLookupDirector director = (AbstractSourceLookupDirector) DebugPlugin.getDefault()
.getLaunchManager().newSourceLocator("org.eclipse.cdt.debug.core.sourceLocator");
@ -133,31 +325,221 @@ public class SourceLookupTest extends BaseTestCase {
}
/**
* Test with default source locators and a path mapping
* {@link MappingSourceContainer} from BUILD_ABSPATH -> SOURCE_ABSPATH that
* GDB does not locate the file, but the source lookup director and the
* source lookup service do find the file.
* Add the mapping source container to the common source lookup
*/
protected void doMappingInCommon(boolean canonical) {
CSourceLookupDirector commonSourceLookupDirector = CDebugCorePlugin.getDefault()
.getCommonSourceLookupDirector();
MappingSourceContainer mapContainer = new MappingSourceContainer("Mappings");
if (canonical) {
mapContainer.addMapEntry(fMapEntrySourceContainerC);
} else {
mapContainer.addMapEntry(fMapEntrySourceContainerN);
}
ArrayList<ISourceContainer> containerList = new ArrayList<ISourceContainer>(
Arrays.asList(commonSourceLookupDirector.getSourceContainers()));
containerList.add(mapContainer);
commonSourceLookupDirector
.setSourceContainers(containerList.toArray(new ISourceContainer[containerList.size()]));
}
/**
* Resource common source container to the default
*/
protected void restoreCommonToDefault() {
CSourceLookupDirector commonSourceLookupDirector = CDebugCorePlugin.getDefault()
.getCommonSourceLookupDirector();
ISourceContainer[] containers = new ISourceContainer[3];
int i = 0;
containers[i++] = new AbsolutePathSourceContainer();
containers[i++] = new ProgramRelativePathSourceContainer();
containers[i++] = new CProjectSourceContainer(null, true);
commonSourceLookupDirector.setSourceContainers(containers);
}
/**
* Set default source locators and a path mapping
* {@link MappingSourceContainer} from BUILD_ABSPATH -> SOURCE_ABSPATH and
* do the launch
*
* @return
*/
protected void doMappingAndLaunch(String programName) throws CoreException, Exception {
MappingSourceContainer mapContainer = new MappingSourceContainer("Mappings");
if (programName.endsWith("N.exe")) {
mapContainer.addMapEntry(fMapEntrySourceContainerN);
} else if (programName.endsWith("C.exe")) {
mapContainer.addMapEntry(fMapEntrySourceContainerC);
} else {
fail("Unexpected file");
}
setSourceContainer(mapContainer);
doLaunch(EXEC_PATH + programName);
}
/**
* With mapping test that GDB does not locate the file, but the source
* lookup director and the source lookup service do find the file.
*/
protected void sourceMapping(String programName) throws Throwable {
doMappingAndLaunch(programName);
assertSourceFoundByDirectorOnly();
}
/**
* With mapping test breakpoints can be inserted.
*/
protected void sourceMappingBreakpoints(String programName) throws Throwable {
doMappingAndLaunch(programName);
// insert breakpoint in source file
fBreakpointInstalledWait.waitReset();
ICLineBreakpoint bp = CDIDebugModel.createLineBreakpoint(
new Path(SOURCE_ABSPATH).append(SOURCE_NAME).toOSString(), ResourcesPlugin.getWorkspace().getRoot(),
ICBreakpointType.REGULAR, SOURCE_LINE, true, 0, "", true);
// The delay here is based on:
// 1) The installation of the breakpoint takes some time
// 2) The notification of the IBreakpoint change needs the autobuild
// to run, and it has up to a 1 second delay (depending on how
// long since it last ran). See
// org.eclipse.core.internal.events.AutoBuildJob.computeScheduleDelay()
fBreakpointInstalledWait.waitUntilDone(TestsPlugin.massageTimeout(2000));
assertTrue("Breakpoint failed to install", bp.isInstalled());
}
/**
* Test source mappings with executable built with an Absolute and Canonical
* build path
*/
@Test
public void sourceMapping() throws Throwable {
MappingSourceContainer mapContainer = new MappingSourceContainer("Mappings");
mapContainer.addMapEntry(new MapEntrySourceContainer(new Path(BUILD_ABSPATH), new Path(SOURCE_ABSPATH)));
setSourceContainer(mapContainer);
doLaunch();
public void sourceMappingAC() throws Throwable {
sourceMapping(EXEC_AC_NAME);
}
// Check file name as returned from back end
IFrameDMData frameData = SyncUtil.getFrameData(0, 0);
assertFalse("GDB Unexpectedly located the source", Files.exists(Paths.get(frameData.getFile())));
/**
* Test source mappings with executable built with an Absolute and
* Non-canonical build path
*/
@Test
public void sourceMappingAN() throws Throwable {
sourceMapping(EXEC_AN_NAME);
}
// Check file as resolved by source lookup director
ISourceLookupDirector director = (ISourceLookupDirector) getGDBLaunch().getSourceLocator();
IFrameDMContext frameDmc = SyncUtil.getStackFrame(0, 0);
Object sourceElement = director.getSourceElement(frameDmc);
assertTrue("Source locator failed to find source", sourceElement instanceof IStorage);
/**
* Test source mappings with executable built with a Relative and Canonical
* build path
*/
@Test
public void sourceMappingRC() throws Throwable {
sourceMapping(EXEC_RC_NAME);
}
// Check file as resolved by ISourceLookup service
sourceElement = SyncUtil.getSource(frameData.getFile());
assertTrue("Source Lookup service failed to find source", sourceElement instanceof IStorage);
/**
* Test source mappings with executable built with a Relative and
* Non-canonical build path
*/
@Test
public void sourceMappingRN() throws Throwable {
sourceMapping(EXEC_RN_NAME);
}
/**
* Test source mappings with executable built with an Absolute and Canonical
* build path
*/
@Test
public void sourceMappingBreakpointsAC() throws Throwable {
sourceMappingBreakpoints(EXEC_AC_NAME);
}
/**
* Test source mappings with executable built with an Absolute and
* Non-canonical build path
*/
@Ignore("Not supported because GDB does not handle non-canonical paths. See Bug 477057")
@Test
public void sourceMappingBreakpointsAN() throws Throwable {
sourceMappingBreakpoints(EXEC_AN_NAME);
}
/**
* Test source mappings with executable built with a Relative and Canonical
* build path
*/
@Test
public void sourceMappingBreakpointsRC() throws Throwable {
sourceMappingBreakpoints(EXEC_RC_NAME);
}
/**
* Test source mappings with executable built with a Relative and
* Non-canonical build path
*/
@Ignore("Not supported because GDB does not handle non-canonical paths. See Bug 477057")
@Test
public void sourceMappingBreakpointsRN() throws Throwable {
sourceMappingBreakpoints(EXEC_RN_NAME);
}
/**
* Test that if the user changes the source mappings in the middle of a
* debug session (e.g. with CSourceNotFoundEditor) that the lookups are
* updated.
*/
@Test
public void sourceMappingChanges() throws Throwable {
doMappingAndLaunch(EXEC_AC_NAME);
DsfSourceLookupDirector sourceLocator = (DsfSourceLookupDirector) getGDBLaunch().getSourceLocator();
MapEntrySourceContainer incorrectMapEntry = new MapEntrySourceContainer(
new Path(BUILD_ABSPATH + "/incorrectsubpath"), new Path(SOURCE_ABSPATH));
assertSourceFoundByDirectorOnly();
// Change the source mappings
ISourceContainer[] containers = sourceLocator.getSourceContainers();
MappingSourceContainer mappingSourceContainer = (MappingSourceContainer) containers[1];
mappingSourceContainer.removeMapEntry(fMapEntrySourceContainerC);
mappingSourceContainer.addMapEntry(incorrectMapEntry);
sourceLocator.setSourceContainers(containers);
assertSourceNotFound();
// Change the source mappings back
containers = sourceLocator.getSourceContainers();
mappingSourceContainer = (MappingSourceContainer) containers[1];
mappingSourceContainer.removeMapEntry(incorrectMapEntry);
mappingSourceContainer.addMapEntry(fMapEntrySourceContainerC);
sourceLocator.setSourceContainers(containers);
assertSourceFoundByDirectorOnly();
}
/**
* Test that if the user changes the source mappings in the middle of a
* debug session (e.g. with CSourceNotFoundEditor) that the lookups are
* updated.
*
* This version is for a new source mapping where there wasn't one
* previously.
*/
@Test
public void sourceMappingAdded() throws Throwable {
doLaunch(EXEC_PATH + EXEC_AC_NAME);
assertSourceNotFound();
// Set the source mappings
DsfSourceLookupDirector sourceLocator = (DsfSourceLookupDirector) getGDBLaunch().getSourceLocator();
ISourceContainer[] containers = sourceLocator.getSourceContainers();
MappingSourceContainer mappingSourceContainer = new MappingSourceContainer("Mappings");
mappingSourceContainer.addMapEntry(fMapEntrySourceContainerC);
ISourceContainer[] newContainers = new ISourceContainer[containers.length + 1];
System.arraycopy(containers, 0, newContainers, 0, containers.length);
newContainers[newContainers.length - 1] = mappingSourceContainer;
sourceLocator.setSourceContainers(newContainers);
assertSourceFoundByDirectorOnly();
}
/**
@ -172,20 +554,151 @@ public class SourceLookupTest extends BaseTestCase {
public void directorySource() throws Throwable {
DirectorySourceContainer container = new DirectorySourceContainer(new Path(SOURCE_ABSPATH), false);
setSourceContainer(container);
doLaunch();
doLaunch(EXEC_PATH + EXEC_RC_NAME);
assertSourceFoundByDirectorOnly();
}
// Check file name as returned from back end
IFrameDMData frameData = SyncUtil.getFrameData(0, 0);
assertFalse("GDB Unexpectedly located the source", Files.exists(Paths.get(frameData.getFile())));
/**
* Create an IBinary with the minimum necessary for use in
* org.eclipse.cdt.debug.internal.core.srcfinder.CSourceFinder.
*
* A mock is used to avoid having to set up the significant of glue
* necessary to create a real IBinary. All that CSourceFinder needs is the
* path to the file.
*/
protected IBinary createMockIBinary(String path) {
IPath absPath = new Path(new File(path).getAbsolutePath());
// Check file as resolved by source lookup director
ISourceLookupDirector director = (ISourceLookupDirector) getGDBLaunch().getSourceLocator();
IFrameDMContext frameDmc = SyncUtil.getStackFrame(0, 0);
Object sourceElement = director.getSourceElement(frameDmc);
assertTrue("Source locator failed to find source", sourceElement instanceof IStorage);
IResource exeResource = createNiceMock(IResource.class);
expect(exeResource.getFullPath()).andReturn(absPath);
expect(exeResource.getProject()).andReturn(null);
replay(exeResource);
// Check file as resolved by ISourceLookup service
sourceElement = SyncUtil.getSource(frameData.getFile());
assertTrue("Source Lookup service failed to find source", sourceElement instanceof IStorage);
IBinary exeBin = createNiceMock(IBinary.class);
expect(exeBin.getPath()).andReturn(absPath);
expect(exeBin.getAdapter(IResource.class)).andReturn(exeResource);
/*
* we use the adapter factory CSourceFinderFactory to convert IBinary to
* ISourceFinder. The way the adapter is resolved it will first try and
* and get the adapter from the IBinary (IBinary extends IAdaptable) so
* we need to return null here for a clean failure. If we didn't
* explicitly provide the null, an exception would be raised because an
* unexpected method is invoked.
*/
expect(exeBin.getAdapter(ISourceFinder.class)).andReturn(null);
replay(exeBin);
return exeBin;
}
/**
* Assert that the finder is able resolve the source file name
*/
protected void assertFinderFinds(String programName, String buildAbspath) {
IBinary binary = createMockIBinary(EXEC_PATH + programName);
ISourceFinder finder = Adapters.adapt(binary, ISourceFinder.class, true);
try {
String localPath = finder.toLocalPath(buildAbspath);
assertEquals("Source Finder failed to find file", new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath(),
localPath);
} finally {
finder.dispose();
}
}
/**
* Assert that the finder is not able resolve the source file name
*/
protected void assertFinderDoesNotFind(String programName, String buildAbspath) {
IBinary binary = createMockIBinary(EXEC_PATH + programName);
ISourceFinder finder = Adapters.adapt(binary, ISourceFinder.class, true);
try {
String localPath = finder.toLocalPath(buildAbspath);
assertNotEquals("Source Finder unexpectedly found file",
new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath(), localPath);
} finally {
finder.dispose();
}
}
/**
* Test the base case of the source finder, when it does not need any
* special help like mapping to find a file.
*/
@Test
public void sourceFinder() throws Throwable {
assertFinderFinds(EXEC_AC_NAME, new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath());
}
/**
* Test the CSourceFinder's use of source lookup when there is an active
* launch.
*
* In this case, the DSF specific director created as part of the launch
* gets used.
*/
@Test
public void sourceFinderMappingAC_ActiveLaunch() throws Throwable {
assertFinderDoesNotFind(EXEC_AC_NAME, new File(BUILD_PATH, SOURCE_NAME).getAbsolutePath());
doMappingAndLaunch(EXEC_AC_NAME);
assertFinderFinds(EXEC_AC_NAME, new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath());
}
/**
* Test the CSourceFinder's use of source lookup when there is a terminated
* launch.
*
* In this case, the DSF specific director created as part of the launch
* gets used.
*/
@Test
public void sourceFinderMappingAC_TerminatedLaunch() throws Throwable {
sourceFinderMappingAC_ActiveLaunch();
// Terminate the launch, but don't remove it
doAfterTest();
assertFinderFinds(EXEC_AC_NAME, new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath());
}
/**
* Test the CSourceFinder's use of source lookup when there is a not active
* launch, but a launch configuration that can be used.
*
* In this case, the c general director created as part of the launch gets
* used.
*/
@Test
public void sourceFinderMappingAC_LaunchConfig() throws Throwable {
sourceFinderMappingAC_TerminatedLaunch();
// Remove the launch, so that we can test with the existing
// configuration
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunch[] launches = launchManager.getLaunches();
assertEquals("Unexpected number of launches", 1, launches.length);
assertTrue(launches[0].isTerminated());
launchManager.removeLaunches(launches);
ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations();
assertEquals("Unexpected number of launch configuration", 1, launchConfigurations.length);
assertFinderFinds(EXEC_AC_NAME, new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath());
}
/**
* Test that CSourceFinder works with the common source director, i.e. no
* launches or launch configs in place.
*/
@Test
public void sourceFinderMappingAC_CommonLocator() throws Throwable {
assertFinderDoesNotFind(EXEC_AC_NAME, new File(BUILD_PATH, SOURCE_NAME).getAbsolutePath());
doMappingInCommon(true);
try {
assertFinderFinds(EXEC_AC_NAME, new File(SOURCE_PATH, SOURCE_NAME).getAbsolutePath());
} finally {
restoreCommonToDefault();
}
assertFinderDoesNotFind(EXEC_AC_NAME, new File(BUILD_PATH, SOURCE_NAME).getAbsolutePath());
}
}

View file

@ -20,18 +20,84 @@ import org.junit.runner.RunWith;
@RunWith(BackgroundRunner.class)
public class SourceLookupTest_6_6 extends SourceLookupTest {
@Override
protected void setGdbVersion() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_6_6);
}
@Override
protected void setExeNames() {
EXEC_AC_NAME = "SourceLookupDwarf2AC.exe"; //$NON-NLS-1$
EXEC_AN_NAME = "SourceLookupDwarf2AN.exe"; //$NON-NLS-1$
EXEC_RC_NAME = "SourceLookupDwarf2RC.exe"; //$NON-NLS-1$
EXEC_RN_NAME = "SourceLookupDwarf2RN.exe"; //$NON-NLS-1$
EXEC_NAME = "SourceLookupDwarf2.exe"; //$NON-NLS-1$
}
/**
* For details on the ignore, see {@link SourceLookupTest_7_6#sourceMapping()}
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMapping() throws Throwable {
super.sourceMapping();
public void sourceMappingAC() throws Throwable {
super.sourceMappingAC();
}
/**
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMappingAN() throws Throwable {
super.sourceMappingAN();
}
/**
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMappingRC() throws Throwable {
super.sourceMappingRC();
}
/**
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMappingRN() throws Throwable {
super.sourceMappingRN();
}
/**
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingBreakpointsAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMappingBreakpointsAC() throws Throwable {
super.sourceMappingBreakpointsAC();
}
/**
* For details on the ignore, see
* {@link SourceLookupTest_7_6#sourceMappingBreakpointsAC()}
*/
@Ignore("Only works starting with GDB 7.6")
@Test
@Override
public void sourceMappingBreakpointsRC() throws Throwable {
super.sourceMappingBreakpointsRC();
}
}

View file

@ -88,6 +88,7 @@ public class TraceFileTest_7_4 extends BaseTestCase {
@Override
public void doBeforeTest() throws Exception {
removeTeminatedLaunchesBeforeTest();
// Suppress settings of the launch attributes and launching.
// Each test sets its own launch attributes
}

View file

@ -17,8 +17,18 @@ import org.junit.runner.RunWith;
@RunWith(BackgroundRunner.class)
public class SourceLookupTest_7_5 extends SourceLookupTest_7_4 {
@Override
protected void setGdbVersion() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_5);
}
@Override
protected void setExeNames() {
EXEC_AC_NAME = "SourceLookupAC.exe"; //$NON-NLS-1$
EXEC_AN_NAME = "SourceLookupAN.exe"; //$NON-NLS-1$
EXEC_RC_NAME = "SourceLookupRC.exe"; //$NON-NLS-1$
EXEC_RN_NAME = "SourceLookupRN.exe"; //$NON-NLS-1$
EXEC_NAME = "SourceLookup.exe"; //$NON-NLS-1$
}
}

View file

@ -44,8 +44,60 @@ public class SourceLookupTest_7_6 extends SourceLookupTest_7_5 {
*/
@Test
@Override
public void sourceMapping() throws Throwable {
super.sourceMapping();
public void sourceMappingAC() throws Throwable {
super.sourceMappingAC();
}
/**
* For details, see {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Test
@Override
public void sourceMappingAN() throws Throwable {
super.sourceMappingAN();
}
/**
* For details, see {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Test
@Override
public void sourceMappingRC() throws Throwable {
super.sourceMappingRC();
}
/**
* For details, see {@link SourceLookupTest_7_6#sourceMappingAC()}
*/
@Test
@Override
public void sourceMappingRN() throws Throwable {
super.sourceMappingRN();
}
/**
* Support for inserting breakpoints on the build fullpath of a filename was
* added in GDB 7.6 along with other changes to fullname handling. (It was
* in 7.6 that fullname started being reported all the time, even if not
* resolved. See associated gdb/NEWS item:
* https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=
* ec83d2110de6831ac2ed0e5a56dc33c60a477eb6 although you have to dig quite
* deep on these changes.)
*/
@Test
@Override
public void sourceMappingBreakpointsAC() throws Throwable {
super.sourceMappingBreakpointsAC();
}
/**
* For details, see
* {@link SourceLookupTest_7_6#sourceMappingBreakpointsAC()}
*/
@Test
@Override
public void sourceMappingBreakpointsRC() throws Throwable {
super.sourceMappingBreakpointsRC();
}
/**

View file

@ -11,6 +11,7 @@
<unit id="org.mockito" version="0.0.0"/>
<unit id="org.hamcrest.core" version="0.0.0"/>
<unit id="com.google.gson" version="0.0.0"/>
<unit id="org.easymock" version="0.0.0"/>
<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20150519210750/repository/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">