Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorPawel Piech2012-06-15 18:08:54 +0000
committerPawel Piech2012-07-20 22:26:47 +0000
commitffcf8a21524290de167d2f0fc05f9b3c33a58c33 (patch)
tree3031245132ae570ff0a74dc443e7d6879fc47b32 /tests
parentbfef150a18afc709a28ea58cbcb2c8a4ab8a134a (diff)
downloadorg.eclipse.tcf-ffcf8a21524290de167d2f0fc05f9b3c33a58c33.tar.gz
org.eclipse.tcf-ffcf8a21524290de167d2f0fc05f9b3c33a58c33.tar.xz
org.eclipse.tcf-ffcf8a21524290de167d2f0fc05f9b3c33a58c33.zip
Bug 380607 - [tests] Intermittent failure in SampleTest.testSteppingDebugViewOnly
Diffstat (limited to 'tests')
-rwxr-xr-x[-rw-r--r--]tests/plugins/org.eclipse.tcf.debug.test/data/agent/linux/x86/agentbin1365704 -> 1365704 bytes
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/pom.xml7
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractCMTest.java689
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractTcfUITest.java6
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RunControlCMTest.java321
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/SampleTest.java157
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/StackTraceCMTest.java93
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/RunControlCM.java37
-rw-r--r--tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/StackTraceCM.java3
9 files changed, 1120 insertions, 193 deletions
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/data/agent/linux/x86/agent b/tests/plugins/org.eclipse.tcf.debug.test/data/agent/linux/x86/agent
index 9bc590e22..9bc590e22 100644..100755
--- a/tests/plugins/org.eclipse.tcf.debug.test/data/agent/linux/x86/agent
+++ b/tests/plugins/org.eclipse.tcf.debug.test/data/agent/linux/x86/agent
Binary files differ
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/pom.xml b/tests/plugins/org.eclipse.tcf.debug.test/pom.xml
index d50d9fde9..2ca083adb 100644
--- a/tests/plugins/org.eclipse.tcf.debug.test/pom.xml
+++ b/tests/plugins/org.eclipse.tcf.debug.test/pom.xml
@@ -33,10 +33,15 @@
<configuration>
<includes>
<include>**/BreakpointsTest.*</include>
+ <include>**/TransactionTests.*</include>
+ <include>**/BreakpointDetailPaneTest.*</include>
+ <include>**/BreakpointsViewTest.*</include>
+ <include>**/RunControlCMTest.*</include>
+ <include>**/StackTraceCMTest.*</include>
<include>**/SampleTest.*</include>
<include>**/CacheTests.*</include>
<include>**/QueryTests.*</include>
- <include>**/TransactionTests.*</include>
+ <include>**/RangeCacheTests.*</include>
</includes>
<!--
<debugPort>8003</debugPort>
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;
+ }
+}
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractTcfUITest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractTcfUITest.java
index b333af29a..b0e924a53 100644
--- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractTcfUITest.java
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/AbstractTcfUITest.java
@@ -654,8 +654,8 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp
// Make sure that delta is posted after launching process so that it doesn't interfere
// with the waiting for the whole viewer to update after breakpoint hit (below).
- fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE);
- fDebugViewListener.resetModelChanged();
+ fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE| CONTENT_SEQUENCE_COMPLETE | LABEL_SEQUENCE_COMPLETE | LABEL_UPDATES);
+ fDebugViewListener.reset();
runToTestEntry(processInfo, testFunc);
removeBreakpoint(bpId);
@@ -678,7 +678,7 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp
fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE | CONTENT_SEQUENCE_COMPLETE | LABEL_SEQUENCE_COMPLETE | LABEL_UPDATES);
VirtualItem topFrameItem = fDebugViewListener.findElement(
- new Pattern[] { Pattern.compile(".*"), Pattern.compile(".*"), Pattern.compile(".*" + processInfo.fProcessId + ".*\\(Breakpoint.*"), Pattern.compile(".*")});
+ new Pattern[] { Pattern.compile(".*"), Pattern.compile(".*"), Pattern.compile(".*" + processInfo.fProcessId + ".*\\(.*[Bb]reakpoint.*"), Pattern.compile(".*")});
if (topFrameItem == null) {
Assert.fail("Top stack frame not found. \n\nDebug view dump: \n:" + fDebugViewViewer.toString());
}
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RunControlCMTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RunControlCMTest.java
new file mode 100644
index 000000000..220a412fd
--- /dev/null
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RunControlCMTest.java
@@ -0,0 +1,321 @@
+/*******************************************************************************
+ * 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.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.tcf.debug.test.services.IWaitForEventCache;
+import org.eclipse.tcf.debug.test.services.RunControlCM;
+import org.eclipse.tcf.debug.test.services.RunControlCM.ContextState;
+import org.eclipse.tcf.debug.test.util.AbstractCache;
+import org.eclipse.tcf.debug.test.util.ICache;
+import org.eclipse.tcf.debug.test.util.Transaction;
+import org.eclipse.tcf.services.IRunControl;
+import org.eclipse.tcf.services.IRunControl.RunControlContext;
+import org.junit.Assert;
+
+public class RunControlCMTest extends AbstractCMTest {
+
+ public void testStateResetOnResumeSuspend() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func0");
+
+ createBreakpoint("test", "tcf_test_func0");
+
+ // Create and validate cache
+ final ICache<ContextState> stateCache = new Transaction<ICache<ContextState>>() {
+ public ICache<ContextState> process() throws InvalidCacheException, ExecutionException {
+ ICache<ContextState> cache = fRunControlCM.getState(processInfo.fThreadId);
+ validate(cache);
+ Assert.assertTrue(cache.getData().suspended == true);
+ return cache;
+ };
+ }.get();
+
+ // Resume thread and wait for suspend
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ IWaitForEventCache<Object> waitResume = fRunControlCM.waitForContextResumed(processInfo.fThreadId, this);
+ IWaitForEventCache<Object> waitSuspend = fRunControlCM.waitForContextSuspended(processInfo.fThreadId, this);
+ validate(fRunControlCM.resume(processInfo.fThreadCtx, this, IRunControl.RM_RESUME, 1));
+ validate(waitResume);
+ if (!waitSuspend.isValid()) {
+ // The state cache should either be invalid, or it should contain updated (running) state.
+ Assert.assertTrue(stateCache.isValid() == false || stateCache.getData().suspended == false);
+ validate(stateCache);
+ Assert.assertTrue(stateCache.getData().suspended == false);
+ }
+ validate(waitSuspend);
+ // The state cache should either be invalid again, or it should contain updated (suspended) state.
+ Assert.assertTrue(stateCache.isValid() == false || stateCache.getData().suspended == true);
+ validate(stateCache);
+ Assert.assertTrue(stateCache.getData().suspended == true);
+
+ return null;
+ }
+ }.get();
+ }
+
+ public void testStateResetOnTerminate() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func0");
+
+ // Create and validate cache
+ final ICache<ContextState> stateCache = new Transaction<ICache<ContextState>>() {
+ public ICache<ContextState> process() throws InvalidCacheException, ExecutionException {
+ ICache<ContextState> cache = fRunControlCM.getState(processInfo.fThreadId);
+ validate(cache);
+ Assert.assertTrue(cache.getData().suspended == true);
+ return cache;
+ };
+ }.get();
+
+ // Terminate process and check state
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ IWaitForEventCache<String[]> wait = fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this);
+ validate(fRunControlCM.terminate(processInfo.fTestCtx, this));
+ validate(wait);
+
+ // The state cache should either be invalid again, or it should contain updated (suspended) state.
+ Assert.assertTrue(stateCache.isValid() == false || stateCache.getError() != null);
+ if (!validateUnchecked(stateCache)) throw new InvalidCacheException();
+ Assert.assertTrue(stateCache.getError() != null);
+
+ return null;
+ }
+ }.get();
+ }
+
+ public void testRunControlCMChildrenInvalidation() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func0");
+
+ createBreakpoint("testRunControlCMChildrenInvalidation", "tcf_test_func0");
+
+ // Wait for each threads to start.
+ final String[] threads = new Transaction<String[]>() {
+ List<String> fThreads = new ArrayList<String>();
+ @Override
+ protected String[] process() throws InvalidCacheException, ExecutionException {
+ IWaitForEventCache<RunControlContext[]> waitCache = fRunControlCM.waitForContextAdded(processInfo.fProcessId, this);
+ validate(fRunControlCM.resume(processInfo.fTestCtx, this, IRunControl.RM_RESUME, 1));
+ RunControlContext[] addedContexts = validate(waitCache);
+ for (RunControlContext addedContext : addedContexts) {
+ fThreads.add(addedContext.getID());
+ }
+ if (fThreads.size() < 4) {
+ waitCache.reset();
+ validate(waitCache);
+ }
+ // Validate children cache
+ String[] children = validate (fRunControlCM.getChildren(processInfo.fProcessId));
+ Assert.assertTrue(
+ "Expected children array to contain added ids",
+ Arrays.asList(children).containsAll(fThreads));
+
+ return fThreads.toArray(new String[fThreads.size()]);
+ }
+ }.get();
+
+ // Wait for each thread to suspend, update caches
+ for (final String thread : threads) {
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ RunControlCM.ContextState state = validate(fRunControlCM.getState(thread));
+ if (!state.suspended) {
+ validate( fRunControlCM.waitForContextSuspended(thread, this) );
+ }
+ String symId = validate( fSymbolsCM.find(thread, new BigInteger(state.pc), "tcf_test_func0") );
+ Number symAddr = validate( fSymbolsCM.getContext(symId) ).getAddress();
+ Assert.assertEquals("Expected thread to suspend at breakpoint address", symAddr.toString(), state.pc);
+ String[] children = validate( fRunControlCM.getChildren(thread));
+ Assert.assertEquals("Expected thread to have no children contexts", 0, children.length);
+ return null;
+ }
+ }.get();
+ }
+
+ // End test, check for removed events and that state caches were cleared
+ new Transaction<String>() {
+ @Override
+ protected String process() throws InvalidCacheException, ExecutionException {
+ // Create wait caches
+ fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this);
+ IWaitForEventCache<?>[] waitCaches = new IWaitForEventCache<?>[threads.length];
+ for (int i = 0; i < threads.length; i++) {
+ waitCaches[i] = fRunControlCM.waitForContextRemoved(threads[i], this);
+ }
+ validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) );
+ validate(waitCaches);
+ validate(fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this));
+
+ try {
+ validate( fRunControlCM.getContext(processInfo.fProcessId) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ validate( fRunControlCM.getState(processInfo.fProcessId) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ String children[] = validate( fRunControlCM.getChildren(processInfo.fProcessId) );
+ Assert.assertEquals("Expected no children", 0, children.length);
+ } catch (ExecutionException e) {}
+
+ for (String thread : threads) {
+ try {
+ validate( fRunControlCM.getContext(thread) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ validate( fRunControlCM.getState(thread) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ }
+
+ return null;
+ }
+ }.get();
+
+ removeBreakpoint("testRunControlCMChildrenInvalidation");
+ }
+
+ public void testChildrenResetOnAddedRemoved() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func0");
+
+ createBreakpoint("test", "tcf_test_func0");
+
+ // Create and validate cache
+ final ICache<String[]> childrenCache = new Transaction<ICache<String[]>>() {
+ public ICache<String[]> process() throws InvalidCacheException, ExecutionException {
+ ICache<String[]> cache = fRunControlCM.getChildren(processInfo.fProcessId);
+ validate(cache);
+ Assert.assertTrue(cache.getData().length == 1);
+ return cache;
+ };
+ }.get();
+
+ // Wait for each threads to start.
+ final String[] threads = new Transaction<String[]>() {
+ List<String> fThreads = new ArrayList<String>();
+ @Override
+ protected String[] process() throws InvalidCacheException, ExecutionException {
+ IWaitForEventCache<RunControlContext[]> waitCache = fRunControlCM.waitForContextAdded(processInfo.fProcessId, this);
+ validate(fRunControlCM.resume(processInfo.fTestCtx, this, IRunControl.RM_RESUME, 1));
+ RunControlContext[] addedContexts = validate(waitCache);
+ for (RunControlContext addedContext : addedContexts) {
+ fThreads.add(addedContext.getID());
+ }
+ if (fThreads.size() < 4) {
+ waitCache.reset();
+ validate(waitCache);
+ }
+
+ // Validate children cache
+ String[] children = validate (childrenCache);
+
+ Assert.assertTrue(
+ "Expected children array to contain added ids",
+ Arrays.asList(children).containsAll(fThreads));
+
+ return fThreads.toArray(new String[fThreads.size()]);
+ }
+ }.get();
+
+ // Wait for each thread to suspend,
+ for (final String thread : threads) {
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ RunControlCM.ContextState state = validate(fRunControlCM.getState(thread));
+ if (!state.suspended) {
+ validate( fRunControlCM.waitForContextSuspended(thread, this) );
+ }
+ String[] children = validate( fRunControlCM.getChildren(thread));
+ Assert.assertEquals("Expected thread to have no children contexts", 0, children.length);
+ return null;
+ }
+ }.get();
+ }
+
+ // End test, check for removed events and that state caches were cleared
+ new Transaction<String>() {
+ @Override
+ protected String process() throws InvalidCacheException, ExecutionException {
+ // Create wait caches
+ fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this);
+ IWaitForEventCache<?>[] waitCaches = new IWaitForEventCache<?>[threads.length];
+ for (int i = 0; i < threads.length; i++) {
+ waitCaches[i] = fRunControlCM.waitForContextRemoved(threads[i], this);
+ }
+ validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) );
+ validate(waitCaches);
+ validate(fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this));
+
+ try {
+ validate( fRunControlCM.getContext(processInfo.fProcessId) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ validate( fRunControlCM.getState(processInfo.fProcessId) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ String children[] = validate( fRunControlCM.getChildren(processInfo.fProcessId) );
+ Assert.assertEquals("Expected no children", 0, children.length);
+ } catch (ExecutionException e) {}
+
+ for (String thread : threads) {
+ try {
+ validate( fRunControlCM.getContext(thread) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ try {
+ validate( fRunControlCM.getState(thread) );
+ Assert.fail("Expected error");
+ } catch (ExecutionException e) {}
+ }
+
+ return null;
+ }
+ }.get();
+ }
+
+ public void testMappingCommandCaches() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func0");
+
+ // Wait for each threads to start.
+ new Transaction<Object>() {
+ ICache<Object> fFirstCommandCache;
+
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ ICache<RunControlContext> contextCache = fRunControlCM.getContext(processInfo.fThreadId);
+ validate(contextCache);
+
+ ICache<Object> resumeCache = fRunControlCM.resume(contextCache.getData(), this, IRunControl.RM_RESUME, 1);
+ if (fFirstCommandCache == null) {
+ // Reset context objet cache to force a new context object to be created and retry.
+ fFirstCommandCache = resumeCache;
+ ((AbstractCache<?>)contextCache).reset();
+ validate(contextCache);
+ }
+ Assert.assertTrue(resumeCache == fFirstCommandCache);
+ return null;
+ }
+ }.get();
+
+ }
+}
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/SampleTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/SampleTest.java
index 347d7ed38..f8d2cff66 100644
--- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/SampleTest.java
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/SampleTest.java
@@ -10,22 +10,17 @@
package org.eclipse.tcf.debug.test;
import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import org.eclipse.debug.internal.ui.viewers.model.provisional.VirtualItem;
-import org.eclipse.tcf.debug.test.services.IWaitForEventCache;
-import org.eclipse.tcf.debug.test.services.RunControlCM;
import org.eclipse.tcf.debug.test.services.RunControlCM.ContextState;
import org.eclipse.tcf.debug.test.util.ICache;
import org.eclipse.tcf.debug.test.util.RangeCache;
import org.eclipse.tcf.debug.test.util.Transaction;
import org.eclipse.tcf.services.ILineNumbers.CodeArea;
import org.eclipse.tcf.services.IRunControl;
-import org.eclipse.tcf.services.IRunControl.RunControlContext;
import org.eclipse.tcf.services.IStackTrace.StackTraceContext;
import org.eclipse.tcf.services.ISymbols;
import org.eclipse.tcf.services.ISymbols.Symbol;
@@ -362,156 +357,4 @@ public class SampleTest extends AbstractTcfUITest {
}
}.get();
}
-
- public void testStackTraceCMResetOnContextStateChange() throws Exception {
- final TestProcessInfo processInfo = initProcessModel("tcf_test_func2");
-
- // Retrieve the current PC and top frame for use later
- final String pc = new Transaction<String>() {
- @Override
- protected String process() throws InvalidCacheException, ExecutionException {
- return validate(fRunControlCM.getState(processInfo.fThreadId)).pc;
- }
- }.get();
-
- // Retrieve data from caches (make them valid).
- new Transaction<Object>() {
- @Override
- protected String process() throws InvalidCacheException, ExecutionException {
- String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
- validate (fStackTraceCM.getContexts(frameIds));
- RangeCache<StackTraceContext> framesRange = fStackTraceCM.getContextRange(processInfo.fThreadId);
- validate( framesRange.getRange(0, frameIds.length) );
- return null;
- }
- }.get();
-
-
- // Execute a step.
- resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_OUT);
-
- // End test, check that all caches were reset and now return an error.
- new Transaction<Object>() {
- @Override
- protected Object process() throws InvalidCacheException, ExecutionException {
- ICache<String[]> frameIdsCache = fStackTraceCM.getChildren(processInfo.fThreadId);
- Assert.assertFalse("Expected cache to be reset", frameIdsCache.isValid());
- return null;
- }
- }.get();
-
- new Transaction<Object>() {
- @Override
- protected Object process() throws InvalidCacheException, ExecutionException {
- String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
- ICache<StackTraceContext[]> cache = fStackTraceCM.getContexts(frameIds);
- Assert.assertFalse("Expected cache to be reset", cache.isValid());
-
- RangeCache<StackTraceContext> framesRange = fStackTraceCM.getContextRange(processInfo.fThreadId);
- ICache<List<StackTraceContext>> framesRangeCache = framesRange.getRange(0, frameIds.length);
- Assert.assertFalse("Expected cache to be reset", framesRangeCache.isValid());
-
- return null;
- }
- }.get();
- }
-
- public void testRunControlCMChildrenInvalidation() throws Exception {
- final TestProcessInfo processInfo = initProcessModel("tcf_test_func0");
-
- createBreakpoint("testRunControlCMChildrenInvalidation", "tcf_test_func0");
-
- // Wait for each threads to start.
- final String[] threads = new Transaction<String[]>() {
- List<String> fThreads = new ArrayList<String>();
- @Override
- protected String[] process() throws InvalidCacheException, ExecutionException {
- IWaitForEventCache<RunControlContext[]> waitCache = fRunControlCM.waitForContextAdded(processInfo.fProcessId, this);
- validate(fRunControlCM.resume(processInfo.fTestCtx, this, IRunControl.RM_RESUME, 1));
- RunControlContext[] addedContexts = validate(waitCache);
- for (RunControlContext addedContext : addedContexts) {
- fThreads.add(addedContext.getID());
- }
- if (fThreads.size() < 4) {
- waitCache.reset();
- validate(waitCache);
- }
- // Validate children cache
- String[] children = validate (fRunControlCM.getChildren(processInfo.fProcessId));
- Assert.assertTrue(
- "Expected children array to contain added ids",
- Arrays.asList(children).containsAll(fThreads));
-
- return fThreads.toArray(new String[fThreads.size()]);
- }
- }.get();
-
- // Wait for each thread to suspend, update caches
- for (final String thread : threads) {
- new Transaction<Object>() {
- @Override
- protected Object process() throws InvalidCacheException, ExecutionException {
- RunControlCM.ContextState state = validate(fRunControlCM.getState(thread));
- if (!state.suspended) {
- validate( fRunControlCM.waitForContextSuspended(thread, this) );
- }
- String symId = validate( fSymbolsCM.find(thread, new BigInteger(state.pc), "tcf_test_func0") );
- Number symAddr = validate( fSymbolsCM.getContext(symId) ).getAddress();
- Assert.assertEquals("Expected thread to suspend at breakpoint address", symAddr.toString(), state.pc);
- String[] children = validate( fRunControlCM.getChildren(thread));
- Assert.assertEquals("Expected thread to have no children contexts", 0, children.length);
- return null;
- }
- }.get();
- }
-
- // End test, check for removed events and that state caches were cleared
- new Transaction<String>() {
- @Override
- protected String process() throws InvalidCacheException, ExecutionException {
- // Create wait caches
- fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this);
- IWaitForEventCache<?>[] waitCaches = new IWaitForEventCache<?>[threads.length];
- for (int i = 0; i < threads.length; i++) {
- waitCaches[i] = fRunControlCM.waitForContextRemoved(threads[i], this);
- }
- validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) );
- validate(waitCaches);
- validate(fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this));
-
- try {
- validate( fRunControlCM.getContext(processInfo.fProcessId) );
- Assert.fail("Expected error");
- } catch (ExecutionException e) {}
- try {
- validate( fRunControlCM.getState(processInfo.fProcessId) );
- Assert.fail("Expected error");
- } catch (ExecutionException e) {}
- try {
- String children[] = validate( fRunControlCM.getChildren(processInfo.fProcessId) );
- Assert.assertEquals("Expected no children", 0, children.length);
- } catch (ExecutionException e) {}
-
- for (String thread : threads) {
- try {
- validate( fRunControlCM.getContext(thread) );
- Assert.fail("Expected error");
- } catch (ExecutionException e) {}
- try {
- validate( fRunControlCM.getState(thread) );
- Assert.fail("Expected error");
- } catch (ExecutionException e) {}
- try {
- String children[] = validate( fRunControlCM.getChildren(processInfo.fProcessId) );
- Assert.assertEquals("Expected no children", 0, children.length);
- } catch (ExecutionException e) {}
- }
-
- return null;
- }
- }.get();
-
- removeBreakpoint("testRunControlCMChildrenInvalidation");
-
- }
}
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/StackTraceCMTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/StackTraceCMTest.java
new file mode 100644
index 000000000..7d1ed61f4
--- /dev/null
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/StackTraceCMTest.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.tcf.debug.test.util.ICache;
+import org.eclipse.tcf.debug.test.util.RangeCache;
+import org.eclipse.tcf.debug.test.util.Transaction;
+import org.eclipse.tcf.services.IRunControl;
+import org.eclipse.tcf.services.IStackTrace.StackTraceContext;
+import org.junit.Assert;
+
+public class StackTraceCMTest extends AbstractCMTest {
+
+ public void testStackTraceCMResetOnContextStateChange() throws Exception {
+ final TestProcessInfo processInfo = startProcess("tcf_test_func2");
+
+ // Retrieve the current PC and top frame for use later
+ final String pc = new Transaction<String>() {
+ @Override
+ protected String process() throws InvalidCacheException, ExecutionException {
+ return validate(fRunControlCM.getState(processInfo.fThreadId)).pc;
+
+ }
+ }.get();
+
+ // Retrieve data from caches (make them valid).
+ new Transaction<Object>() {
+ @Override
+ protected String process() throws InvalidCacheException, ExecutionException {
+ String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
+ validate (fStackTraceCM.getContexts(frameIds));
+ RangeCache<StackTraceContext> framesRange = fStackTraceCM.getContextRange(processInfo.fThreadId);
+ List<StackTraceContext> frames = validate( framesRange.getRange(0, frameIds.length) );
+ StackTraceContext topFrame = frames.get(frames.size() - 1);
+ Assert.assertTrue("Expected PC to match", pc.equals(topFrame.getInstructionAddress().toString()));
+ return null;
+ }
+ }.get();
+
+
+ // Execute a step.
+ resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_OUT);
+
+ // End test, check that all caches were reset and now return an error.
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ ICache<String[]> frameIdsCache = fStackTraceCM.getChildren(processInfo.fThreadId);
+ Assert.assertFalse("Expected cache to be reset", frameIdsCache.isValid());
+ return null;
+ }
+ }.get();
+
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
+ ICache<StackTraceContext[]> cache = fStackTraceCM.getContexts(frameIds);
+ Assert.assertFalse("Expected cache to be reset", cache.isValid());
+
+ RangeCache<StackTraceContext> framesRange = fStackTraceCM.getContextRange(processInfo.fThreadId);
+ ICache<List<StackTraceContext>> framesRangeCache = framesRange.getRange(0, frameIds.length);
+ Assert.assertFalse("Expected cache to be reset", framesRangeCache.isValid());
+
+ return null;
+ }
+ }.get();
+
+ new Transaction<Object>() {
+ @Override
+ protected Object process() throws InvalidCacheException, ExecutionException {
+ String[] frameIds = validate( fStackTraceCM.getChildren(processInfo.fThreadId) );
+
+ RangeCache<StackTraceContext> framesRange = fStackTraceCM.getContextRange(processInfo.fThreadId);
+ List<StackTraceContext> frames = validate(framesRange.getRange(frameIds.length - 1, 1));
+ StackTraceContext topFrame = frames.get(0);
+
+ Assert.assertFalse("Expected PC to be updated", pc.equals(topFrame.getInstructionAddress().toString()));
+ return null;
+ }
+ }.get();
+ }
+}
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/RunControlCM.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/RunControlCM.java
index 758a68e68..db8546769 100644
--- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/RunControlCM.java
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/RunControlCM.java
@@ -132,29 +132,6 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
}
- protected abstract static class ContextKey<V> extends Key<V> {
- RunControlContext fContext;
-
- ContextKey(Class<V> cacheClass, RunControlContext context) {
- super(cacheClass);
- fContext = context;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (super.equals(obj) && obj instanceof ContextKey<?>) {
- return ((ContextKey<?>)obj).fContext.equals(fContext);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return super.hashCode() + fContext.hashCode();
- }
- }
-
-
private class ContextStateCache extends CallbackCache<ContextState> implements IResettable {
private class InnerContextStateCache extends TokenCache<ContextState> implements IRunControl.DoneGetState {
@@ -231,11 +208,11 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
return mapCache(new ContextStateKey(id));
}
- protected abstract static class ContextCommandKey<V> extends ContextKey<V> {
+ protected abstract static class ContextCommandKey<V> extends IdKey<V> {
Object fClientKey;
- ContextCommandKey(Class<V> cacheClass, RunControlContext context, Object clientKey) {
- super(cacheClass, context);
+ ContextCommandKey(Class<V> cacheClass, String contextId, Object clientKey) {
+ super(cacheClass, contextId);
fClientKey = clientKey;
}
@@ -266,7 +243,7 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
return context.suspend(this);
}
}
- return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context, clientKey) {
+ return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context.getID(), clientKey) {
@Override MyCache createCache() { return new MyCache(); }
});
}
@@ -280,7 +257,7 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
return context.resume(mode, count, this);
}
}
- return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context, clientKey) {
+ return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context.getID(), clientKey) {
@Override MyCache createCache() { return new MyCache(); }
});
}
@@ -294,7 +271,7 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
return context.resume(mode, count, params, this);
}
}
- return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context, clientKey) {
+ return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context.getID(), clientKey) {
@Override MyCache createCache() { return new MyCache(); }
});
}
@@ -306,7 +283,7 @@ public class RunControlCM extends AbstractCacheManager implements RunControlList
return context.terminate(this);
}
}
- return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context, clientKey) {
+ return mapCache( new ContextCommandKey<MyCache>(MyCache.class, context.getID(), clientKey) {
@Override MyCache createCache() { return new MyCache(); }
});
diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/StackTraceCM.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/StackTraceCM.java
index 6d49f6671..6cd144c89 100644
--- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/StackTraceCM.java
+++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/StackTraceCM.java
@@ -100,8 +100,7 @@ public class StackTraceCM extends AbstractCacheManager implements IRunControl.Ru
return mapCache(new IdKey<MyCache>(MyCache.class, parentId) {
@Override MyCache createCache() { return new MyCache(); }
- });
-
+ });
}
public ICache<StackTraceContext[]> getContexts(final String[] ids) {

Back to the top