diff options
author | Pawel Piech | 2010-01-09 00:56:21 +0000 |
---|---|---|
committer | Pawel Piech | 2010-01-09 00:56:21 +0000 |
commit | b4eb1781ac5a92ed6708150289bdfbde9259cd13 (patch) | |
tree | c21033f57244139af5858bf135fa303219887fda /dsf/org.eclipse.cdt.tests.dsf | |
parent | 7fdf059e220d0321b0497cfecff4b41241e1cd9a (diff) | |
download | org.eclipse.cdt-b4eb1781ac5a92ed6708150289bdfbde9259cd13.tar.gz org.eclipse.cdt-b4eb1781ac5a92ed6708150289bdfbde9259cd13.tar.xz org.eclipse.cdt-b4eb1781ac5a92ed6708150289bdfbde9259cd13.zip |
Bug 292468 - Create unit tests for BreakpointsMediator2
Diffstat (limited to 'dsf/org.eclipse.cdt.tests.dsf')
8 files changed, 809 insertions, 1 deletions
diff --git a/dsf/org.eclipse.cdt.tests.dsf/META-INF/MANIFEST.MF b/dsf/org.eclipse.cdt.tests.dsf/META-INF/MANIFEST.MF index e44670aa588..2f93d176480 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/META-INF/MANIFEST.MF +++ b/dsf/org.eclipse.cdt.tests.dsf/META-INF/MANIFEST.MF @@ -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 diff --git a/dsf/org.eclipse.cdt.tests.dsf/plugin.xml b/dsf/org.eclipse.cdt.tests.dsf/plugin.xml index ba839803701..4b4d7a573fc 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/plugin.xml +++ b/dsf/org.eclipse.cdt.tests.dsf/plugin.xml @@ -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> diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/DsfTestPlugin.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/DsfTestPlugin.java index 742f1dda5cf..8fcab24f16b 100644 --- a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/DsfTestPlugin.java +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/DsfTestPlugin.java @@ -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(); + } + + } diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/ServiceEventWaitor.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/ServiceEventWaitor.java new file mode 100644 index 00000000000..9357d0a8d67 --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/ServiceEventWaitor.java @@ -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(); + } + } + } +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/BreakpointMediatorTests.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/BreakpointMediatorTests.java new file mode 100644 index 00000000000..b8a91f7ce4f --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/BreakpointMediatorTests.java @@ -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); + } + + +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoint.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoint.java new file mode 100644 index 00000000000..355cee9daf9 --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoint.java @@ -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; + } + + +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpointAttributeTranslator2.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpointAttributeTranslator2.java new file mode 100644 index 00000000000..ea76a625ef1 --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpointAttributeTranslator2.java @@ -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; + } + +} diff --git a/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoints.java b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoints.java new file mode 100644 index 00000000000..e5185ca7c1a --- /dev/null +++ b/dsf/org.eclipse.cdt.tests.dsf/src/org/eclipse/cdt/tests/dsf/breakpoints/DsfTestBreakpoints.java @@ -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"); + } + } +} |