mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
debug tests: Introduce line "tags" to avoid hardcoding line numbers
Hardcoding line numbers in tests make it a pain to modify the test sources. The approach adopted in the gdb testsuite is to look for a specific string in the source file and return the line number where it is found. I made a similar system for the CDT debug tests. I dubbed this system breakpoint tags, a tag being the string we look for in the source file. I modified the MIRunControlTest as an example, as well as GDBProcessesTest and MIRegistersTest because they are re-using the same breakpoints. SOURCE_PATH and EXEC_PATH were duplicated in many test cases, so I factored them in BaseTestCase. Change-Id: Id1e64b2064914005ab1d87e16704866aa1c8b9ec Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca> Reviewed-on: https://git.eclipse.org/r/36872 Tested-by: Hudson CI Reviewed-by: Elena Laskavaia <elaskavaia.cdt@gmail.com>
This commit is contained in:
parent
c0590c67c1
commit
d0e93b665b
5 changed files with 98 additions and 29 deletions
|
@ -12,11 +12,16 @@
|
||||||
package org.eclipse.cdt.tests.dsf.gdb.framework;
|
package org.eclipse.cdt.tests.dsf.gdb.framework;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
||||||
|
@ -66,6 +71,12 @@ import org.junit.rules.Timeout;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("restriction")
|
@SuppressWarnings("restriction")
|
||||||
public class BaseTestCase {
|
public class BaseTestCase {
|
||||||
|
/*
|
||||||
|
* Path to executable
|
||||||
|
*/
|
||||||
|
protected static final String EXEC_PATH = "data/launch/bin/";
|
||||||
|
protected static final String SOURCE_PATH = "data/launch/src/";
|
||||||
|
|
||||||
// Timeout value for each individual test
|
// Timeout value for each individual test
|
||||||
private final static int TEST_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds
|
private final static int TEST_TIMEOUT = 5 * 60 * 1000; // 5 minutes in milliseconds
|
||||||
|
|
||||||
|
@ -103,6 +114,8 @@ public class BaseTestCase {
|
||||||
|
|
||||||
private static boolean fgStatusHandlersEnabled = true;
|
private static boolean fgStatusHandlersEnabled = true;
|
||||||
|
|
||||||
|
private static HashMap<String, Integer> fTagLocations = new HashMap<>();
|
||||||
|
|
||||||
public GdbLaunch getGDBLaunch() { return fLaunch; }
|
public GdbLaunch getGDBLaunch() { return fLaunch; }
|
||||||
|
|
||||||
public void setLaunchAttribute(String key, Object value) {
|
public void setLaunchAttribute(String key, Object value) {
|
||||||
|
@ -197,8 +210,8 @@ public class BaseTestCase {
|
||||||
setLaunchAttributes();
|
setLaunchAttributes();
|
||||||
doLaunch();
|
doLaunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setLaunchAttributes() {
|
protected void setLaunchAttributes() {
|
||||||
// Clear all launch attributes before starting a new test
|
// Clear all launch attributes before starting a new test
|
||||||
launchAttributes = new HashMap<String, Object>();
|
launchAttributes = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
@ -225,6 +238,64 @@ public class BaseTestCase {
|
||||||
launchAttributes.putAll(globalLaunchAttributes);
|
launchAttributes.putAll(globalLaunchAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a set of tags (strings) to find in sourceFile, populate the
|
||||||
|
* fTagLocations map with the line numbers where they are found.
|
||||||
|
*
|
||||||
|
* @param sourceName The path of the source file, relative to {@link #SOURCE_PATH}.
|
||||||
|
* @param tags Strings to find in sourceFile.
|
||||||
|
* @throws IOException If sourceFile is not found or can't be read.
|
||||||
|
* @throws RuntimeException If one or more tags are not found in sourceFile.
|
||||||
|
*/
|
||||||
|
protected void resolveLineTagLocations(String sourceName,
|
||||||
|
String... tags) throws IOException {
|
||||||
|
try (BufferedReader reader =
|
||||||
|
new BufferedReader(new FileReader(SOURCE_PATH + sourceName))) {
|
||||||
|
Set<String> tagsToFind = new HashSet<>(Arrays.asList(tags));
|
||||||
|
String line;
|
||||||
|
int lineNumber = 1;
|
||||||
|
|
||||||
|
fTagLocations.clear();
|
||||||
|
|
||||||
|
line = reader.readLine();
|
||||||
|
while (line != null) {
|
||||||
|
for (String tag : tagsToFind) {
|
||||||
|
if (line.contains(tag)) {
|
||||||
|
fTagLocations.put(tag, lineNumber);
|
||||||
|
tagsToFind.remove(tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineNumber++;
|
||||||
|
line = reader.readLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure all tags have been found */
|
||||||
|
if (tagsToFind.size() > 0) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Some tags were not found in " + sourceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the source line number that contains the specified tag. In order to
|
||||||
|
* get an interesting result, {@link #resolveLineTagLocations} must be
|
||||||
|
* called prior to calling this function.
|
||||||
|
*
|
||||||
|
* @param tag Tag for which to get the source line.
|
||||||
|
* @return The line number corresponding to tag.
|
||||||
|
* @throws NoSuchElementException if the tag does not exist.
|
||||||
|
*/
|
||||||
|
protected int getLineForTag(String tag) {
|
||||||
|
if (!fTagLocations.containsKey(tag)) {
|
||||||
|
throw new NoSuchElementException("tag " + tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fTagLocations.get(tag);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch GDB. The launch attributes must have been set already.
|
* Launch GDB. The launch attributes must have been set already.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -40,10 +40,6 @@ import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@RunWith(BackgroundRunner.class)
|
@RunWith(BackgroundRunner.class)
|
||||||
public class GDBProcessesTest extends BaseTestCase {
|
public class GDBProcessesTest extends BaseTestCase {
|
||||||
/*
|
|
||||||
* Path to executable
|
|
||||||
*/
|
|
||||||
private static final String EXEC_PATH = "data/launch/bin/";
|
|
||||||
/*
|
/*
|
||||||
* Name of the executable
|
* Name of the executable
|
||||||
*/
|
*/
|
||||||
|
@ -64,7 +60,9 @@ public class GDBProcessesTest extends BaseTestCase {
|
||||||
@Override
|
@Override
|
||||||
public void doBeforeTest() throws Exception {
|
public void doBeforeTest() throws Exception {
|
||||||
super.doBeforeTest();
|
super.doBeforeTest();
|
||||||
|
|
||||||
|
resolveLineTagLocations(SOURCE_NAME, MIRunControlTest.LINE_TAGS);
|
||||||
|
|
||||||
fSession = getGDBLaunch().getSession();
|
fSession = getGDBLaunch().getSession();
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -153,7 +151,7 @@ public class GDBProcessesTest extends BaseTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void getThreadData() throws Throwable {
|
public void getThreadData() throws Throwable {
|
||||||
// Start all threads, stop when they are all started
|
// Start all threads, stop when they are all started
|
||||||
SyncUtil.runToLine(SOURCE_NAME, MIRunControlTest.LINE_MAIN_ALL_THREADS_STARTED);
|
SyncUtil.runToLine(SOURCE_NAME, getLineForTag("LINE_MAIN_ALL_THREADS_STARTED"));
|
||||||
|
|
||||||
IThreadDMData mainThreadData = SyncUtil.getThreadData(1);
|
IThreadDMData mainThreadData = SyncUtil.getThreadData(1);
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ public class MIBreakpointsTest extends BaseTestCase {
|
||||||
// Global constants
|
// Global constants
|
||||||
public static final String PLUGIN_ID = "org.eclipse.cdt.debug.core" ; //$NON-NLS-1$
|
public static final String PLUGIN_ID = "org.eclipse.cdt.debug.core" ; //$NON-NLS-1$
|
||||||
public static final String TEST_APPL = "data/launch/bin/BreakpointTestApp.exe"; //$NON-NLS-1$
|
public static final String TEST_APPL = "data/launch/bin/BreakpointTestApp.exe"; //$NON-NLS-1$
|
||||||
public static final String SOURCE_PATH = "data/launch/src"; //$NON-NLS-1$
|
|
||||||
|
|
||||||
public static final String SOURCE_PROJECT = "MIBreakpointsTest";
|
public static final String SOURCE_PROJECT = "MIBreakpointsTest";
|
||||||
public static final String SOURCE_FOLDER = "src";
|
public static final String SOURCE_FOLDER = "src";
|
||||||
|
|
|
@ -116,16 +116,11 @@ public class MIRegistersTest extends BaseTestCase {
|
||||||
return fRegisterNames;
|
return fRegisterNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Path to executable
|
|
||||||
*/
|
|
||||||
private static final String EXEC_PATH = "data/launch/bin/";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name of the executable
|
* Name of the executable
|
||||||
*/
|
*/
|
||||||
private static final String EXEC_NAME = "MultiThread.exe";
|
private static final String EXEC_NAME = "MultiThread.exe";
|
||||||
private static final String SRC_NAME = "MultiThread.cc";
|
private static final String SOURCE_NAME = "MultiThread.cc";
|
||||||
|
|
||||||
private static final String GROUP_X = "GroupX";
|
private static final String GROUP_X = "GroupX";
|
||||||
private static final String GROUP_Y = "GroupY";
|
private static final String GROUP_Y = "GroupY";
|
||||||
|
@ -143,6 +138,7 @@ public class MIRegistersTest extends BaseTestCase {
|
||||||
super.doBeforeTest();
|
super.doBeforeTest();
|
||||||
|
|
||||||
fSession = getGDBLaunch().getSession();
|
fSession = getGDBLaunch().getSession();
|
||||||
|
resolveLineTagLocations(SOURCE_NAME, MIRunControlTest.LINE_TAGS);
|
||||||
|
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -368,7 +364,8 @@ public class MIRegistersTest extends BaseTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compareRegisterForMultipleExecutionContexts() throws Throwable {
|
public void compareRegisterForMultipleExecutionContexts() throws Throwable {
|
||||||
MIStoppedEvent stoppedEvent = SyncUtil.runToLine(SRC_NAME, MIRunControlTest.LINE_MAIN_ALL_THREADS_STARTED);
|
MIStoppedEvent stoppedEvent = SyncUtil.runToLine(SOURCE_NAME,
|
||||||
|
getLineForTag("LINE_MAIN_ALL_THREADS_STARTED"));
|
||||||
|
|
||||||
// Get the thread IDs
|
// Get the thread IDs
|
||||||
final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(stoppedEvent.getDMContext(), IContainerDMContext.class);
|
final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(stoppedEvent.getDMContext(), IContainerDMContext.class);
|
||||||
|
|
|
@ -85,15 +85,12 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
private IContainerDMContext fContainerDmc;
|
private IContainerDMContext fContainerDmc;
|
||||||
private IExecutionDMContext fThreadExecDmc;
|
private IExecutionDMContext fThreadExecDmc;
|
||||||
|
|
||||||
// line numbers in MultiThread.cc
|
// Breakpoint tags in MultiThread.cc
|
||||||
static final int LINE_MAIN_BEFORE_THREAD_START = 75; // Just before StartThread
|
public static final String[] LINE_TAGS = new String[] {
|
||||||
static final int LINE_MAIN_AFTER_THREAD_START = 86; // Just after StartThread, where the thread is guaranteed to be started.
|
"LINE_MAIN_BEFORE_THREAD_START", // Just before StartThread
|
||||||
static final int LINE_MAIN_ALL_THREADS_STARTED = 92; // Where all threads are guaranteed to be started.
|
"LINE_MAIN_AFTER_THREAD_START", // Just after StartThread
|
||||||
|
"LINE_MAIN_ALL_THREADS_STARTED", // Where all threads are guaranteed to be started.
|
||||||
/*
|
};
|
||||||
* Path to executable
|
|
||||||
*/
|
|
||||||
private static final String EXEC_PATH = "data/launch/bin/";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name of the executable
|
* Name of the executable
|
||||||
|
@ -104,7 +101,9 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
@Override
|
@Override
|
||||||
public void doBeforeTest() throws Exception {
|
public void doBeforeTest() throws Exception {
|
||||||
super.doBeforeTest();
|
super.doBeforeTest();
|
||||||
|
|
||||||
|
resolveLineTagLocations(SOURCE_NAME, LINE_TAGS);
|
||||||
|
|
||||||
final DsfSession session = getGDBLaunch().getSession();
|
final DsfSession session = getGDBLaunch().getSession();
|
||||||
|
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
|
@ -275,7 +274,11 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
getGDBLaunch().getSession(),
|
getGDBLaunch().getSession(),
|
||||||
IStartedDMEvent.class);
|
IStartedDMEvent.class);
|
||||||
|
|
||||||
SyncUtil.runToLine(fContainerDmc, SOURCE_NAME, LINE_MAIN_AFTER_THREAD_START, true);
|
SyncUtil.runToLine(
|
||||||
|
fContainerDmc,
|
||||||
|
SOURCE_NAME,
|
||||||
|
getLineForTag("LINE_MAIN_AFTER_THREAD_START"),
|
||||||
|
true);
|
||||||
|
|
||||||
final IContainerDMContext containerDmc = SyncUtil.getContainerContext();
|
final IContainerDMContext containerDmc = SyncUtil.getContainerContext();
|
||||||
|
|
||||||
|
@ -426,7 +429,8 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
/*
|
/*
|
||||||
* Add a breakpoint
|
* Add a breakpoint
|
||||||
*/
|
*/
|
||||||
SyncUtil.addBreakpoint(SOURCE_NAME + ":" + LINE_MAIN_BEFORE_THREAD_START, false);
|
SyncUtil.addBreakpoint(SOURCE_NAME + ":"
|
||||||
|
+ getLineForTag("LINE_MAIN_BEFORE_THREAD_START"), false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resume till the breakpoint is hit
|
* Resume till the breakpoint is hit
|
||||||
|
@ -681,7 +685,7 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
fRunCtrl.runToLine(fThreadExecDmc, SOURCE_NAME,
|
fRunCtrl.runToLine(fThreadExecDmc, SOURCE_NAME,
|
||||||
LINE_MAIN_ALL_THREADS_STARTED, true,
|
getLineForTag("LINE_MAIN_ALL_THREADS_STARTED"), true,
|
||||||
new RequestMonitor(fRunCtrl.getExecutor(), null) {
|
new RequestMonitor(fRunCtrl.getExecutor(), null) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue