/*******************************************************************************
* 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Ericsson AB - Initial implementation of Test cases
* Simon Marchi (Ericsson) - Check for thread name support, add thread name test.
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase;
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class GDBProcessesTest extends BaseParametrizedTestCase {
/*
* 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;
private IMIProcesses fProcService;
@Override
public void doBeforeTest() throws Exception {
super.doBeforeTest();
resolveLineTagLocations(SOURCE_NAME, MIRunControlTest.LINE_TAGS);
fSession = getGDBLaunch().getSession();
Runnable runnable = new Runnable() {
@Override
public void run() {
fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
fProcService = fServicesTracker.getService(IMIProcesses.class);
}
};
fSession.getExecutor().submit(runnable).get();
}
@Override
public void doAfterTest() throws Exception {
super.doAfterTest();
fProcService = null;
if (fServicesTracker!=null) fServicesTracker.dispose();
}
@Override
protected void setLaunchAttributes() {
super.setLaunchAttributes();
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
EXEC_PATH + EXEC_NAME);
}
@Test
/*
* Get the process data for the current program. Process is executable name in case of GDB back end
*/
public void getProcessData() 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) {
fProcService.getExecutionData(processContext, rm);
}
};
fProcService.getExecutor().execute(query);
/*
* Get process data. Name of the process is the executable name in case of GDB back-end.
*/
IThreadDMData processData = query.get(TestsPlugin.massageTimeout(2000), TimeUnit.MILLISECONDS);
Assert.assertNotNull("No process data is returned for Process DMC", processData);
Assert.assertTrue("Process data should be executable name " + EXEC_NAME +
"but we got " + processData.getName(), processData.getName().contains(EXEC_NAME));
}
/*
* Return whether thread names are reported by the debugger.
*
* This defaults to false, and is overridden for specific versions of gdb.
*/
protected boolean threadNamesSupported() {
return !runningOnWindows() && !isRemoteSession();
}
/*
* getThreadData() for multiple threads
*/
@Test
public void getThreadData() throws Throwable {
assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_3);
// Start the threads one by one to make sure they are discovered by gdb in the right
// order.
for (int i = 0; i < 5; i++) {
SyncUtil.runToLocation(SOURCE_NAME + ":" + getLineForTag("LINE_MAIN_AFTER_THREAD_START"));
}
// We need to get there to make sure that all the threads have their name set.
SyncUtil.runToLocation(SOURCE_NAME + ":" + getLineForTag("LINE_MAIN_ALL_THREADS_STARTED"));
IThreadDMData mainThreadData = SyncUtil.getThreadData(1);
// 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());
// 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" };
// 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);
}
}
}