mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-08 08:45:44 +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_start;
|
||||||
ThreadBarrier *barrier_finish;
|
ThreadBarrier *barrier_finish;
|
||||||
ThreadSemaphore *sem_start;
|
ThreadSemaphore *sem_start;
|
||||||
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ThreadRet THREAD_CALL_CONV PrintHello(void *void_arg)
|
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_start = args->barrier_start;
|
||||||
ThreadBarrier *barrier_finish = args->barrier_finish;
|
ThreadBarrier *barrier_finish = args->barrier_finish;
|
||||||
ThreadSemaphore *sem_start = args->sem_start;
|
ThreadSemaphore *sem_start = args->sem_start;
|
||||||
|
const char *name = args->name;
|
||||||
|
|
||||||
/* Indicate to main thread that the thread is started. */
|
/* Indicate to main thread that the thread is started. */
|
||||||
ThreadSemaphorePut(sem_start);
|
ThreadSemaphorePut(sem_start);
|
||||||
|
|
||||||
printf("Hello World! It's me, thread #%d!\n", thread_id);
|
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. */
|
/* Make sure that all threads are started before the breakpoint in main hits. */
|
||||||
ThreadBarrierWait(barrier_start);
|
ThreadBarrierWait(barrier_start);
|
||||||
|
|
||||||
|
@ -43,6 +47,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ThreadHandle threads[NUM_THREADS];
|
ThreadHandle threads[NUM_THREADS];
|
||||||
struct PrintHelloArgs args[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. */
|
/* Used to make rendez-vous points between all threads. */
|
||||||
ThreadBarrier barrier_start;
|
ThreadBarrier barrier_start;
|
||||||
|
@ -65,10 +70,11 @@ int main(int argc, char *argv[])
|
||||||
args[t].barrier_start = &barrier_start;
|
args[t].barrier_start = &barrier_start;
|
||||||
args[t].barrier_finish = &barrier_finish;
|
args[t].barrier_finish = &barrier_finish;
|
||||||
args[t].sem_start = &sem_start;
|
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");
|
printf("Error: StartThread failed.\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -83,7 +89,7 @@ int main(int argc, char *argv[])
|
||||||
/* Let the threads continue to the 'critical' section> */
|
/* Let the threads continue to the 'critical' section> */
|
||||||
ThreadBarrierWait(&barrier_start);
|
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);
|
SLEEP(30);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
#define THREADPTHREAD_H
|
#define THREADPTHREAD_H
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <sys/prctl.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* Thread functions */
|
/* Thread functions */
|
||||||
|
|
||||||
|
@ -55,4 +54,9 @@ static int ThreadSemaphoreDestroy(ThreadSemaphore *sem)
|
||||||
return sem_destroy(sem) == 0;
|
return sem_destroy(sem) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ThreadSetName(const char *name)
|
||||||
|
{
|
||||||
|
return prctl(PR_SET_NAME, name, 0, 0, 0) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // THREADPTHREAD_H
|
#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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
* Ericsson AB - Initial implementation of Test cases
|
* 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
|
* 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) - Make canRestart and restart throw Exception instead of Throwable.
|
||||||
|
* Simon Marchi (Ericsson) - Add getThreadData.
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.tests.dsf.gdb.framework;
|
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.IFormattedValues.IFormattedDataDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
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.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.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
|
||||||
|
@ -480,6 +482,26 @@ public class SyncUtil {
|
||||||
return query.get(500, TimeUnit.MILLISECONDS);
|
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)
|
public static IExpressionDMContext createExpression(final IDMContext parentCtx, final String expression)
|
||||||
throws Throwable {
|
throws Throwable {
|
||||||
Callable<IExpressionDMContext> callable = new Callable<IExpressionDMContext>() {
|
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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Ericsson AB - Initial implementation of Test cases
|
* 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;
|
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.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
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.IProcesses.IThreadDMData;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
@ -49,7 +48,7 @@ public class GDBProcessesTest extends BaseTestCase {
|
||||||
* 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 SOURCE_NAME = "MultiThread.cc";
|
||||||
|
|
||||||
private DsfSession fSession;
|
private DsfSession fSession;
|
||||||
private DsfServicesTracker fServicesTracker;
|
private DsfServicesTracker fServicesTracker;
|
||||||
|
@ -152,46 +151,28 @@ public class GDBProcessesTest extends BaseTestCase {
|
||||||
* getThreadData() for multiple threads
|
* getThreadData() for multiple threads
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void getThreadData() throws InterruptedException, ExecutionException, TimeoutException {
|
public void getThreadData() throws Throwable {
|
||||||
|
// Start all threads, stop when they are all started
|
||||||
|
SyncUtil.runToLine(SOURCE_NAME, MIRunControlTest.LINE_MAIN_ALL_THREADS_STARTED);
|
||||||
|
|
||||||
final String THREAD_ID = "1";
|
IThreadDMData mainThreadData = SyncUtil.getThreadData(1);
|
||||||
final DataRequestMonitor<IThreadDMData> rm =
|
|
||||||
new DataRequestMonitor<IThreadDMData>(fSession.getExecutor(), null) {
|
|
||||||
@Override
|
|
||||||
protected void handleCompleted() {
|
|
||||||
if (isSuccess()) {
|
|
||||||
fWait.setReturnInfo(getData());
|
|
||||||
}
|
|
||||||
fWait.waitFinished(getStatus());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Test that thread id is only a series of numbers
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Thread id is only a series of numbers
|
|
||||||
Pattern pattern = Pattern.compile("\\d*", Pattern.MULTILINE); //$NON-NLS-1$
|
Pattern pattern = Pattern.compile("\\d*", Pattern.MULTILINE); //$NON-NLS-1$
|
||||||
Matcher matcher = pattern.matcher(threadData.getId());
|
Matcher matcher = pattern.matcher(mainThreadData.getId());
|
||||||
assertTrue("Thread ID is a series of number", matcher.find());
|
assertTrue("Thread ID is a series of number", matcher.matches());
|
||||||
|
|
||||||
// Check thread name
|
// Check the thread names. We did not change the main thread's name, so
|
||||||
String expectedThreadName = threadNamesSupported() ? EXEC_NAME : "";
|
// it should be the same as the executable name.
|
||||||
assertEquals("main thread's name is wrong", expectedThreadName, threadData.getName());
|
final String names[] = { EXEC_NAME, "monday", "tuesday", "wednesday",
|
||||||
|
"thursday", "friday" };
|
||||||
|
|
||||||
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
|
* Ericsson AB - Initial implementation of Test cases
|
||||||
* Simon Marchi (Ericsson) - Add and use runningOnWindows().
|
* Simon Marchi (Ericsson) - Add and use runningOnWindows().
|
||||||
* Simon Marchi (Ericsson) - Adapt test code to thread platform compatibility layer.
|
* 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;
|
package org.eclipse.cdt.tests.dsf.gdb.tests;
|
||||||
|
|
||||||
|
@ -85,15 +86,15 @@ public class MIRunControlTest extends BaseTestCase {
|
||||||
private IExecutionDMContext fThreadExecDmc;
|
private IExecutionDMContext fThreadExecDmc;
|
||||||
|
|
||||||
// line numbers in MultiThread.cc
|
// line numbers in MultiThread.cc
|
||||||
static final int LINE_MAIN_BEFORE_THREAD_START = 69; // Just before StartThread
|
static final int LINE_MAIN_BEFORE_THREAD_START = 75; // 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_AFTER_THREAD_START = 86; // 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_ALL_THREADS_STARTED = 92; // Where all threads are guaranteed to be started.
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Path to executable
|
* Path to executable
|
||||||
*/
|
*/
|
||||||
private static final String EXEC_PATH = "data/launch/bin/";
|
private static final String EXEC_PATH = "data/launch/bin/";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name of the executable
|
* Name of the executable
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue