mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 17:35:35 +02:00
debug tests: Add test for thread name
This patch adds SyncUtil.getThreadData to make it easy to get the thread data from the gdb thread number. Change-Id: I948a8b87cc3afa64f3d73de23d4ace12ef4c0c1a Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca> Reviewed-on: https://git.eclipse.org/r/36870 Reviewed-by: Alvaro Sanchez-Leon <alvsan09@gmail.com> Tested-by: Alvaro Sanchez-Leon <alvsan09@gmail.com>
This commit is contained in:
parent
daa20f98b4
commit
79c6c7d775
5 changed files with 66 additions and 52 deletions
|
@ -11,6 +11,7 @@ struct PrintHelloArgs {
|
|||
ThreadBarrier *barrier_start;
|
||||
ThreadBarrier *barrier_finish;
|
||||
ThreadSemaphore *sem_start;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static ThreadRet THREAD_CALL_CONV PrintHello(void *void_arg)
|
||||
|
@ -20,12 +21,15 @@ static ThreadRet THREAD_CALL_CONV PrintHello(void *void_arg)
|
|||
ThreadBarrier *barrier_start = args->barrier_start;
|
||||
ThreadBarrier *barrier_finish = args->barrier_finish;
|
||||
ThreadSemaphore *sem_start = args->sem_start;
|
||||
const char *name = args->name;
|
||||
|
||||
/* Indicate to main thread that the thread is started. */
|
||||
ThreadSemaphorePut(sem_start);
|
||||
|
||||
printf("Hello World! It's me, thread #%d!\n", thread_id);
|
||||
|
||||
ThreadSetName(name);
|
||||
|
||||
/* Make sure that all threads are started before the breakpoint in main hits. */
|
||||
ThreadBarrierWait(barrier_start);
|
||||
|
||||
|
@ -43,6 +47,7 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
ThreadHandle threads[NUM_THREADS];
|
||||
struct PrintHelloArgs args[NUM_THREADS];
|
||||
const char *thread_names[NUM_THREADS] = {"monday", "tuesday", "wednesday", "thursday", "friday"};
|
||||
|
||||
/* Used to make rendez-vous points between all threads. */
|
||||
ThreadBarrier barrier_start;
|
||||
|
@ -65,10 +70,11 @@ int main(int argc, char *argv[])
|
|||
args[t].barrier_start = &barrier_start;
|
||||
args[t].barrier_finish = &barrier_finish;
|
||||
args[t].sem_start = &sem_start;
|
||||
args[t].name = thread_names[t];
|
||||
|
||||
int ret = StartThread(PrintHello, &args[t], &threads[t]);
|
||||
int ret = StartThread(PrintHello, &args[t], &threads[t]); /* Breakpoint LINE_MAIN_BEFORE_THREAD_START */
|
||||
|
||||
if (!ret)
|
||||
if (!ret) /* Breakpoint LINE_MAIN_AFTER_THREAD_START */
|
||||
{
|
||||
printf("Error: StartThread failed.\n");
|
||||
exit(-1);
|
||||
|
@ -83,7 +89,7 @@ int main(int argc, char *argv[])
|
|||
/* Let the threads continue to the 'critical' section> */
|
||||
ThreadBarrierWait(&barrier_start);
|
||||
|
||||
printf("In main thread, all threads created.\n"); /* main breakpoint here */
|
||||
printf("In main thread, all threads created.\n"); /* Breakpoint LINE_MAIN_ALL_THREADS_STARTED */
|
||||
|
||||
SLEEP(30);
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#define THREADPTHREAD_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
/* Thread functions */
|
||||
|
||||
|
@ -55,4 +54,9 @@ static int ThreadSemaphoreDestroy(ThreadSemaphore *sem)
|
|||
return sem_destroy(sem) == 0;
|
||||
}
|
||||
|
||||
static int ThreadSetName(const char *name)
|
||||
{
|
||||
return prctl(PR_SET_NAME, name, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
#endif // THREADPTHREAD_H
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2014 Ericsson and others.
|
||||
* Copyright (c) 2007, 2015 Ericsson and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -9,6 +9,7 @@
|
|||
* Ericsson AB - Initial implementation of Test cases
|
||||
* Alvaro Sanchez-Leon (Ericsson) - Bug 437562 - Split the dsf-gdb tests to a plug-in and fragment pair
|
||||
* Simon Marchi (Ericsson) - Make canRestart and restart throw Exception instead of Throwable.
|
||||
* Simon Marchi (Ericsson) - Add getThreadData.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.gdb.framework;
|
||||
|
||||
|
@ -43,6 +44,7 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
|||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
||||
|
@ -480,6 +482,26 @@ public class SyncUtil {
|
|||
return query.get(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static IThreadDMData getThreadData(final int threadId)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
final IProcessDMContext processContext = DMContexts.getAncestorOfType(
|
||||
SyncUtil.getContainerContext(), IProcessDMContext.class);
|
||||
|
||||
Query<IThreadDMData> query = new Query<IThreadDMData>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<IThreadDMData> rm) {
|
||||
IThreadDMContext threadDmc = fProcessesService
|
||||
.createThreadContext(processContext,
|
||||
Integer.toString(threadId));
|
||||
fProcessesService.getExecutionData(threadDmc, rm);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
fSession.getExecutor().execute(query);
|
||||
return query.get(500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public static IExpressionDMContext createExpression(final IDMContext parentCtx, final String expression)
|
||||
throws Throwable {
|
||||
Callable<IExpressionDMContext> callable = new Callable<IExpressionDMContext>() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2014 Ericsson and others.
|
||||
* Copyright (c) 2009, 2015 Ericsson and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
* Contributors:
|
||||
* Ericsson AB - Initial implementation of Test cases
|
||||
* Simon Marchi (Ericsson) - Check for thread name support.
|
||||
* Simon Marchi (Ericsson) - Check for thread name support, add thread name test.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.gdb.tests;
|
||||
|
||||
|
@ -25,7 +25,6 @@ import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
|||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
|
@ -49,7 +48,7 @@ public class GDBProcessesTest extends BaseTestCase {
|
|||
* Name of the executable
|
||||
*/
|
||||
private static final String EXEC_NAME = "MultiThread.exe";
|
||||
|
||||
private static final String SOURCE_NAME = "MultiThread.cc";
|
||||
|
||||
private DsfSession fSession;
|
||||
private DsfServicesTracker fServicesTracker;
|
||||
|
@ -152,46 +151,28 @@ public class GDBProcessesTest extends BaseTestCase {
|
|||
* getThreadData() for multiple threads
|
||||
*/
|
||||
@Test
|
||||
public void getThreadData() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
|
||||
final String THREAD_ID = "1";
|
||||
final DataRequestMonitor<IThreadDMData> rm =
|
||||
new DataRequestMonitor<IThreadDMData>(fSession.getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
fWait.setReturnInfo(getData());
|
||||
}
|
||||
fWait.waitFinished(getStatus());
|
||||
}
|
||||
};
|
||||
public void getThreadData() throws Throwable {
|
||||
// Start all threads, stop when they are all started
|
||||
SyncUtil.runToLine(SOURCE_NAME, MIRunControlTest.LINE_MAIN_ALL_THREADS_STARTED);
|
||||
|
||||
IThreadDMData mainThreadData = SyncUtil.getThreadData(1);
|
||||
|
||||
final IProcessDMContext processContext = DMContexts.getAncestorOfType(SyncUtil.getContainerContext(), IProcessDMContext.class);
|
||||
fProcService.getExecutor().submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IThreadDMContext threadDmc = fProcService.createThreadContext(processContext, THREAD_ID);
|
||||
fProcService.getExecutionData(threadDmc, rm);
|
||||
}
|
||||
});
|
||||
// Test that thread id is only a series of numbers
|
||||
Pattern pattern = Pattern.compile("\\d*", Pattern.MULTILINE); //$NON-NLS-1$
|
||||
Matcher matcher = pattern.matcher(mainThreadData.getId());
|
||||
assertTrue("Thread ID is a series of number", matcher.matches());
|
||||
|
||||
// Wait for the operation to complete and validate success.
|
||||
fWait.waitUntilDone(TestsPlugin.massageTimeout(2000));
|
||||
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||
|
||||
IThreadDMData threadData = (IThreadDMData)fWait.getReturnInfo();
|
||||
Assert.assertNotNull("Thread data not returned for thread id = " + THREAD_ID, threadData);
|
||||
// Check the thread names. We did not change the main thread's name, so
|
||||
// it should be the same as the executable name.
|
||||
final String names[] = { EXEC_NAME, "monday", "tuesday", "wednesday",
|
||||
"thursday", "friday" };
|
||||
|
||||
// Thread id is only a series of numbers
|
||||
Pattern pattern = Pattern.compile("\\d*", Pattern.MULTILINE); //$NON-NLS-1$
|
||||
Matcher matcher = pattern.matcher(threadData.getId());
|
||||
assertTrue("Thread ID is a series of number", matcher.find());
|
||||
|
||||
// Check thread name
|
||||
String expectedThreadName = threadNamesSupported() ? EXEC_NAME : "";
|
||||
assertEquals("main thread's name is wrong", expectedThreadName, threadData.getName());
|
||||
|
||||
fWait.waitReset();
|
||||
// Check that we have correct data for PrintHello
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
IThreadDMData threadData = SyncUtil.getThreadData(i);
|
||||
String name = threadData.getName();
|
||||
String expectedName = threadNamesSupported() ? names[i - 1] : "";
|
||||
assertEquals("Thread name of thread " + i, expectedName, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Ericsson AB - Initial implementation of Test cases
|
||||
* Simon Marchi (Ericsson) - Add and use runningOnWindows().
|
||||
* Simon Marchi (Ericsson) - Adapt test code to thread platform compatibility layer.
|
||||
* Simon Marchi (Ericsson) - Change breakpoint line numbers.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.gdb.tests;
|
||||
|
||||
|
@ -85,21 +86,21 @@ public class MIRunControlTest extends BaseTestCase {
|
|||
private IExecutionDMContext fThreadExecDmc;
|
||||
|
||||
// line numbers in MultiThread.cc
|
||||
static final int LINE_MAIN_BEFORE_THREAD_START = 69; // Just before StartThread
|
||||
static final int LINE_MAIN_AFTER_THREAD_START = 80; // Just after StartThread, where the thread is guaranteed to be started.
|
||||
static final int LINE_MAIN_ALL_THREADS_STARTED = 88; // Where all threads are guaranteed to be started.
|
||||
|
||||
static final int LINE_MAIN_BEFORE_THREAD_START = 75; // Just before StartThread
|
||||
static final int LINE_MAIN_AFTER_THREAD_START = 86; // Just after StartThread, where the thread is guaranteed to be started.
|
||||
static final int LINE_MAIN_ALL_THREADS_STARTED = 92; // Where all threads are guaranteed to be started.
|
||||
|
||||
/*
|
||||
* Path to executable
|
||||
*/
|
||||
private static final String EXEC_PATH = "data/launch/bin/";
|
||||
|
||||
/*
|
||||
* Name of the executable
|
||||
*/
|
||||
private static final String EXEC_NAME = "MultiThread.exe";
|
||||
private static final String SOURCE_NAME = "MultiThread.cc";
|
||||
|
||||
|
||||
@Override
|
||||
public void doBeforeTest() throws Exception {
|
||||
super.doBeforeTest();
|
||||
|
|
Loading…
Add table
Reference in a new issue