From 35a1eb1832871fcb3488380c6fef588e5a342629 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sat, 26 Jan 2013 22:53:54 -0500 Subject: [PATCH] Bug 399163 - [reverse] Make use of GDB's new =record-started/stopped MI events Change-Id: I168b4734a2971bd71ebd34532bb118aa72ccc70b Reviewed-on: https://git.eclipse.org/r/9957 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../commands/ReverseToggleCommandHandler.java | 6 + .../ui/commands/GdbReverseToggleCommand.java | 58 +++++++++- .../dsf/gdb/service/GDBRunControl_7_0.java | 30 ++++- .../dsf/gdb/service/GDBRunControl_7_6.java | 104 +++++++++++++++++ .../gdb/service/GdbDebugServicesFactory.java | 3 + .../dsf/gdb/service/IReverseRunControl.java | 69 ++++++++++- .../GDBConsoleSynchronizingTest_7_6.java | 108 ++++++++++++++++++ 7 files changed, 373 insertions(+), 5 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_6.java diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/ReverseToggleCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/ReverseToggleCommandHandler.java index dd917d98ddc..64f1a4e5cc3 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/ReverseToggleCommandHandler.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/ReverseToggleCommandHandler.java @@ -124,6 +124,12 @@ public class ReverseToggleCommandHandler extends DebugCommandHandler implements return adapter; } + /* + * (non-Javadoc) + * @see org.eclipse.debug.ui.actions.DebugCommandHandler#postExecute(org.eclipse.debug.core.IRequest, java.lang.Object[]) + * + * We keep this logic for users that may not do the refresh themselves. + */ @Override protected void postExecute(IRequest request, Object[] targets) { super.postExecute(request, targets); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbReverseToggleCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbReverseToggleCommand.java index dd236ed83d0..d02a5008215 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbReverseToggleCommand.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbReverseToggleCommand.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Ericsson and others. + * Copyright (c) 2009, 2013 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 @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Listen for IReverseModeChangedDMEvent (Bug 399163) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.commands; @@ -16,6 +17,7 @@ import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.model.IReverseToggleHandler; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; @@ -24,15 +26,23 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl; +import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl.IReverseModeChangedDMEvent; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.IRequest; import org.eclipse.debug.core.commands.AbstractDebugCommand; import org.eclipse.debug.core.commands.IDebugCommandRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.progress.WorkbenchJob; +import org.eclipse.ui.services.IEvaluationService; /** * Command that toggles the Reverse Debugging feature @@ -42,13 +52,33 @@ import org.eclipse.debug.core.commands.IEnabledStateRequest; public class GdbReverseToggleCommand extends AbstractDebugCommand implements IReverseToggleHandler { private final DsfExecutor fExecutor; private final DsfServicesTracker fTracker; + private final DsfSession fSession; public GdbReverseToggleCommand(DsfSession session) { fExecutor = session.getExecutor(); fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); + fSession = session; + try { + fExecutor.execute(new DsfRunnable() { + @Override + public void run() { + fSession.addServiceEventListener(GdbReverseToggleCommand.this, null); + } + }); + } catch(RejectedExecutionException e) {} } public void dispose() { + try { + fExecutor.execute(new DsfRunnable() { + @Override + public void run() { + fSession.removeServiceEventListener(GdbReverseToggleCommand.this); + } + }); + } catch (RejectedExecutionException e) { + // Session already gone. + } fTracker.dispose(); } @@ -195,4 +225,30 @@ public class GdbReverseToggleCommand extends AbstractDebugCommand implements IRe return false; } + + /** + * @noreference This method is not intended to be referenced by clients. + */ + @DsfServiceEventHandler + public void eventDispatched(IReverseModeChangedDMEvent e) { + new WorkbenchJob("") { //$NON-NLS-1$ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + // Request re-evaluation of property "org.eclipse.cdt.debug.ui.isReverseDebuggingEnabled" to update + // visibility of reverse stepping commands. + IEvaluationService exprService = (IEvaluationService) PlatformUI.getWorkbench().getService(IEvaluationService.class); + if (exprService != null) { + exprService.requestEvaluation("org.eclipse.cdt.debug.ui.isReverseDebuggingEnabled"); //$NON-NLS-1$ + } + // Refresh reverse toggle commands with the new state of reverse enabled. + // This is in order to keep multiple toggle actions in UI in sync. + ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); + if (commandService != null) { + commandService.refreshElements("org.eclipse.cdt.debug.ui.command.reverseToggle", null); //$NON-NLS-1$ + } + + return Status.OK_STATUS; + } + }.schedule(); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java index eb6abfb6adf..f5f8f1b8055 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Wind River Systems and others. + * Copyright (c) 2008, 2013 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 @@ -11,6 +11,7 @@ * Ericsson - Version 7.0 * Nokia - create and use backend service. * Ericsson - Added IReverseControl support + * Marc Khouzam (Ericsson) - Added IReverseModeChangedDMEvent (Bug 399163) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -21,6 +22,7 @@ import java.util.Hashtable; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; @@ -52,6 +54,22 @@ import org.eclipse.core.runtime.Status; public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunControl { + /** @since 4.2 */ + protected static class GdbReverseModeChangedDMEvent extends AbstractDMEvent + implements IReverseModeChangedDMEvent { + private boolean fIsEnabled; + + public GdbReverseModeChangedDMEvent(ICommandControlDMContext context, boolean enabled) { + super(context); + fIsEnabled = enabled; + } + + @Override + public boolean isReverseModeEnabled() { + return fIsEnabled; + } + } + private static class RunToLineActiveOperation { private IMIExecutionDMContext fThreadContext; private int fBpId; @@ -75,6 +93,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } } + private IMICommandControl fCommandControl; private IGDBBackend fGdb; private IMIProcesses fProcService; private CommandFactory fCommandFactory; @@ -111,7 +130,8 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro fGdb = getServicesTracker().getService(IGDBBackend.class); fProcService = getServicesTracker().getService(IMIProcesses.class); - fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + fCommandControl = getServicesTracker().getService(IMICommandControl.class); + fCommandFactory = fCommandControl.getCommandFactory(); if (fGdb.getSessionType() == SessionType.CORE) { // No execution for core files, so no support for reverse @@ -628,6 +648,10 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro /** @since 2.0 */ public void setReverseModeEnabled(boolean enabled) { - fReverseModeEnabled = enabled; + if (fReverseModeEnabled != enabled) { + fReverseModeEnabled = enabled; + getSession().dispatchEvent(new GdbReverseModeChangedDMEvent(fCommandControl.getContext(), fReverseModeEnabled), + getProperties()); + } } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_6.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_6.java new file mode 100644 index 00000000000..0e5a3cc3c7a --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_6.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2013 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: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.service; + + +import java.util.Hashtable; + +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IRunControl2; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; +import org.eclipse.cdt.dsf.debug.service.command.IEventListener; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; +import org.eclipse.cdt.dsf.mi.service.MIRunControl; +import org.eclipse.cdt.dsf.mi.service.command.output.MINotifyAsyncOutput; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * @since 4.2 + */ +public class GDBRunControl_7_6 extends GDBRunControl_7_0 implements IEventListener { + + private ICommandControl fCommandControl; + + public GDBRunControl_7_6(DsfSession session) { + super(session); + } + + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize( + new ImmediateRequestMonitor(requestMonitor) { + @Override + public void handleSuccess() { + doInitialize(requestMonitor); + }}); + } + + private void doInitialize(final RequestMonitor requestMonitor) { + + fCommandControl = getServicesTracker().getService(ICommandControl.class); + + if (fCommandControl == null) { + requestMonitor.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$ + return; + } + + fCommandControl.addEventListener(this); + + register(new String[]{IRunControl.class.getName(), + IRunControl2.class.getName(), + IMIRunControl.class.getName(), + MIRunControl.class.getName(), + GDBRunControl_7_0.class.getName(), + GDBRunControl_7_6.class.getName(), + IReverseRunControl.class.getName()}, + new Hashtable()); + requestMonitor.done(); + } + + @Override + public void shutdown(final RequestMonitor requestMonitor) { + if (fCommandControl != null) { + fCommandControl.removeEventListener(this); + } + unregister(); + super.shutdown(requestMonitor); + } + + @Override + public void eventReceived(Object output) { + if (output instanceof MIOutput) { + MIOOBRecord[] records = ((MIOutput)output).getMIOOBRecords(); + for (MIOOBRecord r : records) { + if (r instanceof MINotifyAsyncOutput) { + MINotifyAsyncOutput notifyOutput = (MINotifyAsyncOutput)r; + String asyncClass = notifyOutput.getAsyncClass(); + // These events have been added with GDB 7.6 + if ("record-started".equals(asyncClass) || //$NON-NLS-1$ + "record-stopped".equals(asyncClass)) { //$NON-NLS-1$ + + boolean enable = "record-started".equals(asyncClass); //$NON-NLS-1$ + setReverseModeEnabled(enable); + } + } + } + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index 0a62d53fb65..d01fcd6e7de 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -215,6 +215,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { @Override protected IRunControl createRunControlService(DsfSession session) { + if (GDB_7_6_VERSION.compareTo(fVersion) <= 0) { + return new GDBRunControl_7_6(session); + } if (GDB_7_0_VERSION.compareTo(fVersion) <= 0) { return new GDBRunControl_7_0(session); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IReverseRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IReverseRunControl.java index 6751d3f4ee3..3d03793bc9c 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IReverseRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IReverseRunControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Ericsson and others. + * Copyright (c) 2009, 2013 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 @@ -7,27 +7,94 @@ * * Contributors: * Ericsson - Initial API and implementation + * Marc Khouzam (Ericsson) - Added IReverseModeChangedDMEvent (Bug 399163) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.IDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; /** + * This interface provides access to controlling and monitoring the reverse execution + * state of a process being debugged. + * * @since 2.0 */ public interface IReverseRunControl { + /** + * Indicates that the enablement of reverse debugging has changed. + * + * @since 4.2 + */ + interface IReverseModeChangedDMEvent extends IDMEvent { + /** + * @return the new state of reverse mode. + */ + boolean isReverseModeEnabled(); + }; + + /** + * Establish if a reverse-resume operation is allowed on the specified context. + * + * @param context The thread or process on which the reverse operation will apply + * @param rm Will contain the result of the operation, true or false, not null. + */ void canReverseResume(IExecutionDMContext context, DataRequestMonitor rm); + + /** + * Perform a reverse-resume operation on the specified context. + * + * @param context The thread or process on which the reverse operation will apply + */ void reverseResume(IExecutionDMContext context, RequestMonitor requestMonitor); + + /** + * Returns whether a reverse-step operation is on-going for the specified context. + * + * @param context The thread or process on which the reverse operation will apply + * @return True if a reverse-steop operation is on-going, false otherwise. + */ boolean isReverseStepping(IExecutionDMContext context); + + /** + * Establish if a reverse-step operation is allowed on the specified context. + * + * @param context The thread or process on which the reverse operation will apply + * @param rm Will contain the result of the operation, true or false, not null. + */ void canReverseStep(IExecutionDMContext context, StepType stepType, DataRequestMonitor rm); + + /** + * Perform a reverse-step operation on the specified context with the specified step type. + * + * @param context The thread or process on which the reverse operation will apply + * @param stepType The step type to be used for the operation + */ void reverseStep(IExecutionDMContext context, StepType stepType, RequestMonitor requestMonitor); + /** + * Establish if it is possible to enable reverse debugging. + * + * @param rm Will contain the result of the operation, true or false, not null. + */ void canEnableReverseMode(ICommandControlDMContext context, DataRequestMonitor rm); + + /** + * Establish if reverse debugging is enabled. + * + * @param rm Will contain the result of the operation, true or false, not null. + */ void isReverseModeEnabled(ICommandControlDMContext context, DataRequestMonitor rm); + + /** + * Enable or disable reverse debugging based on the enable parameter. + * + * @param enable True if reverse debugging should enabled, false for disabled. + */ void enableReverseMode(ICommandControlDMContext context, boolean enable, RequestMonitor rm); } diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_6/GDBConsoleSynchronizingTest_7_6.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_6/GDBConsoleSynchronizingTest_7_6.java index 015ebae46bb..14eeaa21486 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_6/GDBConsoleSynchronizingTest_7_6.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/tests_7_6/GDBConsoleSynchronizingTest_7_6.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_6; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; @@ -20,6 +21,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; @@ -31,7 +33,10 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IMemory; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; +import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl; +import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl.IReverseModeChangedDMEvent; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; @@ -63,6 +68,7 @@ public class GDBConsoleSynchronizingTest_7_6 extends BaseTestCase { private IGDBControl fCommandControl; private IMemory fMemoryService; private IExpressions fExprService; + private IRunControl fRunControl; private List> fEventsReceived = new ArrayList>(); @@ -98,6 +104,9 @@ public class GDBConsoleSynchronizingTest_7_6 extends BaseTestCase { fExprService = fServicesTracker.getService(IExpressions.class); Assert.assertTrue(fExprService != null); + fRunControl = fServicesTracker.getService(IRunControl.class); + Assert.assertTrue(fRunControl != null); + // Register to breakpoint events fSession.addServiceEventListener(GDBConsoleSynchronizingTest_7_6.this, null); } @@ -293,6 +302,105 @@ public class GDBConsoleSynchronizingTest_7_6 extends BaseTestCase { assertEquals(newValue, exprValue); } + /** + * This test verifies that enabling reverse debugging from the + * console will properly trigger a DSF event to indicate the change and + * will be processed by the service. + */ + @Test + public void testEnableRecord() throws Throwable { + assertTrue("Reverse debugging is not supported", fRunControl instanceof IReverseRunControl); + final IReverseRunControl reverseService = (IReverseRunControl)fRunControl; + + SyncUtil.runToLocation("testMemoryChanges"); + + // check starting state + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + reverseService.isReverseModeEnabled(fCommandControl.getContext(), rm); + } + }; + + fSession.getExecutor().execute(query); + Boolean enabled = query.get(); + assertTrue("Reverse debugging should not be enabled", !enabled); + + fEventsReceived.clear(); + + queueConsoleCommand("record"); + + // Wait for the event + IReverseModeChangedDMEvent event = waitForEvent(IReverseModeChangedDMEvent.class); + assertEquals(true, event.isReverseModeEnabled()); + + // Check the service + query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + reverseService.isReverseModeEnabled(fCommandControl.getContext(), rm); + } + }; + fSession.getExecutor().execute(query); + enabled = query.get(); + assertTrue("Reverse debugging should be enabled", enabled); + } + + /** + * This test verifies that disabling reverse debugging from the + * console will properly trigger a DSF event to indicate the change and + * will be processed by the service. + */ + @Test + public void testDisableRecord() throws Throwable { + assertTrue("Reverse debugging is not supported", fRunControl instanceof IReverseRunControl); + final IReverseRunControl reverseService = (IReverseRunControl)fRunControl; + + SyncUtil.runToLocation("testMemoryChanges"); + + fEventsReceived.clear(); + + // check starting state + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + reverseService.enableReverseMode(fCommandControl.getContext(), true, + new ImmediateRequestMonitor(rm) { + @Override + protected void handleSuccess() { + reverseService.isReverseModeEnabled(fCommandControl.getContext(), rm); + } + }); + } + }; + + fSession.getExecutor().execute(query); + Boolean enabled = query.get(); + assertTrue("Reverse debugging should be enabled", enabled); + + // Wait for the event to avoid confusing it with the next one + IReverseModeChangedDMEvent event = waitForEvent(IReverseModeChangedDMEvent.class); + assertEquals(true, event.isReverseModeEnabled()); + fEventsReceived.clear(); + + queueConsoleCommand("record stop"); + + // Wait for the event + event = waitForEvent(IReverseModeChangedDMEvent.class); + assertEquals(false, event.isReverseModeEnabled()); + + // Check the service + query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + reverseService.isReverseModeEnabled(fCommandControl.getContext(), rm); + } + }; + fSession.getExecutor().execute(query); + enabled = query.get(); + assertTrue("Reverse debugging should not be enabled", !enabled); + } + ////////////////////////////////////////////////////////////////////////////////////// // End of tests //////////////////////////////////////////////////////////////////////////////////////