blob: a48f69b3ac2341cb5d946f25f4a3b51417efb8b1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 Nokia 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:
* Nokia - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.edc.debugger.tests;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Breakpoints;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
import org.eclipse.cdt.debug.edc.services.Stack;
import org.eclipse.cdt.debug.edc.tests.EDCTestPlugin;
import org.eclipse.cdt.debug.edc.tests.TestReflectionHelper;
import org.eclipse.cdt.debug.edc.tests.TestUtils;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.tm.tcf.services.IRunControl;
public class RunControlDMCSubclass extends BaseLaunchTest {
private static final String bareDMC_id = "testBareDeviceExcecutionDMC"; //$NON-NLS-1$
private static final String dbg_derived_types_cpp
= "C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp"; //$NON-NLS-1$
private static final String unitTestRCExeDMCContextException
= "unitTestRunControlExecutionDMCContextException"; //$NON-NLS-1$
private RunControl runControlService;
private Breakpoints breakpointsService;
private IStack stackService;
@Override
protected String getExeFileName() {
// This is the executable built by Cygwin gcc 3.4.4
// All source files are built from this folder:
// "C:\\myprog\\BlackFlagWascana\\src\\"
// Note we don't need any source file to perform the test.
//
// used because the locations of certain line numbers are known,
// not because there's no hardcoded break
return "BlackFlagMinGW_NoHardcodedBreak.exe"; //$NON-NLS-1$
}
@Override
protected IStack getStackService() {
return stackService;
}
@Override
protected boolean getStopAtMain() {
return true;
}
@Before
public void launch() throws Exception {
basicLaunch();
EDCServicesTracker edcTracker
= new EDCServicesTracker(EDCDebugger.getBundleContext(), session.getId());
Assert.assertNotNull(edcTracker);
runControlService = edcTracker.getService(RunControl.class);
Assert.assertNotNull(runControlService);
stackService = edcTracker.getService(Stack.class);
Assert.assertNotNull(stackService);
breakpointsService = edcTracker.getService(Breakpoints.class);
Assert.assertNotNull(breakpointsService);
}
@After
public void shutdown() {
threadDMC.purgeFromDebugger();
TestUtils.shutdownDebugSession(launch, session);
session = null;
}
@Test
public void testBareDeviceExecutionDMC() throws Exception {
Map<String, Object> bdeDMCProps = new HashMap<String, Object>();
bdeDMCProps.put(RunControl.PROP_IS_CONTAINER, false);
bdeDMCProps.put(RunControl.BareDeviceExecutionDMC.PROP_ID, bareDMC_id);
RunControl.BareDeviceExecutionDMC bdeDMC
= runControlService.new BareDeviceExecutionDMC(threadDMC, bdeDMCProps, threadDMC.getTCFContext());
assertNotNull(bdeDMC);
assertTrue(bdeDMC.canDetach());
// DMCSuspendedEvent createSuspendedEvent(StateChangeReason reason, Map<String, Object> properties)
Map<String, Object> cseProps = new HashMap<String, Object>();
cseProps.put("cseKey1", "cseVal1");
cseProps.put("cseKey2", "cseVal2");
RunControl.StateChangeReason scr = RunControl.StateChangeReason.CONTAINER;
Object[] cseArgs = new Object[] {scr, cseProps};
Class<?>[] cseArgClasses = new Class<?>[] {scr.getClass(), Map.class};
RunControl.ContainerSuspendedEvent cse
= (RunControl.ContainerSuspendedEvent)TestReflectionHelper
.objectFromPrivateFunctionWithArgs(bdeDMC, "createSuspendedEvent",
cseArgs, cseArgClasses);
assertNotNull(cse);
Map<String, Object> cseParams = cse.getParams();
assertNotNull(cseParams);
Assert.assertEquals(cseProps, cseParams);
RunControl.IExecutionDMContext[] dmc = cse.getTriggeringContexts();
assertNotNull(dmc);
assertEquals(1, dmc.length);
Assert.assertEquals(bdeDMC, dmc[0]);
// protected DMCResumedEvent createResumedEvent()
RunControl.ContainerResumedEvent cre
= (RunControl.ContainerResumedEvent)TestReflectionHelper
.objectFromPrivateFunctionWithArgs(bdeDMC, "createResumedEvent", null);
assertNotNull(cre);
dmc = cre.getTriggeringContexts();
assertNotNull(dmc);
assertEquals(1, dmc.length);
Assert.assertEquals(bdeDMC, dmc[0]);
}
@Test
public void testExecutionDMCStepOut() throws Exception {
waitRunToLine(runControlService, dbg_derived_types_cpp, 57);
// set this so it stops someplace, even if it's after the expected step out point
setTempBreakpoint(breakpointsService, dbg_derived_types_cpp, 288);
// public abstract class ExectionDMC { protected void stepOut(RequestMonitor) }
final Class<?>[] stepOutArgClasses = new Class<?>[] {RequestMonitor.class};
Query<IStatus> query = new Query<IStatus>() {
@Override
protected void execute(final DataRequestMonitor<IStatus> drm) {
ExecutionDMC exeDMC = DMContexts.getAncestorOfType(threadDMC, ExecutionDMC.class);
Object[] stepOutArgs = new Object[] {drm};
try {
TestReflectionHelper.objectFromPrivateFunctionWithArgs(
exeDMC, ExecutionDMC.class, "stepOut", stepOutArgs, stepOutArgClasses);
} catch (InvocationTargetException ite) {
Throwable t = ite.getTargetException();
if ((t instanceof AssertionError)
&& t.getMessage().equals(RunControl.STEP_RETURN_NOT_SUPPORTED)) {
drm.setData(new Status(IStatus.INFO, EDCDebugger.PLUGIN_ID,
RunControl.STEP_RETURN_NOT_SUPPORTED));
} else {
drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
"InvocationTargetException thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$
+ ite.getLocalizedMessage()));
}
drm.done();
} catch (Exception e) {
drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
"exception thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$
+ e.getLocalizedMessage()));
drm.done();
}
}
};
try {
session.getExecutor().execute(query);
} catch (Exception e) {
Assert.fail(e.getLocalizedMessage());
}
IStatus status = query.get(5, TimeUnit.SECONDS);
if (status != null) {
assertTrue(status.getSeverity() == IStatus.INFO);
assertEquals(RunControl.STEP_RETURN_NOT_SUPPORTED, status.getMessage());
} else {
updateSuspendedFrame(200);
assertControlIsAt("dbg_derived_types.cpp", "dbg_derived_types", 286);
}
}
@Test
public void testRootDMC() {
RunControl.RootExecutionDMC rootDMC = runControlService.getRootDMC();
assertNotNull(rootDMC);
assertNull(rootDMC.getSymbolDMContext());
assertFalse(rootDMC.canDetach());
assertFalse(rootDMC.canStep());
}
@Test
public void testThreadDMC() {
assertFalse(threadDMC.canDetach());
ExecutionDMC exeDMC = null;
try {
// first arg is a map of properties, but we expect an immediate assert
exeDMC = threadDMC.contextAdded(null, threadDMC.getTCFContext());
} catch (AssertionError ae) {
// this is expected
}
assertNull(exeDMC);
}
@Test
public void unitTestRunControlGetModelData() throws Exception {
Query<Boolean> query = new Query<Boolean>() {
@Override
protected void execute(final DataRequestMonitor<Boolean> drm) {
runControlService.getModelData(threadDMC, drm);
}
};
session.getExecutor().execute(query);
query.get(2, TimeUnit.SECONDS);
assertTrue(query.isDone());
}
@Test
public void unitTestRunControlStepIntoOneInstruction() throws Exception {
waitRunToLine(runControlService, dbg_derived_types_cpp, 285);
// private void stepOverOneInstruction(ExecutionDMC, IAddress, RequestMonitor)
final Class<?>[] stepIntoArgClasses = new Class<?>[] {ExecutionDMC.class, RequestMonitor.class};
Query<IStatus> query = new Query<IStatus>() {
@Override
protected void execute(final DataRequestMonitor<IStatus> drm) {
Object[] stepIntoArgs = new Object[] {threadDMC, drm};
try {
TestReflectionHelper.objectFromPrivateFunctionWithArgs(
runControlService, "stepIntoOneInstruction", stepIntoArgs, stepIntoArgClasses);
} catch (Exception e) {
drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
"exception thrown invoking RunControl#stepIntoOneInstruction()"//$NON-NLS-1$
+ e.getLocalizedMessage()));
drm.done();
}
}
};
session.getExecutor().execute(query);
query.get(5, TimeUnit.SECONDS);
assertTrue(query.isDone());
updateSuspendedFrame(200);
assertControlIsAt("dbg_derived_types.cpp", "structs", 40);
}
@Test
public void unitTestRunControlStepOverOneInstruction() throws Exception {
waitRunToLine(runControlService, dbg_derived_types_cpp, 285);
final IAddress line285Addr = waitGetLineAddress(dbg_derived_types_cpp, 285);
final Class<?>[] stepOverArgClasses = new Class<?>[] {ExecutionDMC.class, IAddress.class, RequestMonitor.class};
// private void stepOverOneInstruction(ExecutionDMC, IAddress pcAddress, RequestMonitor)
Query<Boolean> query = new Query<Boolean>() {
@Override
protected void execute(final DataRequestMonitor<Boolean> drm) {
Object[] stepOverArgs = new Object[] {threadDMC, line285Addr, drm};
try {
TestReflectionHelper.objectFromPrivateFunctionWithArgs(
runControlService, "stepOverOneInstruction", stepOverArgs, stepOverArgClasses);
} catch (Exception e) {
drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
"exception thrown invoking RunControl#stepOverOneInstruction()"//$NON-NLS-1$
+ e.getLocalizedMessage()));
drm.done();
}
}
};
session.getExecutor().execute(query);
query.get(5, TimeUnit.SECONDS);
assertTrue(query.isDone());
updateSuspendedFrame(100);
assertControlIsAt("dbg_derived_types.cpp", "dbg_derived_types", 286);
}
@Test
public void coverageRunControlGetSteppingStartTime() {
long steppingStartTime = RunControl.getSteppingStartTime();
if (RunControl.timeStepping()) {
} else {
assertEquals(0, steppingStartTime);
}
}
@Test
public void coverageRunControlRunListener() throws Exception {
IRunControl.RunControlListener runListener
= (IRunControl.RunControlListener)
TestReflectionHelper.getPrivateField("runListener", runControlService);
assertNotNull(runListener);
// the following will also test ExecutionDMC#contextException()
runListener.contextException(threadDMC.getID(), unitTestRCExeDMCContextException);
Thread.sleep(400); // wait a little for the exception to propagate
String propMessage = (String)threadDMC.getProperty(RunControl.PROP_MESSAGE);
assertEquals(unitTestRCExeDMCContextException, propMessage);
// the next 3 are empty and expected to do nothing
runListener.containerResumed(null);
runListener.containerSuspended(null, null, null, null, null);
runListener.contextChanged(null);
// resume our thread
assertTrue(threadDMC.isSuspended());
runListener.contextResumed(threadDMC.getID());
Thread.sleep(400); // wait a little for it to get re-started
assertFalse(threadDMC.isSuspended());
}
}