blob: 2d2c905336504a7044aa6bb7377596d4aa5fa016 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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. Mar, 2010
*******************************************************************************/
package org.eclipse.cdt.debug.edc.debugger.tests;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Breakpoints;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
import org.eclipse.cdt.debug.edc.launch.EDCLaunch;
import org.eclipse.cdt.debug.edc.services.IEDCExecutionDMC;
import org.eclipse.cdt.debug.edc.tests.TestUtils;
import org.eclipse.cdt.debug.edc.tests.TestUtils.Condition;
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.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl2;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.swt.widgets.Display;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
/**
* Test run-to-line, move-to-line and resume-at-line.
*
*/
public class RunAndMoveToLine extends BaseLaunchTest {
protected DsfSession session;
protected ExecutionDMC threadDMC;
protected IFrameDMContext frame;
protected EDCLaunch launch;
protected IStack stackService;
protected Breakpoints breakpointsService;
protected IRunControl2 runControlService;
@Override
protected String getExeFileName() {
// This is the executable built by Cygwin gcc 3.4.4
// All source files are built from this foler:
// "C:\\myprog\\BlackFlagWascana\\src\\"
// Note we don't need any source file to perform the test.
//
return "BlackFlagMinGW_NoHardcodedBreak.exe";
}
@Override
protected void configureLaunchConfiguration(
ILaunchConfigurationWorkingCopy configuration) {
// Make sure it stop at main
configuration.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, true);
configuration.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, "main");
}
@After
public void shutdown() {
TestUtils.shutdownDebugSession(launch, session);
}
/**
* test run-to-line, move-to-line and resume-at-line.
*
* @throws Exception
*/
@Test
public void testRunAndMoveToLine() throws Exception {
TestUtils.showDebugPerspective();
launch = createLaunch();
assertNotNull(launch);
session = TestUtils.waitForSession(launch);
Assert.assertNotNull(session);
getDsfServices();
IEDCExecutionDMC executionDMC = TestUtils.waitForExecutionDMC(session);
Assert.assertNotNull(executionDMC);
updateSuspendedThreadAndFrame(2000);
assertControlIsAt("BlackFlagWascana.cpp", "main", 15);
waitForUIUpdate(2000);
/*
* Now we test control in structs() function of
* dbg_derived_type.cpp in Blackflag.
* Here's the snippet of the source lines in structs():
*
52 lstruct.achar = '1';
53 lstruct.auchar = 2;
54 lstruct.aschar = '3';
55 lstruct.ashort = 4;
56 lstruct.aushort = 5;
57 lstruct.asshort = 6;
58 lstruct.aint = 7;
59 lstruct.auint = 8;
*
* Here's what's done below:
* 1) Run to line 53.
* 2) Move to line 56.
* 3) Run to line 57.
* 4) Set temp breakpoint at line 56
* 5) resume from line 54, which should stop at line 56.
*/
// run to line 53, so "lstruct.achar = '1'" is executed.
waitRunToLine("C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp", 53);
assertControlIsAt("dbg_derived_types.cpp", "structs", 53);
// move to line 56, namely skip line 53, 54 & 55
waitMoveToLine("C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp", 56, false);
assertControlIsAt("dbg_derived_types.cpp", "structs", 56);
// run to line 57, namely line 56 is executed, "aushort" is assigned.
waitRunToLine("C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp", 57);
assertControlIsAt("dbg_derived_types.cpp", "structs", 57);
// Now check which lines are executed by checking which struct fields are set.
assertEquals("49 ('1')", TestUtils.getExpressionValue(session, frame, "lstruct.achar")); // 52
assertEquals("0 ('\\0')", TestUtils.getExpressionValue(session, frame, "lstruct.auchar"));// 53
assertEquals("0 ('\\0')", TestUtils.getExpressionValue(session, frame, "lstruct.aschar"));// 54
assertEquals("0", TestUtils.getExpressionValue(session, frame, "lstruct.ashort")); // 55
assertEquals("5", TestUtils.getExpressionValue(session, frame, "lstruct.aushort")); // 56
assertEquals("0", TestUtils.getExpressionValue(session, frame, "lstruct.asshort")); // 57
// Set temp breakpoint at line 56.
setTempBreakpoint(threadDMC, breakpointsService, "C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp", 56);
// Resume from line 54, namely execute line 54, 55.
waitMoveToLine("C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp", 54, true);
assertControlIsAt("dbg_derived_types.cpp", "structs", 56);
assertEquals("0 ('\\0')", TestUtils.getExpressionValue(session, frame, "lstruct.auchar"));// 53
assertEquals("51 ('3')", TestUtils.getExpressionValue(session, frame, "lstruct.aschar"));// 54
assertEquals("4", TestUtils.getExpressionValue(session, frame, "lstruct.ashort")); // 55
assertEquals("5", TestUtils.getExpressionValue(session, frame, "lstruct.aushort")); // 56
assertEquals("0", TestUtils.getExpressionValue(session, frame, "lstruct.asshort")); // 57
waitForUIUpdate(2000);
}
private void getDsfServices() throws Exception {
assertNotNull(session); // this must be initialized already.
TestUtils.waitOnExecutorThread(session, new Condition() {
public boolean isConditionValid() {
DsfServicesTracker servicesTracker = getDsfServicesTracker(session);
stackService = servicesTracker.getService(IStack.class);
breakpointsService = servicesTracker.getService(Breakpoints.class);
runControlService = servicesTracker.getService(IRunControl2.class);
return true;
}
});
}
/**
* Wait for UI to update so that we can see the debugger work in
* test workbench.
* For headless mode, this just does nothing and return immediately.
*
* @param timeout
*/
private void waitForUIUpdate(int timeout) {
long limit = System.currentTimeMillis() + timeout;
Display display = Display.getCurrent();
if (display == null || null == display.getActiveShell())
return;
while (true) {
while (display.readAndDispatch());
if (System.currentTimeMillis() > limit)
break;
}
}
/**
* Perform run to line and wait till it's done. Underlying members "thread" and "frame"
* will be updated.
*
* @param fileName
* @param lineNo
* @throws Exception
*/
private void waitRunToLine(final String fileName, final int lineNo) throws Exception {
Query<IStatus> query = new Query<IStatus>() {
@Override
protected void execute(final DataRequestMonitor<IStatus> drm) {
runControlService.runToLine(threadDMC, fileName, lineNo, false, new RequestMonitor(session.getExecutor(), drm) {
@Override
protected void handleCompleted() {
drm.setData(getStatus());
drm.done();
}});
}
};
session.getExecutor().execute(query);
IStatus status = query.get(5, TimeUnit.SECONDS);
if (status == null || ! status.isOK())
fail("Error in run-to-line: " + (status == null ? "Exception happened." : status.getMessage()));
updateSuspendedThreadAndFrame(500);
}
/**
* Perform run to line and wait till it's done. Underlying members "thread" and "frame"
* will be updated.
*
* @param fileName
* @param lineNo
* @param resume TODO
* @throws Exception
*/
private void waitMoveToLine(final String fileName, final int lineNo, final boolean resume) throws Exception {
Query<IStatus> query = new Query<IStatus>() {
@Override
protected void execute(final DataRequestMonitor<IStatus> drm) {
runControlService.moveToLine(threadDMC, fileName, lineNo, resume, new RequestMonitor(session.getExecutor(), drm) {
@Override
protected void handleCompleted() {
drm.setData(getStatus());
drm.done();
}});
}
};
session.getExecutor().execute(query);
IStatus status = query.get(5, TimeUnit.SECONDS);
if (status == null || ! status.isOK())
fail("Error in move-to-line: " + (status == null ? "Exception happened." : status.getMessage()));
updateSuspendedThreadAndFrame(500);
}
/**
* Wait for a suspend and update suspended thread and frame.
* @param waitForSuspend time to wait for suspend event to be broadcasted.
*
* @throws Exception
*/
private void updateSuspendedThreadAndFrame(int waitForSuspend) throws Exception {
threadDMC = TestUtils.waitForSuspendedThread(session);
Assert.assertNotNull(threadDMC);
// Wait some time for the suspend event to get broadcasted.
Thread.sleep(waitForSuspend);
frame = TestUtils.waitForStackFrame(session, threadDMC, 0);
}
private void assertControlIsAt(String fileName,
String functionName, int lineNo) throws Exception {
assertFrameMatches(frame, fileName, functionName, lineNo);
}
private void assertFrameMatches(final IFrameDMContext frame2, String fileName,
String functionName, int lineNo) throws Exception {
Query<IFrameDMData> query = new Query<IFrameDMData>() {
@Override
protected void execute(final DataRequestMonitor<IFrameDMData> drm) {
stackService.getFrameData(frame2, drm);
}
};
session.getExecutor().execute(query);
IFrameDMData fdata = null;
fdata = query.get(5, TimeUnit.SECONDS);
if (fdata == null)
fail("Error getting stack frame data.");
assertNotNull(fdata);
assertNotNull(fdata.getFile());
assertTrue(
"Expected source file is [" + fileName + "] but got [" + fdata.getFile() + "].",
fdata.getFile().contains(fileName));
assertEquals(functionName, fdata.getFunction());
assertEquals(lineNo, fdata.getLine());
}
private void setTempBreakpoint(final ExecutionDMC executionDMC, final Breakpoints bpService,
final String srcFile, final int lineNo) throws Exception {
Query<IBreakpointDMContext> query = new Query<IBreakpoints.IBreakpointDMContext>() {
@Override
protected void execute(
final DataRequestMonitor<IBreakpoints.IBreakpointDMContext> drm) {
Modules modulesService = getDsfServicesTracker(session).getService(Modules.class);
modulesService.getLineAddress(executionDMC, srcFile, lineNo, new DataRequestMonitor<List<IAddress>>(session.getExecutor(), drm) {
@Override
protected void handleSuccess() {
List<IAddress> addrs = getData();
// IBreakpointsTargetDMContext bt_dmc = DMContexts.getAncestorOfType(executionDMC, IBreakpointsTargetDMContext.class);
bpService.setTempBreakpoint(executionDMC, addrs.get(0), new RequestMonitor(session.getExecutor(), drm));
}});
}
};
session.getExecutor().execute(query);
query.get(5, TimeUnit.SECONDS);
}
}