blob: 96f3ef39ad14afb62f08615cda597e0b2eed0bf4 [file] [log] [blame]
package org.eclipse.jdt.debug.tests;
/**********************************************************************
Copyright (c) 2000, 2002 IBM Corp. and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Common Public License v0.5
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/cpl-v05.html
Contributors:
IBM Corporation - Initial implementation
**********************************************************************/
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.ILineBreakpoint;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaExceptionBreakpoint;
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint;
import org.eclipse.jdt.debug.core.IJavaPatternBreakpoint;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaTargetPatternBreakpoint;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaWatchpoint;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.debug.eval.EvaluationManager;
import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
import org.eclipse.jdt.debug.testplugin.DebugElementEventWaiter;
import org.eclipse.jdt.debug.testplugin.DebugElementKindEventDetailWaiter;
import org.eclipse.jdt.debug.testplugin.DebugElementKindEventWaiter;
import org.eclipse.jdt.debug.testplugin.DebugEventWaiter;
import org.eclipse.jdt.internal.debug.ui.IJDIPreferencesConstants;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
/**
* Tests for launch configurations
*/
public abstract class AbstractDebugTest extends TestCase implements IEvaluationListener {
public static final int DEFAULT_TIMEOUT = 30000;
public IEvaluationResult fEvaluationResult;
public static IJavaProject fJavaProject;
/**
* The last relevent event set - for example, that caused
* a thread to suspend
*/
protected DebugEvent[] fEventSet;
public AbstractDebugTest(String name) {
super(name);
}
/**
* Sets the last relevant event set
*
* @param set event set
*/
protected void setEventSet(DebugEvent[] set) {
fEventSet = set;
}
/**
* Returns the last relevant event set
*
* @return event set
*/
protected DebugEvent[] getEventSet() {
return fEventSet;
}
/**
* Returns the launch manager
*
* @return launch manager
*/
protected ILaunchManager getLaunchManager() {
return DebugPlugin.getDefault().getLaunchManager();
}
/**
* Returns the breakpoint manager
*
* @return breakpoint manager
*/
protected IBreakpointManager getBreakpointManager() {
return DebugPlugin.getDefault().getBreakpointManager();
}
/**
* Returns the 'DebugTests' project.
*
* @return the test project
*/
protected IJavaProject getJavaProject() {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("DebugTests");
return JavaCore.create(project);
}
/**
* Launches the type with the given name, and waits for a
* suspend event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param mainTypeName the program to launch
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchAndSuspend(String mainTypeName) throws Exception {
ILaunchConfiguration config = getLaunchConfiguration(mainTypeName);
assertNotNull("Could not locate launch configuration for " + mainTypeName, config);
return launchAndSuspend(config);
}
/**
* Launches the given configuration in debug mode, and waits for a
* suspend event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param config the configuration to launch
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchAndSuspend(ILaunchConfiguration config) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.SUSPEND, IJavaThread.class);
waiter.setTimeout(DEFAULT_TIMEOUT);
config.launch(ILaunchManager.DEBUG_MODE, null);
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
return (IJavaThread)suspendee;
}
/**
* Launches the type with the given name, and waits for a breakpoint-caused
* suspend event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param mainTypeName the program to launch
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchToBreakpoint(String mainTypeName) throws Exception {
ILaunchConfiguration config = getLaunchConfiguration(mainTypeName);
assertNotNull("Could not locate launch configuration for " + mainTypeName, config);
return launchToBreakpoint(config);
}
/**
* Launches the given configuration in debug mode, and waits for a breakpoint-caused
* suspend event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param config the configuration to launch
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchToBreakpoint(ILaunchConfiguration config) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventDetailWaiter(DebugEvent.SUSPEND, IJavaThread.class, DebugEvent.BREAKPOINT);
waiter.setTimeout(DEFAULT_TIMEOUT);
config.launch(ILaunchManager.DEBUG_MODE, null);
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
assertTrue("suspendee was not an IJavaThread", suspendee instanceof IJavaThread);
return (IJavaThread)suspendee;
}
/**
* Launches the type with the given name, and waits for a terminate
* event in that program. Returns the debug target in which the suspend
* event occurred.
*
* @param mainTypeName the program to launch
* @param timeout the number of milliseconds to wait for a terminate event
* @return debug target in which the terminate event occurred
*/
protected IJavaDebugTarget launchAndTerminate(String mainTypeName) throws Exception {
ILaunchConfiguration config = getLaunchConfiguration(mainTypeName);
assertNotNull("Could not locate launch configuration for " + mainTypeName, config);
return launchAndTerminate(config, DEFAULT_TIMEOUT);
}
/**
* Launches the given configuration in debug mode, and waits for a terminate
* event in that program. Returns the debug target in which the terminate
* event occurred.
*
* @param config the configuration to launch
* @param timeout the number of milliseconds to wait for a terminate event
* @return thread in which the first suspend event occurred
*/
protected IJavaDebugTarget launchAndTerminate(ILaunchConfiguration config, int timeout) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.TERMINATE, IJavaDebugTarget.class);
waiter.setTimeout(timeout);
ILaunch launch = config.launch(ILaunchManager.DEBUG_MODE, null);
IJavaDebugTarget debugTarget = (IJavaDebugTarget)launch.getDebugTarget();
if (debugTarget == null || !(debugTarget.isTerminated() || debugTarget.isDisconnected())) {
Object terminatee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not terminate.", terminatee);
assertTrue("terminatee is not an IJavaDebugTarget", terminatee instanceof IJavaDebugTarget);
debugTarget = (IJavaDebugTarget) terminatee;
assertTrue("debug target is not terminated", debugTarget.isTerminated() || debugTarget.isDisconnected());
}
return debugTarget;
}
/**
* Launches the type with the given name, and waits for a line breakpoint suspend
* event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param mainTypeName the program to launch
* @param bp the breakpoint that should cause a suspend event
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchToLineBreakpoint(String mainTypeName, ILineBreakpoint bp) throws Exception {
ILaunchConfiguration config = getLaunchConfiguration(mainTypeName);
assertNotNull("Could not locate launch configuration for " + mainTypeName, config);
return launchToLineBreakpoint(config, bp);
}
/**
* Launches the given configuration in debug mode, and waits for a line breakpoint
* suspend event in that program. Returns the thread in which the suspend
* event occurred.
*
* @param config the configuration to launch
* @param bp the breakpoint that should cause a suspend event
* @return thread in which the first suspend event occurred
*/
protected IJavaThread launchToLineBreakpoint(ILaunchConfiguration config, ILineBreakpoint bp) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventDetailWaiter(DebugEvent.SUSPEND, IJavaThread.class, DebugEvent.BREAKPOINT);
waiter.setTimeout(DEFAULT_TIMEOUT);
config.launch(ILaunchManager.DEBUG_MODE, null);
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
assertTrue("suspendee was not an IJavaThread", suspendee instanceof IJavaThread);
IJavaThread thread = (IJavaThread) suspendee;
IBreakpoint hit = getBreakpoint(thread);
assertNotNull("suspended, but not by breakpoint", hit);
assertTrue("hit un-registered breakpoint", bp.equals(hit));
assertTrue("suspended, but not by line breakpoint", hit instanceof ILineBreakpoint);
ILineBreakpoint breakpoint= (ILineBreakpoint) hit;
int lineNumber = breakpoint.getLineNumber();
int stackLine = thread.getTopStackFrame().getLineNumber();
assertTrue("line numbers of breakpoint and stack frame do not match", lineNumber == stackLine);
return thread;
}
/**
* Resumes the given thread, and waits for another breakpoint-caused suspend event.
* Returns the thread in which the suspend event occurrs.
*
* @param thread thread to resume
* @return thread in which the first suspend event occurrs
*/
protected IJavaThread resume(IJavaThread thread) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventDetailWaiter(DebugEvent.SUSPEND, IJavaThread.class, DebugEvent.BREAKPOINT);
waiter.setTimeout(DEFAULT_TIMEOUT);
thread.resume();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
return (IJavaThread)suspendee;
}
/**
* Resumes the given thread, and waits for a suspend event caused by the specified
* line breakpoint. Returns the thread in which the suspend event occurrs.
*
* @param thread thread to resume
* @return thread in which the first suspend event occurrs
*/
protected IJavaThread resumeToLineBreakpoint(IJavaThread resumeThread, ILineBreakpoint bp) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventDetailWaiter(DebugEvent.SUSPEND, IJavaThread.class, DebugEvent.BREAKPOINT);
waiter.setTimeout(DEFAULT_TIMEOUT);
resumeThread.resume();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
assertTrue("suspendee was not an IJavaThread", suspendee instanceof IJavaThread);
IJavaThread thread = (IJavaThread) suspendee;
IBreakpoint hit = getBreakpoint(thread);
assertNotNull("suspended, but not by breakpoint", hit);
assertTrue("hit un-registered breakpoint", bp.equals(hit));
assertTrue("suspended, but not by line breakpoint", hit instanceof ILineBreakpoint);
ILineBreakpoint breakpoint= (ILineBreakpoint) hit;
int lineNumber = breakpoint.getLineNumber();
int stackLine = thread.getTopStackFrame().getLineNumber();
assertTrue("line numbers of breakpoint and stack frame do not match", lineNumber == stackLine);
return (IJavaThread)suspendee;
}
/**
* Resumes the given thread, and waits for the debug target
* to terminate (i.e. finish/exit the program).
*
* @param thread thread to resume
*/
protected void exit(IJavaThread thread) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.TERMINATE, IProcess.class);
waiter.setTimeout(DEFAULT_TIMEOUT);
thread.resume();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not terminate.", suspendee);
}
/**
* Resumes the given thread, and waits the associated debug
* target to terminate.
*
* @param thread thread to resume
* @return the terminated debug target
*/
protected IJavaDebugTarget resumeAndExit(IJavaThread thread) throws Exception {
DebugEventWaiter waiter= new DebugElementEventWaiter(DebugEvent.TERMINATE, thread.getDebugTarget());
waiter.setTimeout(DEFAULT_TIMEOUT);
thread.resume();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not terminate.", suspendee);
IJavaDebugTarget target = (IJavaDebugTarget)suspendee;
assertTrue("program should have exited", target.isTerminated() || target.isDisconnected());
return target;
}
/**
* Returns the launch configuration for the given main type
*
* @param mainTypeName program to launch
* @see ProjectCreationDecorator
*/
protected ILaunchConfiguration getLaunchConfiguration(String mainTypeName) {
IFile file = getJavaProject().getProject().getFolder("launchConfigurations").getFile(mainTypeName + ".launch");
ILaunchConfiguration config = getLaunchManager().getLaunchConfiguration(file);
assertTrue("Could not find launch configuration for " + mainTypeName, config.exists());
return config;
}
protected IResource getBreakpointResource(String typeName) throws Exception {
IJavaElement element = getJavaProject().findElement(new Path(typeName + ".java"));
IResource resource = element.getCorrespondingResource();
if (resource == null) {
resource = getJavaProject().getProject();
}
return resource;
}
/**
* Creates and returns a line breakpoint at the given line number in the type with the
* given name.
*
* @param lineNumber line number
* @param typeName type name
*/
protected IJavaLineBreakpoint createLineBreakpoint(int lineNumber, String typeName) throws Exception {
return JDIDebugModel.createLineBreakpoint(getBreakpointResource(typeName), typeName, lineNumber, -1, -1, 0, true, null);
}
/**
* Creates and returns a line breakpoint at the given line number in the type with the
* given name and sets the specified condition on the breakpoint.
*
* @param lineNumber line number
* @param typeName type name
* @param condition condition
*/
protected IJavaLineBreakpoint createConditionalLineBreakpoint(int lineNumber, String typeName, String condition) throws Exception {
IJavaLineBreakpoint bp = JDIDebugModel.createLineBreakpoint(getBreakpointResource(typeName), typeName, lineNumber, -1, -1, 0, true, null);
bp.setCondition(condition);
bp.setConditionEnabled(true);
return bp;
}
/**
* Creates and returns a pattern breakpoint at the given line number in the
* source file with the given name.
*
* @param lineNumber line number
* @param sourceName name of source file
* @param pattern the pattern of the class file name
*/
protected IJavaPatternBreakpoint createPatternBreakpoint(int lineNumber, String sourceName, String pattern) throws Exception {
return JDIDebugModel.createPatternBreakpoint(getJavaProject().getProject(), sourceName, pattern, lineNumber, -1, -1, 0, true, null);
}
/**
* Creates and returns a target pattern breakpoint at the given line number in the
* source file with the given name.
*
* @param lineNumber line number
* @param sourceName name of source file
*/
protected IJavaTargetPatternBreakpoint createTargetPatternBreakpoint(int lineNumber, String sourceName) throws Exception {
return JDIDebugModel.createTargetPatternBreakpoint(getJavaProject().getProject(), sourceName, lineNumber, -1, -1, 0, true, null);
}
/**
* Creates and returns a method breakpoint
*
* @param typeNamePattern type name pattern
* @param methodName method name
* @param methodSignature method signature
* @param entry whether to break on entry
* @param exit whether to break on exit
*/
protected IJavaMethodBreakpoint createMethodBreakpoint(String typeNamePattern, String methodName, String methodSignature, boolean entry, boolean exit) throws Exception {
return JDIDebugModel.createMethodBreakpoint(getJavaProject().getProject(), typeNamePattern, methodName, methodSignature, entry, exit,false, -1, -1, -1, 0, true, null);
}
/**
* Creates and returns an exception breakpoint
*
* @param exName exception name
* @param caught whether to suspend in caught locations
* @param uncaught whether to suspend in uncaught locations
*/
protected IJavaExceptionBreakpoint createExceptionBreakpoint(String exName, boolean caught, boolean uncaught) throws Exception {
return JDIDebugModel.createExceptionBreakpoint(getBreakpointResource(exName),exName, caught, uncaught, false, true, null);
}
/**
* Creates and returns a watchpoint
*
* @param typeNmae type name
* @param fieldName field name
* @param access whether to suspend on field access
* @param modification whether to suspend on field modification
*/
protected IJavaWatchpoint createWatchpoint(String typeName, String fieldName, boolean access, boolean modification) throws Exception {
IJavaWatchpoint wp = JDIDebugModel.createWatchpoint(getBreakpointResource(typeName), typeName, fieldName, -1, -1, -1, 0, true, null);
wp.setAccess(access);
wp.setModification(modification);
return wp;
}
/**
* Terminates the given thread and removes its launch
*/
protected void terminateAndRemove(IJavaThread thread) {
if (thread != null) {
terminateAndRemove((IJavaDebugTarget)thread.getDebugTarget());
}
}
/**
* Terminates the given debug target and removes its launch.
*
* NOTE: all breakpoints are removed, all threads are resumed, and then
* the target is terminated. This avoids defunct processes on linux.
*/
protected void terminateAndRemove(IJavaDebugTarget debugTarget) {
if (debugTarget != null) {
ILaunch launch = debugTarget.getLaunch();
try {
removeAllBreakpoints();
IThread[] threads = debugTarget.getThreads();
for (int i = 0; i < threads.length; i++) {
IThread thread = threads[i];
try {
if (thread.isSuspended()) {
thread.resume();
}
} catch (CoreException e) {
}
}
debugTarget.getDebugTarget().terminate();
} catch (CoreException e) {
} finally {
getLaunchManager().removeLaunch(launch);
}
}
}
/**
* Deletes all existing breakpoints
*/
protected void removeAllBreakpoints() {
IBreakpoint[] bps = getBreakpointManager().getBreakpoints();
try {
getBreakpointManager().removeBreakpoints(bps, true);
} catch (CoreException e) {
}
}
/**
* Returns the first breakpoint the given thread is suspended
* at, or <code>null</code> if none.
*
* @return the first breakpoint the given thread is suspended
* at, or <code>null</code> if none
*/
protected IBreakpoint getBreakpoint(IThread thread) {
IBreakpoint[] bps = thread.getBreakpoints();
if (bps.length > 0) {
return bps[0];
}
return null;
}
/**
* Evaluates the given snippet in the context of the given stack frame and returns
* the result.
*
* @param snippet code snippet
* @param frame stack frame context
* @return evaluation result
*/
protected IEvaluationResult evaluate(String snippet, IJavaStackFrame frame) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.SUSPEND, IJavaThread.class);
waiter.setTimeout(DEFAULT_TIMEOUT);
IAstEvaluationEngine engine = EvaluationManager.newAstEvaluationEngine(getJavaProject(), (IJavaDebugTarget)frame.getDebugTarget());
engine.evaluate(snippet, frame, this, DebugEvent.EVALUATION, true);
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
engine.dispose();
return fEvaluationResult;
}
/**
* @see IEvaluationListener#evaluationComplete(IEvaluationResult)
*/
public void evaluationComplete(IEvaluationResult result) {
fEvaluationResult = result;
}
/**
* Performs a step over in the given stack frame and returns when complete.
*
* @param frame stack frame to step in
*/
protected IJavaThread stepOver(IJavaStackFrame frame) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.SUSPEND, IJavaThread.class);
waiter.setTimeout(DEFAULT_TIMEOUT);
frame.stepOver();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
return (IJavaThread) suspendee;
}
/**
* Performs a step into in the given stack frame and returns when complete.
*
* @param frame stack frame to step in
*/
protected IJavaThread stepInto(IJavaStackFrame frame) throws Exception {
DebugEventWaiter waiter= new DebugElementKindEventWaiter(DebugEvent.SUSPEND, IJavaThread.class);
waiter.setTimeout(DEFAULT_TIMEOUT);
frame.stepInto();
Object suspendee= waiter.waitForEvent();
setEventSet(waiter.getEventSet());
assertNotNull("Program did not suspend.", suspendee);
return (IJavaThread) suspendee;
}
/**
* Sets the "suspend on uncaught exception" preference as specified.
* * @param on of off */
protected void setSuspendOnUncaughtExceptionsPreference(boolean on) {
JDIDebugUIPlugin.getDefault().getPreferenceStore().setDefault(IJDIPreferencesConstants.PREF_SUSPEND_ON_UNCAUGHT_EXCEPTIONS, on);
}
}