Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java')
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java689
1 files changed, 689 insertions, 0 deletions
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java
new file mode 100644
index 000000000..811d7bff6
--- /dev/null
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java
@@ -0,0 +1,689 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Wind River Systems, Inc. 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.tcf.debug.test;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+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.core.runtime.NullProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDisconnect;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.jface.dialogs.MessageDialogWithToggle;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.tcf.debug.test.services.BreakpointsCM;
+import org.eclipse.tcf.debug.test.services.DiagnosticsCM;
+import org.eclipse.tcf.debug.test.services.LineNumbersCM;
+import org.eclipse.tcf.debug.test.services.ProcessesCM;
+import org.eclipse.tcf.debug.test.services.RegistersCM;
+import org.eclipse.tcf.debug.test.services.RunControlCM;
+import org.eclipse.tcf.debug.test.services.RunControlCM.ContextState;
+import org.eclipse.tcf.debug.test.services.StackTraceCM;
+import org.eclipse.tcf.debug.test.services.SymbolsCM;
+import org.eclipse.tcf.debug.test.util.AggregateCallback;
+import org.eclipse.tcf.debug.test.util.Callback;
+import org.eclipse.tcf.debug.test.util.Callback.ICanceledListener;
+import org.eclipse.tcf.debug.test.util.DataCallback;
+import org.eclipse.tcf.debug.test.util.ICache;
+import org.eclipse.tcf.debug.test.util.Query;
+import org.eclipse.tcf.debug.test.util.Task;
+import org.eclipse.tcf.debug.test.util.Transaction;
+import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate;
+import org.eclipse.tcf.protocol.IChannel;
+import org.eclipse.tcf.protocol.IPeer;
+import org.eclipse.tcf.protocol.JSON;
+import org.eclipse.tcf.protocol.Protocol;
+import org.eclipse.tcf.services.IBreakpoints;
+import org.eclipse.tcf.services.IDiagnostics;
+import org.eclipse.tcf.services.IDiagnostics.ISymbol;
+import org.eclipse.tcf.services.IExpressions;
+import org.eclipse.tcf.services.ILineNumbers;
+import org.eclipse.tcf.services.IMemoryMap;
+import org.eclipse.tcf.services.IProcesses;
+import org.eclipse.tcf.services.IRegisters;
+import org.eclipse.tcf.services.IRegisters.RegistersContext;
+import org.eclipse.tcf.services.IRunControl;
+import org.eclipse.tcf.services.IRunControl.RunControlContext;
+import org.eclipse.tcf.services.IStackTrace;
+import org.eclipse.tcf.services.ISymbols;
+import org.eclipse.tcf.te.tests.interfaces.IConfigurationProperties;
+import org.eclipse.tcf.te.tests.tcf.TcfTestCase;
+import org.junit.Assert;
+import org.osgi.framework.Bundle;
+
+/**
+ * Base test for validating TCF Debugger UI.
+ */
+@SuppressWarnings("restriction")
+public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdatesListenerConstants {
+
+ private final static int NUM_CHANNELS = 1;
+
+ protected IChannel[] channels;
+
+ private Query<Object> fMonitorChannelQuery;
+ private List<Throwable> errors = new ArrayList<Throwable>();
+ protected ILaunch fLaunch;
+
+ protected Object fTestRunKey;
+
+ protected IDiagnostics diag;
+ protected IExpressions expr;
+ protected ISymbols syms;
+ protected IStackTrace stk;
+ protected IRunControl rc;
+ protected IBreakpoints bp;
+ protected IMemoryMap fMemoryMap;
+ protected ILineNumbers fLineNumbers;
+ protected IRegisters fRegisters;
+ protected IProcesses fProcesses;
+
+ protected RunControlCM fRunControlCM;
+ protected DiagnosticsCM fDiagnosticsCM;
+ protected BreakpointsCM fBreakpointsCM;
+ protected StackTraceCM fStackTraceCM;
+ protected SymbolsCM fSymbolsCM;
+ protected LineNumbersCM fLineNumbersCM;
+ protected RegistersCM fRegistersCM;
+ protected ProcessesCM fProcessesCM;
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tests.CoreTestCase#getTestBundle()
+ */
+ @Override
+ protected Bundle getTestBundle() {
+ return Activator.getDefault().getBundle();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.tests.CoreTestCase#initialize()
+ */
+ @Override
+ protected void initialize() {
+ // Turn off the automatic perspective switch and debug view activation to avoid
+ // JFace views from interfering with the virtual viewers used in tests.
+ IPreferenceStore prefs = DebugUITools.getPreferenceStore();
+ prefs.setValue(IInternalDebugUIConstants.PREF_ACTIVATE_DEBUG_VIEW, false);
+ prefs.setValue(IInternalDebugUIConstants.PREF_SWITCH_PERSPECTIVE_ON_SUSPEND, MessageDialogWithToggle.NEVER);
+
+ super.initialize();
+ // Do not activate debug view or debug perspective, also to avoid interfering
+ // with tests' virtual viewers.
+ setProperty(IConfigurationProperties.TARGET_PERSPECTIVE, "org.eclipse.cdt.ui.CPerspective"); //$NON-NLS-1$
+ setProperty(IConfigurationProperties.TARGET_VIEW, "org.eclipse.cdt.ui.CView"); //$NON-NLS-1$
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ fTestRunKey = new Object();
+
+ // Launch the agent
+ super.setUp();
+ createLaunch();
+
+ channels = new IChannel[NUM_CHANNELS];
+
+ new Query<Object>() {
+ @Override
+ protected void execute(DataCallback<Object> callback) {
+ try {
+ openChannels(peer, callback);
+ }
+ catch (Throwable x) {
+ errors.add(x);
+ int cnt = 0;
+ for (int i = 0; i < channels.length; i++) {
+ if (channels[i] == null) continue;
+ if (channels[i].getState() != IChannel.STATE_CLOSED) channels[i].close();
+ cnt++;
+ }
+ if (cnt == 0) {
+ callback.setError(errors.get(0));
+ callback.done();
+ }
+ }
+ }
+ }.get();
+
+ getRemoteServices();
+
+ new Task<Object>() {
+ @Override
+ public Object call() throws Exception {
+ setUpServiceListeners();
+ return null;
+ }
+ }.get();
+
+ validateTestAvailable();
+ clearBreakpoints();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ new Task<Object>() {
+ @Override
+ public Object call() throws Exception {
+ tearDownServiceListeners();
+ return null;
+ }
+ }.get();
+
+ terminateLaunch();
+
+ new Query<Object>() {
+ @Override
+ protected void execute(DataCallback<Object> callback) {
+ closeChannels(callback);
+ }
+ }.get();
+
+ super.tearDown();
+ }
+
+ protected String getDiagnosticsTestName() {
+ return "RCBP1";
+ }
+
+ protected void setUpServiceListeners() throws Exception{
+ fRunControlCM = new RunControlCM(rc);
+ fDiagnosticsCM = new DiagnosticsCM(diag);
+ fBreakpointsCM = new BreakpointsCM(bp);
+ fStackTraceCM = new StackTraceCM(stk, rc);
+ fSymbolsCM = new SymbolsCM(syms, fRunControlCM, fMemoryMap);
+ fLineNumbersCM = new LineNumbersCM(fLineNumbers, fMemoryMap, fRunControlCM);
+ fRegistersCM = new RegistersCM(fRegisters, rc);
+ fProcessesCM = new ProcessesCM(fProcesses);
+ }
+
+ protected void tearDownServiceListeners() throws Exception{
+ fProcessesCM.dispose();
+ fRegistersCM.dispose();
+ fSymbolsCM.dispose();
+ fBreakpointsCM.dispose();
+ fStackTraceCM.dispose();
+ fRunControlCM.dispose();
+ fDiagnosticsCM.dispose();
+ fLineNumbersCM.dispose();
+ }
+
+
+ private void createLaunch() throws Exception {
+ ILaunchManager lManager = DebugPlugin.getDefault().getLaunchManager();
+ ILaunchConfigurationType lcType = lManager.getLaunchConfigurationType("org.eclipse.tcf.debug.LaunchConfigurationType");
+ ILaunchConfigurationWorkingCopy lcWc = lcType.newInstance(null, "test");
+ lcWc.setAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, false);
+ lcWc.setAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false);
+ lcWc.setAttribute(TCFLaunchDelegate.ATTR_PEER_ID, peer.getID());
+ lcWc.doSave();
+ fLaunch = lcWc.launch("debug", new NullProgressMonitor());
+ Assert.assertTrue( fLaunch instanceof IDisconnect );
+ }
+
+ private void terminateLaunch() throws DebugException, InterruptedException, ExecutionException {
+ ((IDisconnect)fLaunch).disconnect();
+
+ new Query<Object>() {
+ @Override
+ protected void execute(final DataCallback<Object> callback) {
+ final ILaunchManager lm = DebugPlugin.getDefault().getLaunchManager();
+
+ final AtomicBoolean callbackDone = new AtomicBoolean(false);
+ ILaunchesListener2 disconnectListener = new ILaunchesListener2() {
+ public void launchesAdded(ILaunch[] launches) {}
+ public void launchesChanged(ILaunch[] launches) {}
+ public void launchesRemoved(ILaunch[] launches) {}
+ public void launchesTerminated(ILaunch[] launches) {
+ if (Arrays.asList(launches).contains(fLaunch)) {
+ if (!callbackDone.getAndSet(true)) {
+ lm.removeLaunchListener(this);
+ callback.done();
+ }
+ }
+ }
+ };
+ lm.addLaunchListener(disconnectListener);
+ if (((IDisconnect)fLaunch).isDisconnected() && !callbackDone.getAndSet(true)) {
+ lm.removeLaunchListener(disconnectListener);
+ callback.done();
+
+ }
+ }
+ }.get();
+ }
+
+ private void getRemoteServices() {
+ assert !Protocol.isDispatchThread();
+ Protocol.invokeAndWait(new Runnable() {
+ public void run() {
+ diag = channels[0].getRemoteService(IDiagnostics.class);
+ expr = channels[0].getRemoteService(IExpressions.class);
+ syms = channels[0].getRemoteService(ISymbols.class);
+ stk = channels[0].getRemoteService(IStackTrace.class);
+ rc = channels[0].getRemoteService(IRunControl.class);
+ bp = channels[0].getRemoteService(IBreakpoints.class);
+ fMemoryMap = channels[0].getRemoteService(IMemoryMap.class);
+ fLineNumbers = channels[0].getRemoteService(ILineNumbers.class);
+ fRegisters = channels[0].getRemoteService(IRegisters.class);
+ fProcesses = channels[0].getRemoteService(IProcesses.class);
+ };
+ });
+ }
+
+ private void openChannels(IPeer peer, Callback callback) {
+ assert Protocol.isDispatchThread();
+
+ for (int i = 0; i < channels.length; i++) {
+ channels[i] = peer.openChannel();
+ }
+ monitorChannels(
+ new Callback(callback) {
+ @Override
+ protected void handleSuccess() {
+ fMonitorChannelQuery = new Query<Object>() {
+ @Override
+ protected void execute(org.eclipse.tcf.debug.test.util.DataCallback<Object> callback) {
+ monitorChannels(callback, true);
+ };
+ };
+ fMonitorChannelQuery.invoke();
+ super.handleSuccess();
+ }
+ },
+ false);
+ }
+
+ private void closeChannels(final Callback callback) {
+ assert Protocol.isDispatchThread();
+ fMonitorChannelQuery.cancel(false);
+ try {
+ fMonitorChannelQuery.get();
+ } catch (ExecutionException e) {
+ callback.setError(e.getCause());
+ } catch (CancellationException e) {
+ // expected
+ } catch (InterruptedException e) {
+ }
+
+ for (int i = 0; i < channels.length; i++) {
+ if (channels[i].getState() != IChannel.STATE_CLOSED) channels[i].close();
+ }
+ monitorChannels(callback, true);
+ }
+
+ private static class ChannelMonitorListener implements IChannel.IChannelListener {
+
+ final IChannel fChannel;
+ final boolean fClose;
+ final Callback fCallback;
+ private boolean fActive = true;
+
+ private class CancelListener implements ICanceledListener {
+ public void requestCanceled(Callback rm) {
+ Protocol.invokeLater(new Runnable() {
+ public void run() {
+ if (deactivate()) {
+ fCallback.done();
+ }
+ }
+ });
+ }
+ }
+
+ private boolean deactivate() {
+ if (fActive) {
+ fChannel.removeChannelListener(ChannelMonitorListener.this);
+ fActive = false;
+ return true;
+ }
+ return false;
+ }
+
+ ChannelMonitorListener (IChannel channel, Callback cb, boolean close) {
+ fCallback = cb;
+ fClose = close;
+ fChannel = channel;
+ fChannel.addChannelListener(this);
+ fCallback.addCancelListener(new CancelListener());
+ }
+
+ public void onChannelOpened() {
+ if (!deactivate()) return;
+
+ fChannel.removeChannelListener(this);
+ fCallback.done();
+ }
+
+ public void congestionLevel(int level) {
+ }
+
+ public void onChannelClosed(Throwable error) {
+ if (!deactivate()) return;
+
+ if (!fClose) {
+ fCallback.setError( new IOException("Remote peer closed connection before all tests finished") );
+ } else {
+ fCallback.setError(error);
+ }
+ fCallback.done();
+ }
+ }
+
+ protected void monitorChannels(final Callback callback, final boolean close) {
+ assert Protocol.isDispatchThread();
+
+ AggregateCallback acb = new AggregateCallback(callback);
+ int count = 0;
+ for (int i = 0; i < channels.length; i++) {
+ if (!checkChannelsState(channels[i], close)) {
+ new ChannelMonitorListener(channels[i], new Callback(acb), close);
+ count++;
+ }
+ }
+ acb.setDoneCount(count);
+ }
+
+ // Checks whether all channels have achieved the desired state.
+ private boolean checkChannelsState(IChannel channel, boolean close) {
+ if (close) {
+ if (channel.getState() != IChannel.STATE_CLOSED) {
+ return false;
+ }
+ } else {
+ if (channel.getState() != IChannel.STATE_OPEN) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void validateTestAvailable() throws ExecutionException, InterruptedException {
+ String[] testList = new Transaction<String[]>() {
+ @Override
+ protected String[] process() throws InvalidCacheException ,ExecutionException {
+ return validate( fDiagnosticsCM.getTestList() );
+ }
+ }.get();
+
+ int i = 0;
+ for (; i < testList.length; i++) {
+ if ("RCBP1".equals(testList[i])) break;
+ }
+
+ Assert.assertTrue("Required test not supported", i != testList.length);
+ }
+
+ protected void clearBreakpoints() throws InterruptedException, ExecutionException, CoreException {
+
+ // Delete eclipse breakpoints.
+ IWorkspaceRunnable wr = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IBreakpointManager mgr = DebugPlugin.getDefault().getBreakpointManager();
+ IBreakpoint[] bps = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
+ mgr.removeBreakpoints(bps, true);
+ }
+ };
+ ResourcesPlugin.getWorkspace().run(wr, null, 0, null);
+
+ // Delete TCF breakpoints
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ // Initialize the event cache for breakpoint status
+ @SuppressWarnings("unchecked")
+ Map<String, Object>[] bps = new Map[] { };
+ validate( fBreakpointsCM.set(bps, this) );
+ return null;
+ }
+ }.get();
+ }
+
+ private TestProcessInfo startProcess() throws InterruptedException, ExecutionException {
+ return new Transaction<TestProcessInfo>() {
+ @Override
+ protected TestProcessInfo process() throws Transaction.InvalidCacheException ,ExecutionException {
+ String testId = validate( fDiagnosticsCM.runTest(getDiagnosticsTestName(), this) );
+ RunControlContext testCtx = validate( fRunControlCM.getContext(testId) );
+ String processId = testCtx.getProcessID();
+ // Create the cache to listen for exceptions.
+ fRunControlCM.waitForContextException(testId, fTestRunKey);
+
+ String threadId = "";
+ if (!processId.equals(testId)) {
+ threadId = testId;
+ } else {
+ String[] threads = validate( fRunControlCM.getChildren(processId) );
+ threadId = threads[0];
+ }
+ RunControlContext threadCtx = validate( fRunControlCM.getContext(threadId) );
+
+ Assert.assertTrue("Invalid thread context", threadCtx.hasState());
+
+ return new TestProcessInfo(testId, testCtx, processId, threadId, threadCtx);
+ };
+ }.get();
+ }
+
+ private boolean runToTestEntry(final TestProcessInfo processInfo, final String testFunc) throws InterruptedException, ExecutionException {
+ return new Transaction<Boolean>() {
+ Object fWaitForResumeKey;
+ Object fWaitForSuspendKey;
+ boolean fSuspendEventReceived = false;
+ @Override
+ protected Boolean process() throws Transaction.InvalidCacheException ,ExecutionException {
+ ISymbol sym_func0 = validate( fDiagnosticsCM.getSymbol(processInfo.fProcessId, testFunc) );
+ String sym_func0_value = sym_func0.getValue().toString();
+ ContextState state = validate (fRunControlCM.getState(processInfo.fThreadId));
+
+ while (!state.suspended || !new BigInteger(state.pc).equals(new BigInteger(sym_func0_value))) {
+ if (state.suspended && fWaitForSuspendKey == null) {
+ fSuspendEventReceived = true;
+ // We are not at test entry. Create a new suspend wait cache.
+ fWaitForResumeKey = new Object();
+ fWaitForSuspendKey = new Object();
+ ICache<Object> waitForResume = fRunControlCM.waitForContextResumed(processInfo.fThreadId, fWaitForResumeKey);
+
+ // Issue resume command.
+ validate( fRunControlCM.resume(processInfo.fThreadCtx, fWaitForResumeKey, IRunControl.RM_RESUME, 1) );
+
+ // Wait until we receive the resume event.
+ validate(waitForResume);
+ fWaitForSuspendKey = new Object();
+ fRunControlCM.waitForContextSuspended(processInfo.fThreadId, fWaitForSuspendKey);
+ } else {
+ if (fWaitForResumeKey != null) {
+ // Validate resume command
+ validate( fRunControlCM.resume(processInfo.fThreadCtx, fWaitForResumeKey, IRunControl.RM_RESUME, 1) );
+ fWaitForResumeKey = null;
+
+ }
+ // Wait until we suspend.
+ validate( fRunControlCM.waitForContextSuspended(processInfo.fThreadId, fWaitForSuspendKey) );
+ fWaitForSuspendKey = null;
+ }
+ }
+
+ return fSuspendEventReceived;
+ }
+ }.get();
+ }
+
+ protected TestProcessInfo startProcess(String testFunc) throws Exception {
+ String bpId = "entryPointBreakpoint";
+ createBreakpoint(bpId, testFunc);
+
+ final TestProcessInfo processInfo = startProcess();
+
+ runToTestEntry(processInfo, testFunc);
+ removeBreakpoint(bpId);
+
+ new Transaction<String>() {
+ @Override
+ protected String process() throws InvalidCacheException, ExecutionException {
+ String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
+ Assert.assertTrue("No stack frames" , frameIds.length != 0);
+ return frameIds[frameIds.length - 1];
+ }
+ }.get();
+
+ return processInfo;
+ }
+
+ protected ContextState resumeAndWaitForSuspend(final RunControlContext context, final int mode) throws InterruptedException, ExecutionException {
+ return new Transaction<ContextState>() {
+ @Override
+ protected ContextState process() throws InvalidCacheException, ExecutionException {
+ ICache<Object> waitCache = fRunControlCM.waitForContextSuspended(context.getID(), this);
+ validate( fRunControlCM.resume(context, this, mode, 1) );
+ validate(waitCache);
+ return validate( fRunControlCM.getState(context.getID()) );
+ }
+ }.get();
+ }
+
+ protected void createBreakpoint(final String bpId, final String testFunc)
+ throws InterruptedException, ExecutionException
+ {
+ new Transaction<Object>() {
+ private Map<String,Object> fBp;
+ {
+ fBp = new TreeMap<String,Object>();
+ fBp.put(IBreakpoints.PROP_ID, bpId);
+ fBp.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE);
+ fBp.put(IBreakpoints.PROP_LOCATION, testFunc);
+ }
+
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ // Prime event wait caches
+ fBreakpointsCM.waitContextAdded(this);
+
+ validate( fBreakpointsCM.add(fBp, this) );
+ validate( fBreakpointsCM.waitContextAdded(this));
+
+ // Wait for breakpoint status event and validate it.
+ Map<String, Object> status = validate(fBreakpointsCM.getStatus(bpId));
+ String s = (String)status.get(IBreakpoints.STATUS_ERROR);
+ if (s != null) {
+ Assert.fail("Invalid BP status: " + s);
+ }
+ @SuppressWarnings("unchecked")
+ Collection<Map<String,Object>> list =
+ (Collection<Map<String,Object>>)status.get(IBreakpoints.STATUS_INSTANCES);
+ if (list != null) {
+ String err = null;
+ for (Map<String,Object> map : list) {
+ if (map.get(IBreakpoints.INSTANCE_ERROR) != null) {
+ err = (String)map.get(IBreakpoints.INSTANCE_ERROR);
+ }
+ }
+ if (err != null) {
+ Assert.fail("Invalid BP status: " + s);
+ }
+ }
+ return null;
+ }
+ }.get();
+ }
+
+ protected void removeBreakpoint(final String bpId) throws InterruptedException, ExecutionException {
+ new Transaction<Object>() {
+
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+
+ // Prime event wait caches
+ fBreakpointsCM.waitContextRemoved(this);
+
+ // Remove
+ validate( fBreakpointsCM.remove(new String[] { bpId }, this) );
+
+ // Verify removed event
+ String[] removedIds = validate( fBreakpointsCM.waitContextRemoved(this));
+ Assert.assertTrue(Arrays.asList(removedIds).contains(bpId));
+ return null;
+ }
+ }.get();
+ }
+
+ protected void moveToLocation(final String context, final Number address) throws
+ DebugException, ExecutionException, InterruptedException
+ {
+ final RegistersContext pcReg = new Transaction<RegistersContext>() {
+ @Override
+ protected RegistersContext process() throws InvalidCacheException ,ExecutionException {
+ String[] registers = validate(fRegistersCM.getChildren(context));
+ return findPCRegister(registers);
+ }
+
+ private RegistersContext findPCRegister(String[] registerIds) throws InvalidCacheException ,ExecutionException {
+ for (String regId : registerIds) {
+ RegistersContext reg = validate(fRegistersCM.getContext(regId));
+ if ( IRegisters.ROLE_PC.equals(reg.getRole()) ) {
+ return reg;
+ }
+ }
+ for (String regId : registerIds) {
+ String[] children = validate(fRegistersCM.getChildren(regId));
+ RegistersContext pc = findPCRegister(children);
+ if (pc != null) return pc;
+ }
+ return null;
+ }
+ }.get();
+
+ assertNotNull("Cannot find PC register", pcReg);
+
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws Transaction.InvalidCacheException ,ExecutionException {
+ byte[] value = addressToByteArray(address, pcReg.getSize(), pcReg.isBigEndian());
+ validate(fRegistersCM.setContextValue(pcReg, this, value));
+ return null;
+ };
+ }.get();
+ }
+
+ private byte[] addressToByteArray(Number address, int size, boolean bigEndian) {
+ byte[] bytes = new byte[size];
+ byte[] addrBytes = JSON.toBigInteger(address).toByteArray();
+ for (int i=0; i < bytes.length; ++i) {
+ byte b = 0;
+ if (i < addrBytes.length) {
+ b = addrBytes[addrBytes.length - i - 1];
+ }
+ bytes[bigEndian ? size -i - 1 : i] = b;
+ }
+ return bytes;
+ }
+}

Back to the top