mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 14:15:23 +02:00
Bug 292468 - Create unit tests for BreakpointsMediator2
This commit is contained in:
parent
7fdf059e22
commit
b4eb1781ac
8 changed files with 809 additions and 1 deletions
|
@ -14,5 +14,6 @@ Require-Bundle: org.eclipse.core.runtime,
|
|||
org.junit4,
|
||||
org.eclipse.ui,
|
||||
org.eclipse.cdt.dsf.ui,
|
||||
org.eclipse.cdt.examples.dsf.pda;bundle-version="2.0.0"
|
||||
org.eclipse.cdt.examples.dsf.pda;bundle-version="2.0.0",
|
||||
org.eclipse.cdt.core;bundle-version="5.2.0"
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
|
|
|
@ -15,4 +15,22 @@
|
|||
id="org.eclipse.cdt.tests.dsf.model.ModelTestView">
|
||||
</view>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
id="markerType.breakpoint"
|
||||
name="DSF Test Breakpoint Marker"
|
||||
point="org.eclipse.core.resources.markers">
|
||||
<super type="org.eclipse.debug.core.lineBreakpointMarker"/>
|
||||
<persistent value="true"/>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.debug.core.breakpoints">
|
||||
<breakpoint
|
||||
class="org.eclipse.cdt.tests.dsf.breakpoints.DsfTestBreakpoint"
|
||||
name="DSF Test Breakpoints"
|
||||
markerType="markerType.breakpoint"
|
||||
id="org.eclipse.cdt.tests.dsf.breakpoint"/>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
@ -66,4 +69,10 @@ public class DsfTestPlugin extends AbstractUIPlugin {
|
|||
return fgBundleContext;
|
||||
}
|
||||
|
||||
public static void failRequest(RequestMonitor rm, int code, String message) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PLUGIN_ID, code, message, null));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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 - Initial Implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf;
|
||||
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
|
||||
/*
|
||||
* This class provides a way to wait for an asynchronous ServerEvent
|
||||
* to occur. The user of this class specifies which event is of
|
||||
* interest using the proper constructor or the registerForEvent() method.
|
||||
* waitForEvent() can then be called to block until the event occurs or
|
||||
* the timeout elapses.
|
||||
*
|
||||
* Note that if the event occurs after regsiterForEvent() is called but
|
||||
* before waitForEvent() is called, waitForEvent() will return immediatly
|
||||
* since it will know the event has already occured.
|
||||
*/
|
||||
|
||||
public class ServiceEventWaitor<V> {
|
||||
/*
|
||||
* Indicates we will wait forever. Otherwise the time specified
|
||||
* is in milliseconds.
|
||||
*/
|
||||
public final static int WAIT_FOREVER = 0 ;
|
||||
|
||||
/* The type of event to wait for */
|
||||
private Class<V> fEventTypeClass;
|
||||
private DsfSession fSession;
|
||||
private V fEvent;
|
||||
|
||||
|
||||
/* Empty contructor. registerForEvent() should be called when
|
||||
* this constructor is used.
|
||||
*/
|
||||
public ServiceEventWaitor(DsfSession session) {
|
||||
fSession = session;
|
||||
}
|
||||
|
||||
/* Contructor that takes the eventClass as parameter. This is a shortcut
|
||||
* that avoids calling registerForEvent()
|
||||
*/
|
||||
public ServiceEventWaitor(DsfSession session, Class<V> eventClass) {
|
||||
this(session);
|
||||
registerForEvent(eventClass);
|
||||
}
|
||||
|
||||
/* Specify which event to wait for, and add ourselves as
|
||||
* a listener with the session
|
||||
*/
|
||||
public void registerForEvent(Class<V> eventClass) {
|
||||
fEventTypeClass = eventClass;
|
||||
fEvent = null;
|
||||
fSession.addServiceEventListener(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
if (fEventTypeClass != null) fSession.removeServiceEventListener(this);
|
||||
}
|
||||
|
||||
/* Block until 'timeout' or the previously specified event has been
|
||||
* received. The reason we don's specify the event as a parameter
|
||||
* is that we must be ready for the event to occur event before
|
||||
* this method is called.
|
||||
*/
|
||||
public synchronized V waitForEvent(int timeout) throws Exception {
|
||||
if (fEventTypeClass == null) {
|
||||
throw new Exception("Event to wait for has not been specified!");
|
||||
}
|
||||
// The event might have already been received
|
||||
if (fEvent != null) return fEvent;
|
||||
|
||||
wait(timeout);
|
||||
|
||||
if (fEvent == null) {
|
||||
throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName());
|
||||
}
|
||||
return fEvent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Listen to all possible events by having the base class be the parameter.
|
||||
* and then igure out if that event is the one we were waiting for.
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(V event) {
|
||||
if (fEventTypeClass.isAssignableFrom(event.getClass())) {
|
||||
synchronized(this) {
|
||||
fEvent = event;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.breakpoints;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslator2;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.dsf.service.IDsfService;
|
||||
import org.eclipse.cdt.tests.dsf.ServiceEventWaitor;
|
||||
import org.eclipse.cdt.tests.dsf.TestDsfExecutor;
|
||||
import org.eclipse.cdt.tests.dsf.breakpoints.DsfTestBreakpoints.BreakpointsAddedEvent;
|
||||
import org.eclipse.cdt.tests.dsf.breakpoints.DsfTestBreakpoints.BreakpointsTargetDMContext;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BreakpointMediatorTests {
|
||||
TestDsfExecutor fExecutor;
|
||||
DsfSession fSession;
|
||||
DsfTestBreakpoints fBreakpoints;
|
||||
BreakpointsMediator2 fMediator;
|
||||
IBreakpointAttributeTranslator2 fTranslator;
|
||||
BreakpointsTargetDMContext fTargetContext;
|
||||
|
||||
abstract private class InitializeServiceStep<V extends IDsfService> extends Sequence.Step {
|
||||
Class<V> fServiceClass;
|
||||
|
||||
InitializeServiceStep(Class<V> serviceClass) {
|
||||
fServiceClass = serviceClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
try {
|
||||
Constructor<V> c = fServiceClass.getConstructor(new Class[] {DsfSession.class});
|
||||
V service = c.newInstance(new Object[] {fSession});
|
||||
setService(service);
|
||||
service.initialize(requestMonitor);
|
||||
} catch (Exception e) {
|
||||
Assert.fail("Unexpected exception"); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
protected void setService(V service) {}
|
||||
}
|
||||
|
||||
private class ShutdownServiceStep extends Sequence.Step {
|
||||
IDsfService fService;
|
||||
|
||||
ShutdownServiceStep(IDsfService service) {
|
||||
fService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
fService.shutdown(requestMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
@Before public void start() throws ExecutionException, InterruptedException {
|
||||
fExecutor = new TestDsfExecutor();
|
||||
|
||||
Sequence seq = new Sequence(fExecutor) {
|
||||
@Override
|
||||
public Step[] getSteps() {
|
||||
return new Step[] {
|
||||
// Create session
|
||||
new Sequence.Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
fSession = DsfSession.startSession(fExecutor, "org.eclipse.cdt.dsf.tests"); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize breakpoints service
|
||||
new InitializeServiceStep<DsfTestBreakpoints>(DsfTestBreakpoints.class) {
|
||||
@Override
|
||||
protected void setService(DsfTestBreakpoints service) {
|
||||
fBreakpoints = service;
|
||||
}
|
||||
},
|
||||
|
||||
// Initialize breakpoint mediator
|
||||
new Sequence.Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
fTranslator = new DsfTestBreakpointAttributeTranslator2();
|
||||
fMediator = new BreakpointsMediator2(fSession, fTranslator);
|
||||
fMediator.initialize(rm);
|
||||
}
|
||||
},
|
||||
|
||||
// Start tracking breakpoints
|
||||
new Sequence.Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
fTargetContext = new BreakpointsTargetDMContext(fSession.getId());
|
||||
fMediator.startTrackingBreakpoints(fTargetContext, rm);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fExecutor.execute(seq);
|
||||
seq.get();
|
||||
}
|
||||
|
||||
@After public void shutdown() throws ExecutionException, InterruptedException {
|
||||
Sequence seq = new Sequence(fExecutor) {
|
||||
@Override
|
||||
public Step[] getSteps() {
|
||||
return new Step[] {
|
||||
// Stop tracking breakpoints
|
||||
new Sequence.Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
fMediator.stopTrackingBreakpoints(fTargetContext, rm);
|
||||
fTargetContext = null;
|
||||
}
|
||||
},
|
||||
|
||||
// Shutdown services
|
||||
new ShutdownServiceStep(fMediator),
|
||||
new ShutdownServiceStep(fBreakpoints),
|
||||
|
||||
// Shutdown session
|
||||
new Sequence.Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
DsfSession.endSession(fSession);
|
||||
rm.done();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fExecutor.execute(seq);
|
||||
seq.get();
|
||||
|
||||
fExecutor.submit(new DsfRunnable() { public void run() {
|
||||
fExecutor.shutdown();
|
||||
}}).get();
|
||||
if (fExecutor.exceptionsCaught()) {
|
||||
Throwable[] exceptions = fExecutor.getExceptions();
|
||||
throw new ExecutionException(exceptions[0]);
|
||||
}
|
||||
fExecutor = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleServiceTest() throws Exception {
|
||||
|
||||
ServiceEventWaitor<BreakpointsAddedEvent> waitor = new ServiceEventWaitor<BreakpointsAddedEvent>(fSession, BreakpointsAddedEvent.class);
|
||||
|
||||
new DsfTestBreakpoint();
|
||||
|
||||
waitor.waitForEvent(50000);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.breakpoints;
|
||||
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.resources.IWorkspaceRunnable;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.model.Breakpoint;
|
||||
import org.eclipse.debug.core.model.IBreakpoint;
|
||||
|
||||
/**
|
||||
* Test breakpoint.
|
||||
*/
|
||||
public class DsfTestBreakpoint extends Breakpoint {
|
||||
|
||||
public static final String DSF_TEST_BREAKPOINT_MODEL_ID = "dsfTest";
|
||||
public static final String ATTR_IDE_PREFIX = DSF_TEST_BREAKPOINT_MODEL_ID + ".ide.";
|
||||
|
||||
public static final String ATTR_ID = ATTR_IDE_PREFIX + "id";
|
||||
public static final String ATTR_NUM_TARGET_BREAKPOINTS = ATTR_IDE_PREFIX + "numTargetBreakpoints";
|
||||
public static final String ATTR_TRANSLATED = ATTR_IDE_PREFIX + "translated";
|
||||
public static final String ATTR_UNTRANSLATED = ATTR_IDE_PREFIX + "untranslated";
|
||||
public static final String ATTR_UPDATABLE = ATTR_IDE_PREFIX + "updatable";
|
||||
|
||||
public static int fgIdCounter = 0;
|
||||
|
||||
public DsfTestBreakpoint() throws CoreException {
|
||||
this(true, 1, "", "", "");
|
||||
}
|
||||
|
||||
public DsfTestBreakpoint(final boolean enabled, final int numTargetBPs, final String translated,
|
||||
final String untranslated, final String updatable)
|
||||
throws CoreException
|
||||
{
|
||||
final IResource resource = ResourcesPlugin.getWorkspace().getRoot();
|
||||
IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
|
||||
public void run(IProgressMonitor monitor) throws CoreException {
|
||||
IMarker marker = resource.createMarker("org.eclipse.cdt.tests.dsf.markerType.breakpoint");
|
||||
setMarker(marker);
|
||||
marker.setAttribute(IBreakpoint.ENABLED, enabled);
|
||||
marker.setAttribute(DsfTestBreakpoint.ATTR_ID, fgIdCounter++);
|
||||
marker.setAttribute(DsfTestBreakpoint.ATTR_NUM_TARGET_BREAKPOINTS, numTargetBPs);
|
||||
marker.setAttribute(DsfTestBreakpoint.ATTR_TRANSLATED, translated);
|
||||
marker.setAttribute(DsfTestBreakpoint.ATTR_UNTRANSLATED, untranslated);
|
||||
marker.setAttribute(DsfTestBreakpoint.ATTR_UPDATABLE, updatable);
|
||||
}
|
||||
};
|
||||
run(getMarkerRule(resource), runnable);
|
||||
DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(this);
|
||||
}
|
||||
|
||||
public Integer getID() throws CoreException {
|
||||
return (Integer)ensureMarker().getAttribute(ATTR_ID);
|
||||
}
|
||||
|
||||
public String getModelIdentifier() {
|
||||
return DSF_TEST_BREAKPOINT_MODEL_ID;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems 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:
|
||||
* Wind River Systems - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.tests.dsf.breakpoints;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslator2;
|
||||
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2.BreakpointEventType;
|
||||
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2.ITargetBreakpointInfo;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.debug.core.model.IBreakpoint;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DsfTestBreakpointAttributeTranslator2 implements IBreakpointAttributeTranslator2 {
|
||||
|
||||
public void initialize(BreakpointsMediator2 mediator) {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public boolean supportsBreakpoint(IBreakpoint bp) {
|
||||
return DsfTestBreakpoint.DSF_TEST_BREAKPOINT_MODEL_ID.equals(bp.getModelIdentifier());
|
||||
}
|
||||
|
||||
public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint,
|
||||
Map<String, Object> bpAttrs, DataRequestMonitor<List<Map<String, Object>>> drm)
|
||||
{
|
||||
Integer num = (Integer)bpAttrs.get(DsfTestBreakpoint.ATTR_NUM_TARGET_BREAKPOINTS);
|
||||
if (num == null) {
|
||||
num = new Integer(1);
|
||||
}
|
||||
List<Map<String, Object>> subBpsAttrs = new ArrayList<Map<String, Object>>(num);
|
||||
for (int i = 0; i < num; i++) {
|
||||
Map<String, Object> subBpAttr = new HashMap<String, Object>(bpAttrs);
|
||||
subBpAttr.put(DsfTestBreakpoints.ATTR_SUB_ID, i);
|
||||
subBpsAttrs.add(subBpAttr);
|
||||
}
|
||||
drm.setData(subBpsAttrs);
|
||||
drm.done();
|
||||
}
|
||||
|
||||
public Map<String, Object> getAllBreakpointAttributes(IBreakpoint platformBP, boolean bpManagerEnabled)
|
||||
throws CoreException
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> platformBPAttr = platformBP.getMarker().getAttributes();
|
||||
if (!bpManagerEnabled) {
|
||||
platformBPAttr.put(IBreakpoint.ENABLED, Boolean.FALSE);
|
||||
}
|
||||
|
||||
return convertAttributes(platformBPAttr);
|
||||
}
|
||||
|
||||
public Map<String, Object> convertAttributes(Map<String, Object> platformBPAttr) {
|
||||
Map<String, Object> debugAttrs = new HashMap<String, Object>(platformBPAttr.size());
|
||||
for (Map.Entry<String, Object> entry : platformBPAttr.entrySet()) {
|
||||
if ( DsfTestBreakpoint.ATTR_TRANSLATED.equals(entry.getKey())) {
|
||||
debugAttrs.put(DsfTestBreakpoints.ATTR_TRANSLATED, entry.getValue());
|
||||
}
|
||||
else if ( IBreakpoint.ENABLED.equals(entry.getKey())) {
|
||||
debugAttrs.put(DsfTestBreakpoints.ATTR_ENABLED, entry.getValue());
|
||||
} else {
|
||||
debugAttrs.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return debugAttrs;
|
||||
}
|
||||
|
||||
public void updateBreakpointsStatus(
|
||||
Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo,
|
||||
BreakpointEventType eventType)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context,
|
||||
Map<String, Object> attributes)
|
||||
{
|
||||
for (String attribute : attributes.keySet()) {
|
||||
if (!DsfTestBreakpoint.ATTR_UPDATABLE.equals(attribute)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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 - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.tests.dsf.breakpoints;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.core.IAddress;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
|
||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.DsfTestPlugin;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.model.IBreakpoint;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* Initial breakpoint service implementation.
|
||||
* Implements the IBreakpoints interface.
|
||||
*/
|
||||
public class DsfTestBreakpoints extends AbstractDsfService implements IBreakpoints
|
||||
{
|
||||
public static final String ATTR_DEBUGGER_PREFIX = DsfTestBreakpoint.DSF_TEST_BREAKPOINT_MODEL_ID + ".debugger.";
|
||||
|
||||
public static final String ATTR_ENABLED = ATTR_DEBUGGER_PREFIX + "enabled";
|
||||
public static final String ATTR_TRANSLATED = ATTR_DEBUGGER_PREFIX + "enabled";
|
||||
public static final String ATTR_SUB_ID = ATTR_DEBUGGER_PREFIX + "subId";
|
||||
|
||||
@Immutable
|
||||
public static class BreakpointsTargetDMContext extends AbstractDMContext implements IBreakpointsTargetDMContext {
|
||||
|
||||
private static int fIdCounter = 1;
|
||||
|
||||
public final Integer fId = fIdCounter++;
|
||||
|
||||
BreakpointsTargetDMContext (String sessionId) {
|
||||
super(sessionId, DMContexts.EMPTY_CONTEXTS_ARRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return baseEquals(obj) && (fId.equals(((BreakpointsTargetDMContext) obj).fId));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseHashCode() + fId.hashCode() ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "breakpointsTarget(" + fId + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Context representing a PDA line breakpoint. In PDA debugger, since there is only
|
||||
* one file being debugged at a time, a breakpoint is uniquely identified using the
|
||||
* line number only.
|
||||
*/
|
||||
@Immutable
|
||||
public static class BreakpointDMContext extends AbstractDMContext implements IBreakpointDMContext {
|
||||
public final Integer fId;
|
||||
public final Integer fSubId;
|
||||
|
||||
public BreakpointDMContext(String sessionId, BreakpointsTargetDMContext commandControlCtx, Integer id, Integer subId) {
|
||||
super(sessionId, new IDMContext[] { commandControlCtx });
|
||||
fId = id;
|
||||
fSubId = subId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return baseEquals(obj) &&
|
||||
(fId.equals(((BreakpointDMContext) obj).fId)) &&
|
||||
(fSubId.equals(((BreakpointDMContext) obj).fSubId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseHashCode() + fId.hashCode() + fSubId.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseToString() + ".breakpoint(" + fId + "-" + fSubId + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
public static class BreakpointDMData implements IBreakpointDMData {
|
||||
public final Map<String, Object> fAttributes;
|
||||
|
||||
public BreakpointDMData(Map<String, Object> attributes) {
|
||||
fAttributes = Collections.unmodifiableMap( new HashMap<String, Object>(attributes) );
|
||||
}
|
||||
|
||||
public IAddress[] getAddresses() { return null; }
|
||||
public String getBreakpointType() { return null; }
|
||||
public String getFileName() { return null; }
|
||||
public int getLineNumber() { return 0; }
|
||||
public String getFunctionName() { return null; }
|
||||
public String getCondition() { return null; }
|
||||
public int getIgnoreCount() { return 0; }
|
||||
public String getExpression() { return null; }
|
||||
|
||||
public boolean isEnabled() { return (Boolean)getAttributes().get(ATTR_ENABLED); }
|
||||
public Map<String, Object> getAttributes() { return fAttributes; }
|
||||
}
|
||||
|
||||
public static class BreakpointsChangedEvent implements IBreakpointsChangedEvent {
|
||||
public final BreakpointDMContext fBreakpoint;
|
||||
public final IBreakpointDMContext [] fBreakpointArray;
|
||||
|
||||
BreakpointsChangedEvent (BreakpointDMContext bp) {
|
||||
fBreakpoint = bp;
|
||||
fBreakpointArray = new IBreakpointDMContext[] { bp };
|
||||
}
|
||||
|
||||
public IBreakpointsTargetDMContext getDMContext() {
|
||||
return DMContexts.getAncestorOfType(fBreakpoint, IBreakpointsTargetDMContext.class);
|
||||
}
|
||||
|
||||
public IBreakpointDMContext[] getBreakpoints() {
|
||||
return fBreakpointArray;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BreakpointsAddedEvent extends BreakpointsChangedEvent implements IBreakpointsAddedEvent {
|
||||
BreakpointsAddedEvent(BreakpointDMContext bp) {
|
||||
super(bp);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BreakpointsRemovedEvent extends BreakpointsChangedEvent implements IBreakpointsRemovedEvent {
|
||||
BreakpointsRemovedEvent(BreakpointDMContext bp) {
|
||||
super(bp);
|
||||
}
|
||||
}
|
||||
|
||||
public static class BreakpointsUpdatedEvent extends BreakpointsChangedEvent implements IBreakpointsUpdatedEvent {
|
||||
BreakpointsUpdatedEvent(BreakpointDMContext bp) {
|
||||
super(bp);
|
||||
}
|
||||
}
|
||||
|
||||
// Breakpoints currently installed
|
||||
private Map<BreakpointDMContext, BreakpointDMData> fBreakpoints = new HashMap<BreakpointDMContext, BreakpointDMData>();
|
||||
|
||||
/**
|
||||
* The service constructor
|
||||
*
|
||||
* @param session The debugging session this service belongs to.
|
||||
*/
|
||||
public DsfTestBreakpoints(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final RequestMonitor rm) {
|
||||
super.initialize(new RequestMonitor(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
doInitialize(rm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doInitialize(final RequestMonitor rm) {
|
||||
|
||||
// Register this service
|
||||
register(new String[] { IBreakpoints.class.getName(), DsfTestBreakpoints.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(final RequestMonitor rm) {
|
||||
unregister();
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BundleContext getBundleContext() {
|
||||
return DsfTestPlugin.getBundleContext();
|
||||
}
|
||||
|
||||
public void getBreakpoints(final IBreakpointsTargetDMContext context, final DataRequestMonitor<IBreakpointDMContext[]> rm) {
|
||||
// Validate the context
|
||||
// TODO: check the target context
|
||||
// if (!fCommandControl.getContext().equals(context)) {
|
||||
// DsfTestPlugin.failRequest(rm, INVALID_HANDLE, "Invalid breakpoints target context");
|
||||
// return;
|
||||
// }
|
||||
|
||||
rm.setData(fBreakpoints.keySet().toArray(new IBreakpointDMContext[fBreakpoints.size()]));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void getBreakpointDMData(IBreakpointDMContext dmc, DataRequestMonitor<IBreakpointDMData> rm) {
|
||||
DsfTestPlugin.failRequest(rm, NOT_SUPPORTED, "Retrieving breakpoint data is not supported");
|
||||
}
|
||||
|
||||
public void insertBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes,
|
||||
DataRequestMonitor<IBreakpointDMContext> rm)
|
||||
{
|
||||
Boolean enabled = (Boolean)attributes.get(IBreakpoint.ENABLED);
|
||||
if (enabled != null && !enabled.booleanValue()) {
|
||||
// If the breakpoint is disabled, just fail the request.
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "Breakpoint is disabled");
|
||||
} else {
|
||||
BreakpointsTargetDMContext targetCtx = DMContexts.getAncestorOfType(context, BreakpointsTargetDMContext.class);
|
||||
if (targetCtx != null) {
|
||||
doInsertBreakpoint(targetCtx, attributes, rm);
|
||||
} else {
|
||||
DsfTestPlugin.failRequest(rm, INVALID_HANDLE, "Unknown breakpoint type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doInsertBreakpoint(BreakpointsTargetDMContext targetCtx, final Map<String, Object> attributes, final DataRequestMonitor<IBreakpointDMContext> rm)
|
||||
{
|
||||
// Retrieve the id
|
||||
Integer id = (Integer)attributes.get(DsfTestBreakpoint.ATTR_ID);
|
||||
if (id == null) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "No ID specified");
|
||||
return;
|
||||
}
|
||||
|
||||
Integer subId = (Integer)attributes.get(ATTR_SUB_ID);
|
||||
if (id == null) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "No Sub ID specified");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new breakpoint context object and check that it's not
|
||||
// installed already. PDA can only track a single breakpoint at a
|
||||
// given line, attempting to set the second breakpoint should fail.
|
||||
final BreakpointDMContext breakpointCtx =
|
||||
new BreakpointDMContext(getSession().getId(), targetCtx, id, subId);
|
||||
if (fBreakpoints.containsKey(breakpointCtx)) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "Breakpoint already set");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the new breakpoint context to the list of known breakpoints.
|
||||
// Adding it here, before the set command is completed will prevent
|
||||
// a possibility of a second breakpoint being installed in the same
|
||||
// location while this breakpoint is being processed. It will also
|
||||
// allow the breakpoint to be removed or updated even while it is
|
||||
// still being processed here.
|
||||
fBreakpoints.put(breakpointCtx, new BreakpointDMData(attributes));
|
||||
rm.setData(breakpointCtx);
|
||||
getSession().dispatchEvent(new BreakpointsAddedEvent(breakpointCtx), getProperties());
|
||||
}
|
||||
|
||||
|
||||
public void removeBreakpoint(IBreakpointDMContext bpCtx, RequestMonitor rm) {
|
||||
if (!fBreakpoints.containsKey(bpCtx)) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "Breakpoint already removed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bpCtx instanceof BreakpointDMContext) {
|
||||
if ( fBreakpoints.remove(bpCtx) == null ) {
|
||||
DsfTestPlugin.failRequest(rm, INVALID_STATE, "Breakpoint does not exist");
|
||||
} else {
|
||||
getSession().dispatchEvent(new BreakpointsRemovedEvent((BreakpointDMContext)bpCtx), getProperties());
|
||||
}
|
||||
rm.done();
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, DsfTestPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid breakpoint type", null ));
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBreakpoint(final IBreakpointDMContext bpCtx, Map<String, Object> attributes, final RequestMonitor rm) {
|
||||
if (!fBreakpoints.containsKey(bpCtx)) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "Breakpoint not installed");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String attribute : attributes.keySet()) {
|
||||
if (!DsfTestBreakpoint.ATTR_UPDATABLE.equals(attribute)) {
|
||||
DsfTestPlugin.failRequest(rm, REQUEST_FAILED, "Attribute cannot be updated");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (bpCtx instanceof BreakpointDMContext) {
|
||||
Map<String, Object> newAttrs = new HashMap<String, Object>(fBreakpoints.get(bpCtx).getAttributes());
|
||||
newAttrs.putAll(attributes);
|
||||
fBreakpoints.put((BreakpointDMContext)bpCtx, new BreakpointDMData(newAttrs));
|
||||
getSession().dispatchEvent(new BreakpointsRemovedEvent((BreakpointDMContext)bpCtx), getProperties());
|
||||
|
||||
} else {
|
||||
DsfTestPlugin.failRequest(rm, INVALID_HANDLE, "Invalid breakpoint type");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue