diff options
author | Pawel Piech | 2012-06-25 23:17:52 +0000 |
---|---|---|
committer | Pawel Piech | 2012-07-25 23:51:26 +0000 |
commit | fbc0c803672ebcf2ddcb44805bc0c1a8fa9d6ab7 (patch) | |
tree | 098da09adb75fa2af511e8ed498e3cb6330e0a13 /tests | |
parent | 1e3b243e20a842fafab7884555df73f14518797a (diff) | |
download | org.eclipse.tcf-fbc0c803672ebcf2ddcb44805bc0c1a8fa9d6ab7.tar.gz org.eclipse.tcf-fbc0c803672ebcf2ddcb44805bc0c1a8fa9d6ab7.tar.xz org.eclipse.tcf-fbc0c803672ebcf2ddcb44805bc0c1a8fa9d6ab7.zip |
Debug Tests - Refactored symbols and stack trace cache managers.
Diffstat (limited to 'tests')
17 files changed, 464 insertions, 997 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 index 811d7bff6..57417d694 100644 --- 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 @@ -67,6 +67,7 @@ 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.IMemory; import org.eclipse.tcf.services.IMemoryMap; import org.eclipse.tcf.services.IProcesses; import org.eclipse.tcf.services.IRegisters; @@ -101,7 +102,8 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat protected ISymbols syms; protected IStackTrace stk; protected IRunControl rc; - protected IBreakpoints bp; + protected IBreakpoints bp; + protected IMemory fMemory; protected IMemoryMap fMemoryMap; protected ILineNumbers fLineNumbers; protected IRegisters fRegisters; @@ -145,10 +147,11 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat @Override protected void setUp() throws Exception { + super.setUp(); + fTestRunKey = new Object(); // Launch the agent - super.setUp(); createLaunch(); channels = new IChannel[NUM_CHANNELS]; @@ -219,7 +222,7 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat fRunControlCM = new RunControlCM(rc); fDiagnosticsCM = new DiagnosticsCM(diag); fBreakpointsCM = new BreakpointsCM(bp); - fStackTraceCM = new StackTraceCM(stk, rc); + fStackTraceCM = new StackTraceCM(stk, fRunControlCM, fMemory, fMemoryMap); fSymbolsCM = new SymbolsCM(syms, fRunControlCM, fMemoryMap); fLineNumbersCM = new LineNumbersCM(fLineNumbers, fMemoryMap, fRunControlCM); fRegistersCM = new RegistersCM(fRegisters, rc); @@ -292,7 +295,8 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat stk = channels[0].getRemoteService(IStackTrace.class); rc = channels[0].getRemoteService(IRunControl.class); bp = channels[0].getRemoteService(IBreakpoints.class); - fMemoryMap = channels[0].getRemoteService(IMemoryMap.class); + fMemory = channels[0].getRemoteService(IMemory.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); @@ -468,7 +472,7 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat }.get(); } - private TestProcessInfo startProcess() throws InterruptedException, ExecutionException { + protected TestProcessInfo startProcess() throws InterruptedException, ExecutionException { return new Transaction<TestProcessInfo>() { @Override protected TestProcessInfo process() throws Transaction.InvalidCacheException ,ExecutionException { @@ -494,7 +498,7 @@ public abstract class AbstractCMTest extends TcfTestCase implements IViewerUpdat }.get(); } - private boolean runToTestEntry(final TestProcessInfo processInfo, final String testFunc) throws InterruptedException, ExecutionException { + protected boolean runToTestEntry(final TestProcessInfo processInfo, final String testFunc) throws InterruptedException, ExecutionException { return new Transaction<Boolean>() { Object fWaitForResumeKey; Object fWaitForSuspendKey; 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 b0e924a53..5f8ee7e4f 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 @@ -9,34 +9,10 @@ *******************************************************************************/ 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 java.util.regex.Pattern; -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.internal.ui.elements.adapters.DefaultBreakpointsViewInput; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; @@ -53,44 +29,10 @@ import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; -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.debug.ui.ITCFObject; -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; @@ -98,15 +40,7 @@ import org.osgi.framework.Bundle; * Base test for validating TCF Debugger UI. */ @SuppressWarnings("restriction") -public abstract class AbstractTcfUITest 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; +public abstract class AbstractTcfUITest extends AbstractCMTest implements IViewerUpdatesListenerConstants { protected VirtualTreeModelViewer fDebugViewViewer; protected TestDebugContextProvider fDebugContextProvider; @@ -120,29 +54,6 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp protected TestSourceDisplayService fSourceDisplayService; protected SourceDisplayListener fSourceDisplayListener; - 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() */ @@ -171,101 +82,16 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp @Override protected void setUp() throws Exception { - fTestRunKey = new Object(); - - // Launch the agent super.setUp(); - createDebugViewViewer(); - 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(); disposeDebugViewViewer(); - - 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 createDebugViewViewer() { final Display display = Display.getDefault(); display.syncExec(new Runnable() { @@ -314,324 +140,6 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp } - 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(); - fDebugViewListener.reset(); - fDebugViewListener.setDelayContentUntilProxyInstall(true); - fLaunch = lcWc.launch("debug", new NullProgressMonitor()); - Assert.assertTrue( fLaunch instanceof IDisconnect ); - - // The launch element may or may not have been populated into the viewer. It's label - // also may or may not have been updated. Check viewer item for launch, then wait if needed. - TreePath launchPath = new TreePath(new Object[] { fLaunch }); - fDebugViewListener.addLabelUpdate(launchPath); - VirtualItem launchItem = fDebugViewViewer.findItem(launchPath); - fDebugViewListener.findElement(new Pattern[] { Pattern.compile(".*" + fLaunch.getLaunchConfiguration().getName() + ".*") } ); - if (launchItem == null || launchItem.getData() == null || launchItem.getData(VirtualItem.LABEL_KEY) == null) { - fDebugViewListener.waitTillFinished(MODEL_CHANGED_COMPLETE | MODEL_PROXIES_INSTALLED | CONTENT_SEQUENCE_COMPLETE | LABEL_UPDATES); - launchItem = fDebugViewViewer.findItem(launchPath); - } - - Assert.assertTrue( launchItem != null ); - String[] launchItemLabel = (String[])launchItem.getData(VirtualItem.LABEL_KEY); - Assert.assertTrue( launchItemLabel[0].contains(fLaunch.getLaunchConfiguration().getName()) ); - Assert.assertEquals(fLaunch, launchItem.getData()); - } - - 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 initProcessModel(String testFunc) throws Exception { String bpId = "entryPointBreakpoint"; createBreakpoint(bpId, testFunc); @@ -685,134 +193,4 @@ public abstract class AbstractTcfUITest extends TcfTestCase implements IViewerUp 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/CacheTests.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/CacheTests.java index 0f70c24c1..51679e428 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/CacheTests.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/CacheTests.java @@ -53,7 +53,7 @@ public class CacheTests extends TestCase { class TestQuery extends Query<Integer> { @Override protected void execute(final DataCallback<Integer> rm) { - fTestCache.update(new DataCallback<Integer>(rm) { + fTestCache.wait(new DataCallback<Integer>(rm) { @Override protected void handleSuccess() { rm.setData(fTestCache.getData()); @@ -521,7 +521,7 @@ public class CacheTests extends TestCase { @Override protected void execute(final DataCallback<Integer> rm) { - fTestCache.update(new Callback(rm) { + fTestCache.wait(new Callback(rm) { @Override public synchronized void addCancelListener(ICanceledListener listener) { // Do not add the cancel listener so that the cancel request is not @@ -617,7 +617,7 @@ public class CacheTests extends TestCase { }; }; - fTestCache.update(rmBad[0]); + fTestCache.wait(rmBad[0]); } }; qBad.invoke(); diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/LineNumbersCMTest.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/LineNumbersCMTest.java new file mode 100644 index 000000000..5cbf96066 --- /dev/null +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/LineNumbersCMTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * 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.concurrent.ExecutionException; + +import org.eclipse.tcf.debug.test.util.Transaction; +import org.eclipse.tcf.services.ILineNumbers.CodeArea; +import org.junit.Assert; + +public class LineNumbersCMTest extends AbstractCMTest { + + public void testLineNumbersCMResetOnContextRemove() throws Exception { + final TestProcessInfo processInfo = startProcess("tcf_test_func0"); + + // Retrieve the current PC for use later + final String pc = new Transaction<String>() { + @Override + protected String process() throws InvalidCacheException, ExecutionException { + return validate(fRunControlCM.getState(processInfo.fThreadId)).pc; + } + }.get(); + + final BigInteger pcNumber = new BigInteger(pc); + final BigInteger pcNumberPlusOne = pcNumber.add(BigInteger.valueOf(1)); + + // Retrieve the line number for current PC. + final CodeArea[] pcCodeAreas = new Transaction<CodeArea[]>() { + @Override + protected CodeArea[] process() throws InvalidCacheException, ExecutionException { + CodeArea[] areas = validate(fLineNumbersCM.mapToSource(processInfo.fProcessId, pcNumber, pcNumberPlusOne)); + Assert.assertNotNull(areas); + Assert.assertTrue(areas.length != 0); + + areas = validate(fLineNumbersCM.mapToSource(processInfo.fThreadId, pcNumber, pcNumberPlusOne)); + Assert.assertNotNull(areas); + Assert.assertTrue(areas.length != 0); + + CodeArea[] areas2 = validate(fLineNumbersCM.mapToMemory(processInfo.fProcessId, areas[0].file, areas[0].start_line, areas[0].start_column)); + Assert.assertNotNull(areas2); + Assert.assertTrue(areas2.length != 0); + + areas2 = validate(fLineNumbersCM.mapToMemory(processInfo.fThreadId, areas[0].file, areas[0].start_line, areas[0].start_column)); + Assert.assertNotNull(areas2); + Assert.assertTrue(areas2.length != 0); + + return areas; + } + }.get(); + + // End test, check that all caches were reset and now return an error. + new Transaction<String>() { + @Override + protected String process() throws InvalidCacheException, ExecutionException { + validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) ); + validate( fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this) ); + try { + validate(fLineNumbersCM.mapToSource(processInfo.fProcessId, pcNumber, pcNumberPlusOne)); + Assert.fail("Expected error"); + } catch (ExecutionException e) {} + try { + validate(fLineNumbersCM.mapToSource(processInfo.fThreadId, pcNumber, pcNumberPlusOne)); + Assert.fail("Expected error"); + } catch (ExecutionException e) {} + try { + CodeArea[] areas3 = validate(fLineNumbersCM.mapToMemory(processInfo.fProcessId, pcCodeAreas[0].file, pcCodeAreas[0].start_line, pcCodeAreas[0].start_column)); + Assert.fail("Expected error"); + } catch (ExecutionException e) {} + try { + validate(fLineNumbersCM.mapToMemory(processInfo.fThreadId, pcCodeAreas[0].file, pcCodeAreas[0].start_line, pcCodeAreas[0].start_column)); + Assert.fail("Expected error"); + } catch (ExecutionException e) {} + + return null; + } + }.get(); + } + +} diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RangeCacheTests.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RangeCacheTests.java index 413df7e0b..ea9bdc54b 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RangeCacheTests.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/RangeCacheTests.java @@ -62,7 +62,7 @@ public class RangeCacheTests extends TestCase { rm.setError(fRangeCache.getError()); rm.done(); } else { - fRangeCache.update(new Callback(rm) { + fRangeCache.wait(new Callback(rm) { @Override protected void handleSuccess() { rm.setData(fRangeCache.getData()); 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 index 220a412fd..3df5c098a 100644 --- 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 @@ -97,7 +97,7 @@ public class RunControlCMTest extends AbstractCMTest { } }.get(); } - + public void testRunControlCMChildrenInvalidation() throws Exception { final TestProcessInfo processInfo = startProcess("tcf_test_func0"); 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 f8d2cff66..4f825740c 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 @@ -231,72 +231,6 @@ public class SampleTest extends AbstractTcfUITest { }.get(); } - public void testLineNumbersCMResetOnContextRemove() throws Exception { - final TestProcessInfo processInfo = initProcessModel("tcf_test_func0"); - - // Retrieve the current PC for use later - final String pc = new Transaction<String>() { - @Override - protected String process() throws InvalidCacheException, ExecutionException { - return validate(fRunControlCM.getState(processInfo.fThreadId)).pc; - } - }.get(); - - final BigInteger pcNumber = new BigInteger(pc); - final BigInteger pcNumberPlusOne = pcNumber.add(BigInteger.valueOf(1)); - - // Retrieve the line number for current PC. - final CodeArea[] pcCodeAreas = new Transaction<CodeArea[]>() { - @Override - protected CodeArea[] process() throws InvalidCacheException, ExecutionException { - CodeArea[] areas = validate(fLineNumbersCM.mapToSource(processInfo.fProcessId, pcNumber, pcNumberPlusOne)); - Assert.assertNotNull(areas); - Assert.assertTrue(areas.length != 0); - - areas = validate(fLineNumbersCM.mapToSource(processInfo.fThreadId, pcNumber, pcNumberPlusOne)); - Assert.assertNotNull(areas); - Assert.assertTrue(areas.length != 0); - - CodeArea[] areas2 = validate(fLineNumbersCM.mapToMemory(processInfo.fProcessId, areas[0].file, areas[0].start_line, areas[0].start_column)); - Assert.assertNotNull(areas2); - Assert.assertTrue(areas2.length != 0); - - areas2 = validate(fLineNumbersCM.mapToMemory(processInfo.fThreadId, areas[0].file, areas[0].start_line, areas[0].start_column)); - Assert.assertNotNull(areas2); - Assert.assertTrue(areas2.length != 0); - - return areas; - } - }.get(); - - // End test, check that all caches were reset and now return an error. - new Transaction<String>() { - @Override - protected String process() throws InvalidCacheException, ExecutionException { - validate( fDiagnosticsCM.cancelTest(processInfo.fTestId, this) ); - validate( fRunControlCM.waitForContextRemoved(processInfo.fProcessId, this) ); - try { - validate(fLineNumbersCM.mapToSource(processInfo.fProcessId, pcNumber, pcNumberPlusOne)); - Assert.fail("Expected error"); - } catch (ExecutionException e) {} - try { - validate(fLineNumbersCM.mapToSource(processInfo.fThreadId, pcNumber, pcNumberPlusOne)); - Assert.fail("Expected error"); - } catch (ExecutionException e) {} - try { - CodeArea[] areas3 = validate(fLineNumbersCM.mapToMemory(processInfo.fProcessId, pcCodeAreas[0].file, pcCodeAreas[0].start_line, pcCodeAreas[0].start_column)); - Assert.fail("Expected error"); - } catch (ExecutionException e) {} - try { - validate(fLineNumbersCM.mapToMemory(processInfo.fThreadId, pcCodeAreas[0].file, pcCodeAreas[0].start_line, pcCodeAreas[0].start_column)); - Assert.fail("Expected error"); - } catch (ExecutionException e) {} - - return null; - } - }.get(); - } - public void testSymbolsCMResetOnContextStateChange() throws Exception { final TestProcessInfo processInfo = initProcessModel("tcf_test_func2"); 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 index 7d1ed61f4..d17a24cdf 100644 --- 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 @@ -10,20 +10,88 @@ package org.eclipse.tcf.debug.test; import java.util.List; +import java.util.concurrent.Callable; 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.protocol.Protocol; import org.eclipse.tcf.services.IRunControl; +import org.eclipse.tcf.services.IRunControl.RunControlContext; import org.eclipse.tcf.services.IStackTrace.StackTraceContext; import org.junit.Assert; public class StackTraceCMTest extends AbstractCMTest { - public void testStackTraceCMResetOnContextStateChange() throws Exception { + public void testStackTraceCMResetOnResumeSuspend() throws Exception { final TestProcessInfo processInfo = startProcess("tcf_test_func2"); + doTestStackTraceCMReset( + processInfo, + new Callable<Object>() { + public Object call() throws Exception { + resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_OUT); + return null; + } + }, + true); + } + + public void testStackTraceCMResetOnContextChange() throws Exception { + final TestProcessInfo processInfo = startProcess("tcf_test_func2"); + doTestStackTraceCMReset( + processInfo, + new Callable<Object>() { + public Object call() throws Exception { + Protocol.invokeAndWait(new Runnable() { + public void run() { + fStackTraceCM.fRunControlListener.contextChanged(new RunControlContext[] { processInfo.fThreadCtx }); + } + }); + return null; + } + }, + false); + } + + public void testStackTraceCMResetOnMemoryChange() throws Exception { + final TestProcessInfo processInfo = startProcess("tcf_test_func2"); + doTestStackTraceCMReset( + processInfo, + new Callable<Object>() { + public Object call() throws Exception { + Protocol.invokeAndWait(new Runnable() { + public void run() { + fStackTraceCM.fMemoryListener.memoryChanged(processInfo.fProcessId, new Number[0], new long[0]); + } + }); + return null; + } + }, + false); + } + + public void testStackTraceCMResetOnMemoryMapChange() throws Exception { + final TestProcessInfo processInfo = startProcess("tcf_test_func2"); + doTestStackTraceCMReset( + processInfo, + new Callable<Object>() { + public Object call() throws Exception { + Protocol.invokeAndWait(new Runnable() { + public void run() { + fStackTraceCM.fMemoryMapListener.changed(processInfo.fProcessId); + } + }); + return null; + } + }, + false); + } + + private void doTestStackTraceCMReset(final TestProcessInfo processInfo, Callable<?> resetCallable, + final boolean pcShouldChange) throws Exception + { // Retrieve the current PC and top frame for use later final String pc = new Transaction<String>() { @Override @@ -47,9 +115,8 @@ public class StackTraceCMTest extends AbstractCMTest { } }.get(); - - // Execute a step. - resumeAndWaitForSuspend(processInfo.fThreadCtx, IRunControl.RM_STEP_OUT); + // Call the runnable that should reset the stack caches' state. + resetCallable.call(); // End test, check that all caches were reset and now return an error. new Transaction<Object>() { @@ -83,11 +150,13 @@ public class StackTraceCMTest extends AbstractCMTest { 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())); + if (pcShouldChange) { + 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/LineNumbersCM.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/LineNumbersCM.java index 23f513343..89c1a3f8f 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/LineNumbersCM.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/LineNumbersCM.java @@ -49,15 +49,6 @@ public class LineNumbersCM extends AbstractCacheManager { super.dispose(); } - private abstract class LineNumbersTokenCache<V> extends TokenCache<V> { - abstract protected String getId(); - - protected void set(IToken token, V data, Throwable error) { - fMemContextResetMap.addValid(getId(), this); - super.set(token, data, error); - } - } - abstract private class MapToSourceKey<V> extends IdKey<V> { private final Number fStartAdddress; private final Number fEndAddress; @@ -84,15 +75,14 @@ public class LineNumbersCM extends AbstractCacheManager { public ICache<CodeArea[]> mapToSource(final String context_id, final Number start_address, final Number end_address) { class MyCache extends TransactionCache<ILineNumbers.CodeArea[]> { - private String fId = context_id; - + @Override protected CodeArea[] process() throws InvalidCacheException, ExecutionException { - RunControlContext rcContext = validate(fRunControlCM.getContext(fId)); + RunControlContext rcContext = validate(fRunControlCM.getContext(context_id)); String mem_id = rcContext.getProcessID(); if (mem_id == null) { // TODO: is this the correct fall-back. Should we save the parent ID for reset? - mem_id = fId; + mem_id = context_id; } return validate( doMapToSource(mem_id, start_address, end_address) ); } @@ -104,26 +94,21 @@ public class LineNumbersCM extends AbstractCacheManager { } private ICache<CodeArea[]> doMapToSource(final String mem_id, final Number start_address, final Number end_address) { - class MyCache extends LineNumbersTokenCache<CodeArea[]> implements ILineNumbers.DoneMapToSource { - @Override - protected String getId() { - return mem_id; - } + class MyCache extends TokenCache<CodeArea[]> implements ILineNumbers.DoneMapToSource { @Override protected IToken retrieveToken() { return fService.mapToSource(mem_id, start_address, end_address, this); } public void doneMapToSource(IToken token, Exception error, CodeArea[] areas) { + fMemContextResetMap.addValid(mem_id, this); set(token, areas, error); } - }; return mapCache(new MapToSourceKey<MyCache>(MyCache.class, mem_id, start_address, end_address) { @Override MyCache createCache() { return new MyCache(); } }); - } abstract private class MapToMemoryKey<V> extends IdKey<V> { @@ -173,16 +158,13 @@ public class LineNumbersCM extends AbstractCacheManager { } private ICache<CodeArea[]> doMapToMemory(final String mem_id, final String file, final int line, final int column) { - class MyCache extends LineNumbersTokenCache<CodeArea[]> implements ILineNumbers.DoneMapToMemory { - @Override - protected String getId() { - return mem_id; - } + class MyCache extends TokenCache<CodeArea[]> implements ILineNumbers.DoneMapToMemory { @Override protected IToken retrieveToken() { return fService.mapToMemory(mem_id, file, line, column, this); } public void doneMapToMemory(IToken token, Exception error, CodeArea[] areas) { + fMemContextResetMap.addValid(mem_id, this); set(token, areas, error); } diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/ResetMap.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/ResetMap.java index 49d8f0ea1..af2cfc8bd 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/ResetMap.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/ResetMap.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -40,7 +41,8 @@ public class ResetMap { // Mapping of context IDs that were reset while a given cache was pending. private Map<IResettable, Set<String>> fPending = new LinkedHashMap<IResettable, Set<String>>(); - public synchronized Set<String> removePending(IResettable cache) { + public Set<String> removePending(IResettable cache) { + assert Protocol.isDispatchThread(); Set<String> pendingIds = fPending.remove(cache); if (pendingIds == null) { pendingIds = Collections.emptySet(); @@ -48,23 +50,37 @@ public class ResetMap { return pendingIds; } - public synchronized void addValid(String id, IResettable cache) { - assert !fPending.containsKey(cache); + public boolean clearPending(String id, IResettable cache) { + assert Protocol.isDispatchThread(); + Set<String> pendingIds = fPending.remove(cache); + if (pendingIds != null && pendingIds.contains(id)) { + cache.reset(); + return true; + } + return false; + } + + public void addValid(String id, IResettable cache) { + assert Protocol.isDispatchThread(); + + if (clearPending(id, cache)) return; List<IResettable> list = fValid.get(id); if (list == null) { - list = new ArrayList<IResettable>(); + list = new LinkedList<IResettable>(); fValid.put(id, list); } list.add(cache); } - public synchronized void addValid(String id, String[] childrenIds, IResettable cache) { - assert !fPending.containsKey(cache); + public void addValid(String id, String[] childrenIds, IResettable cache) { + assert Protocol.isDispatchThread(); + + if (!clearPending(id, cache)) return; List<IResettable> list = fValid.get(id); if (list == null) { - list = new ArrayList<IResettable>(); + list = new LinkedList<IResettable>(); fValid.put(id, list); } list.add(cache); @@ -73,9 +89,15 @@ public class ResetMap { } } - public synchronized void addValid(List<String> ids, IResettable cache) { - assert !fPending.containsKey(cache); + public void addValid(List<String> ids, IResettable cache) { + assert Protocol.isDispatchThread(); + boolean valid = true; + for (int i = 0; i < ids.size() - 1; i++) { + valid = clearPending(ids.get(i), cache) && valid; + } + if (!valid) return; + String id = ids.get(0); List<IResettable> list = fValid.get(id); if (list == null) { @@ -94,7 +116,9 @@ public class ResetMap { } } - public synchronized List<IResettable> getCaches(String id) { + public List<IResettable> getCaches(String id) { + assert Protocol.isDispatchThread(); + List<IResettable> list = fValid.get(id); if (list == null) { list = Collections.emptyList(); @@ -157,7 +181,8 @@ public class ResetMap { } } - public synchronized void resetAll() { + public void resetAll() { + assert Protocol.isDispatchThread(); Collection<List<IResettable>> valid = null; synchronized (this) { valid = fValid.values(); @@ -168,7 +193,10 @@ public class ResetMap { } } - public synchronized void addPending(IResettable cache) { - fPending.put(cache, new TreeSet<String>()); + public void addPending(IResettable cache) { + assert Protocol.isDispatchThread(); + if (!fPending.containsKey(cache)) { + fPending.put(cache, new TreeSet<String>()); + } } } 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 6cd144c89..f6cb8f283 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 @@ -22,7 +22,11 @@ import org.eclipse.tcf.debug.test.util.ICache; import org.eclipse.tcf.debug.test.util.RangeCache; import org.eclipse.tcf.debug.test.util.TokenCache; import org.eclipse.tcf.debug.test.util.Transaction; +import org.eclipse.tcf.debug.test.util.TransactionCache; import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.services.IMemory; +import org.eclipse.tcf.services.IMemory.MemoryContext; +import org.eclipse.tcf.services.IMemoryMap; import org.eclipse.tcf.services.IRunControl; import org.eclipse.tcf.services.IRunControl.RunControlContext; import org.eclipse.tcf.services.IStackTrace; @@ -31,33 +35,133 @@ import org.eclipse.tcf.services.IStackTrace.StackTraceContext; /** * */ -public class StackTraceCM extends AbstractCacheManager implements IRunControl.RunControlListener { +public class StackTraceCM extends AbstractCacheManager { private IStackTrace fService; - private IRunControl fRunControl; + private RunControlCM fRunControlCM; + private IMemory fMemory; + private IMemoryMap fMemoryMap; private final ResetMap fRunControlStateResetMap = new ResetMap(); + private final ResetMap fMemoryResetMap = new ResetMap(); - public StackTraceCM(IStackTrace service, IRunControl runControl) { + /** + * Listener public for testing purposes only. + */ + public final IRunControl.RunControlListener fRunControlListener = new IRunControl.RunControlListener() { + @Override + public void contextAdded(RunControlContext[] contexts) { + } + + @Override + public void contextChanged(RunControlContext[] contexts) { + for (RunControlContext context : contexts) fRunControlStateResetMap.reset(context.getID()); + } + + @Override + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) fRunControlStateResetMap.reset(id); + } + + @Override + public void contextSuspended(String context, String pc, String reason, Map<String, Object> params) { + fRunControlStateResetMap.reset(context); + } + + @Override + public void contextResumed(String context) { + fRunControlStateResetMap.reset(context); + } + + @Override + public void containerSuspended(String context, String pc, String reason, Map<String, Object> params, + String[] suspended_ids) + { + for (String id : suspended_ids) fRunControlStateResetMap.reset(id); + } + + @Override + public void containerResumed(String[] context_ids) { + for (String id : context_ids) fRunControlStateResetMap.reset(id); + } + + @Override + public void contextException(String context, String msg) { + fRunControlStateResetMap.reset(context); + } + }; + + public final IMemory.MemoryListener fMemoryListener = new IMemory.MemoryListener() { + + @Override + public void contextAdded(MemoryContext[] contexts) { + } + + @Override + public void contextChanged(MemoryContext[] contexts) { + for (MemoryContext context : contexts) fMemoryResetMap.reset(context.getID()); + } + + public void contextRemoved(String[] context_ids) { + for (String context_id : context_ids) fMemoryResetMap.reset(context_id); + + }; + + @Override + public void memoryChanged(String context_id, Number[] addr, long[] size) { + fMemoryResetMap.reset(context_id); + } + + }; + + public final IMemoryMap.MemoryMapListener fMemoryMapListener = new IMemoryMap.MemoryMapListener() { + @Override + public void changed(String context_id) { + // Memory Map changed + fMemoryResetMap.reset(context_id); + } + }; + + public StackTraceCM(IStackTrace service, RunControlCM runControlCM, IMemory memory, IMemoryMap memoryMap) { fService = service; - fRunControl = runControl; - fRunControl.addListener(this); + fRunControlCM = runControlCM; + fRunControlCM.getService().addListener(fRunControlListener); + fMemory = memory; + fMemory.addListener(fMemoryListener); + fMemoryMap = memoryMap; + fMemoryMap.addListener(fMemoryMapListener); } @Override public void dispose() { - fRunControl.removeListener(this); + fRunControlCM.getService().removeListener(fRunControlListener); + fMemory.removeListener(fMemoryListener); + fMemoryMap.removeListener(fMemoryMapListener); super.dispose(); } public ICache<String[]> getChildren(final String id) { - class MyCache extends TokenCache<String[]> implements IStackTrace.DoneGetChildren { - @Override - protected IToken retrieveToken() { - return fService.getChildren(id, this); - } + class MyCache extends TransactionCache<String[]> { + + class InnerCache extends TokenCache<String[]> implements IStackTrace.DoneGetChildren { + @Override + protected IToken retrieveToken() { + return fService.getChildren(id, this); + } + + @Override + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + set(token, context_ids, error); + } + }; + + private final InnerCache fInner = new InnerCache(); - public void doneGetChildren(IToken token, Exception error, String[] context_ids) { - fRunControlStateResetMap.addValid(id, this); - set(token, context_ids, error); + @Override + protected String[] process() throws InvalidCacheException, ExecutionException { + RunControlContext rcContext = validate(fRunControlCM.getContext(id)); + validate(fInner); + fRunControlStateResetMap.addValid(id, fInner); + fMemoryResetMap.addValid(rcContext.getProcessID(), fInner); + return fInner.getData(); } }; @@ -80,8 +184,10 @@ public class StackTraceCM extends AbstractCacheManager implements IRunControl.Ru String[] subIds = new String[adjustedCount]; System.arraycopy(ids, (int)offset, subIds, 0, adjustedCount); StackTraceContext[] contexts = validate(getContexts(subIds)); + RunControlContext rcContext = validate(fRunControlCM.getContext(parentId)); if (!fIsValid) { fRunControlStateResetMap.addValid(parentId, MyCache.this); + fMemoryResetMap.addValid(rcContext.getProcessID(), MyCache.this); } return Arrays.asList(contexts); @@ -104,65 +210,38 @@ public class StackTraceCM extends AbstractCacheManager implements IRunControl.Ru } public ICache<StackTraceContext[]> getContexts(final String[] ids) { - class MyCache extends TokenCache<StackTraceContext[]> implements IStackTrace.DoneGetContext { - @Override - protected IToken retrieveToken() { - fRunControlStateResetMap.addPending(this); - return fService.getContext(ids, this); + assert ids.length != 0; + + class MyCache extends TransactionCache<StackTraceContext[]> { + class InnerCache extends TokenCache<StackTraceContext[]> implements IStackTrace.DoneGetContext { + @Override + protected IToken retrieveToken() { + return fService.getContext(ids, this); + } + + public void doneGetContext(IToken token, Exception error, StackTraceContext[] contexts) { + set(token, contexts, error); + } } - public void doneGetContext(IToken token, Exception error, StackTraceContext[] contexts) { - fRunControlStateResetMap.removePending(this); - fRunControlStateResetMap.addValid(contexts[0].getParentID(), this); - set(token, contexts, error); + private InnerCache fInner = new InnerCache(); + + @Override + protected StackTraceContext[] process() throws InvalidCacheException, ExecutionException { + StackTraceContext[] contexts = validate(fInner); + String threadId = contexts[0].getParentID(); + fMemoryResetMap.addPending(fInner); + RunControlContext threadContext = validate(fRunControlCM.getContext(threadId)); + fRunControlStateResetMap.addValid(threadId, fInner); + fMemoryResetMap.addValid(threadContext.getProcessID(), fInner); + return contexts; } } - + return mapCache(new IdKey<MyCache>(MyCache.class, Arrays.toString(ids)) { @Override MyCache createCache() { return new MyCache(); } }); } - - public void contextAdded(RunControlContext[] contexts) { - } - - public void contextChanged(RunControlContext[] contexts) { - for (RunControlContext context : contexts) { - fRunControlStateResetMap.reset(context.getID()); - } - } - - public void contextRemoved(String[] context_ids) { - for (String id : context_ids) { - fRunControlStateResetMap.reset(id); - } - } - - public void contextSuspended(String context, String pc, String reason, Map<String, Object> params) { - fRunControlStateResetMap.reset(context); - } - - public void contextResumed(String context) { - fRunControlStateResetMap.reset(context); - } - - public void containerSuspended(String context, String pc, String reason, Map<String, Object> params, - String[] suspended_ids) - { - for (String id : suspended_ids) { - fRunControlStateResetMap.reset(id); - } - } - - public void containerResumed(String[] context_ids) { - for (String id : context_ids) { - fRunControlStateResetMap.reset(id); - } - } - - public void contextException(String context, String msg) { - fRunControlStateResetMap.reset(context); - } } diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/SymbolsCM.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/SymbolsCM.java index 77ed3a461..13658b652 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/SymbolsCM.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/services/SymbolsCM.java @@ -10,20 +10,14 @@ *******************************************************************************/ package org.eclipse.tcf.debug.test.services; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.ExecutionException; import org.eclipse.tcf.debug.test.services.ResetMap.IResettable; import org.eclipse.tcf.debug.test.util.AbstractCache; -import org.eclipse.tcf.debug.test.util.CallbackCache; -import org.eclipse.tcf.debug.test.util.DataCallback; import org.eclipse.tcf.debug.test.util.ICache; import org.eclipse.tcf.debug.test.util.TokenCache; -import org.eclipse.tcf.debug.test.util.Transaction; -import org.eclipse.tcf.debug.test.util.Transaction.InvalidCacheException; +import org.eclipse.tcf.debug.test.util.TransactionCache; import org.eclipse.tcf.protocol.IToken; import org.eclipse.tcf.services.IMemoryMap; import org.eclipse.tcf.services.IMemoryMap.MemoryMapListener; @@ -59,114 +53,40 @@ public class SymbolsCM extends AbstractCacheManager { super.dispose(); } - private static final List<String> ANY_ID_PARENTS = new ArrayList<String>(1); - { - ANY_ID_PARENTS.add(ResetMap.ANY_ID); - } - abstract private class SymbolCache<V> extends CallbackCache<V> implements IResettable { + abstract private class SymbolCache<V> extends TransactionCache<V> { protected final AbstractCache<V> fInner; - private Symbol fSymbol; - private List<String> fParents = new ArrayList<String>(4); public SymbolCache(AbstractCache<V> inner) { fInner = inner; } - public void reset() { - super.reset(); - if (fInner.isValid()) fInner.reset(); - } - abstract protected String getSymbolId(); - - @Override - protected void retrieve(final DataCallback<V> rm) { - fRunControlResetMap.addPending(this); - fMemoryResetMap.addPending(this); - Transaction<V> transaction = new Transaction<V>() { - protected V process() throws InvalidCacheException, ExecutionException { - V retVal = processInner(this); - fSymbol = processSymbol(this); - fParents = processParents(this); - return retVal; - } - }; - transaction.request(rm); - } - protected V processInner(Transaction<V> t) throws InvalidCacheException, ExecutionException { - return t.validate(fInner); - } - - protected Symbol processSymbol(Transaction<V> t) throws InvalidCacheException, ExecutionException { - return t.validate( getContext(getSymbolId()) ); - } - - protected List<String> processParents(Transaction<V> t) throws InvalidCacheException, ExecutionException { - List<String> parents = new ArrayList<String>(2); - String rcContextId = fSymbol.getOwnerID(); - while( rcContextId != null ) { - parents.add(rcContextId); - RunControlContext rcContext = t.validate( fRunControlCM.getContext(rcContextId) ); - rcContextId = rcContext.getParentID(); - } - return parents; - } - @Override - protected void handleCompleted(V data, Throwable error, boolean canceled) { - if (canceled) return; - - // If we cannot retrieve the symbol's context. Reset the cache on - // any rc event. - List<String> parents = ANY_ID_PARENTS; - int updatePolicy = ISymbols.UPDATE_ON_EXE_STATE_CHANGES; - if (error == null) { - parents = fParents; - updatePolicy = fSymbol.getUpdatePolicy(); - } - updateRunControlResetMap(parents, updatePolicy, data, error); - updateMemoryMapResetMap(parents, data, error); + protected V process() throws InvalidCacheException, ExecutionException { + validate(fInner); + Symbol sym = validate( getContext(getSymbolId()) ); + addPending(sym, fInner); + RunControlContext rcContext = validate(fRunControlCM.getContext(sym.getOwnerID())); + addValid(sym, rcContext, fInner); + return validate(fInner); } + } - private void updateRunControlResetMap(List<String> parents, int updatePolicy, V data, Throwable error) { - Set<String> pendingIds = fRunControlResetMap.removePending(this); - if (updatePolicy == ISymbols.UPDATE_ON_EXE_STATE_CHANGES) { - String ownerId = parents.get(0); - if (pendingIds.contains(ownerId) || (ResetMap.ANY_ID.equals(ownerId) && !pendingIds.isEmpty())) { - // Reset cache immediately after setting value. - set(data, error, false); - } else { - fRunControlResetMap.addValid(ownerId, this); - set(data, error, true); - } - } + private void addPending(Symbol sym, IResettable cache) { + if (sym.getUpdatePolicy() == ISymbols.UPDATE_ON_EXE_STATE_CHANGES) { + fRunControlResetMap.addPending(cache); } - - private void updateMemoryMapResetMap(List<String> parents, V data, Throwable error) { - Set<String> pendingIds = fMemoryResetMap.removePending(this); - boolean resetPending = false; - if (!pendingIds.isEmpty()) { - if (ResetMap.ANY_ID.equals(parents.get(0))) { - resetPending = true; - } else { - for (String parent : parents) { - if (pendingIds.contains(parent)) { - resetPending = true; - } - } - } - } - - if (resetPending) { - // Reset cache immediately after setting value. - set(data, error, false); - } else { - fMemoryResetMap.addValid(parents, this); - set(data, error, true); - } + fMemoryResetMap.addPending(cache); + } + + private void addValid(Symbol sym, RunControlContext rcContext, IResettable cache) { + if (sym.getUpdatePolicy() == ISymbols.UPDATE_ON_EXE_STATE_CHANGES) { + String ownerId = sym.getOwnerID(); + fRunControlResetMap.addValid(ownerId, cache); } + fMemoryResetMap.addValid(rcContext.getProcessID(), cache); } private class ChildrenCache extends SymbolCache<String[]> { @@ -207,88 +127,64 @@ public class SymbolsCM extends AbstractCacheManager { return mapCache(new ChildrenCacheKey(id)); } - private class ContextCache extends SymbolCache<Symbol> { - public ContextCache(InnerContextCache inner) { - super(inner); - } - @Override - protected String getSymbolId() { - return fInner.getData().getID(); - } - @Override - protected Symbol processSymbol(Transaction<Symbol> t) throws InvalidCacheException, ExecutionException { - return fInner.getData(); - } - } + public ICache<Symbol> getContext(final String id) { + class MyCache extends TransactionCache<Symbol> { - class InnerContextCache extends TokenCache<Symbol> implements ISymbols.DoneGetContext { - private final String fId; - - public InnerContextCache(String id) { - fId = id; - } - @Override - protected IToken retrieveToken() { - return fService.getContext(fId, this); - } - public void doneGetContext(IToken token, Exception error, Symbol symbol) { - set(token, symbol, error); - } - public void resetContext() { - if (isValid()) reset(); - } - } - - private class ContextCacheKey extends IdKey<ContextCache> { - public ContextCacheKey(String id) { - super(ContextCache.class, id); - } - @Override ContextCache createCache() { return new ContextCache( new InnerContextCache(fId)); } - } - - public ICache<Symbol> getContext(String id) { - return mapCache(new ContextCacheKey(id)); - } + class InnerCache extends TokenCache<Symbol> implements ISymbols.DoneGetContext{ + @Override + protected IToken retrieveToken() { + return fService.getContext(id, this); + } + + @Override + public void doneGetContext(IToken token, Exception error, Symbol context) { + set(token, context, error); + } + }; + + private final InnerCache fInner = new InnerCache(); + + @Override + protected Symbol process() throws InvalidCacheException, ExecutionException { + Symbol sym = validate(fInner); + addPending(sym, fInner); + RunControlContext rcContext = validate(fRunControlCM.getContext(sym.getOwnerID())); + addValid(sym, rcContext, fInner); + return validate(fInner); + } + }; - private class LocationInfoCache extends SymbolCache<Map<String,Object>> { - public LocationInfoCache(InnerLocationInfoCache inner) { - super(inner); - } - @Override - protected String getSymbolId() { - return ((InnerLocationInfoCache)fInner).fId; - } + return mapCache(new IdKey<MyCache>(MyCache.class, id) { + @Override MyCache createCache() { return new MyCache(); } + }); } - class InnerLocationInfoCache extends TokenCache<Map<String,Object>> implements ISymbols.DoneGetLocationInfo { - final String fId; - - public InnerLocationInfoCache(String id) { - fId = id; - } - @Override - protected IToken retrieveToken() { - return fService.getLocationInfo(fId, this); - } - - public void doneGetLocationInfo(IToken token, Exception error, Map<String,Object> props) { - set(token, props, error); - } - - public void resetContext() { - if (isValid()) reset(); + public ICache<Map<String, Object>> getLocationInfo(final String symbol_id) { + + class InnerCache extends TokenCache<Map<String,Object>> implements ISymbols.DoneGetLocationInfo { + @Override + protected IToken retrieveToken() { + return fService.getLocationInfo(symbol_id, this); + } + + public void doneGetLocationInfo(IToken token, Exception error, Map<String,Object> props) { + set(token, props, error); + } } - } - - private class LocationInfoCacheKey extends IdKey<LocationInfoCache> { - public LocationInfoCacheKey(String id) { - super(LocationInfoCache.class, id); + + class MyCache extends SymbolCache<Map<String,Object>> { + public MyCache() { + super(new InnerCache()); + } + @Override + protected String getSymbolId() { + return symbol_id; + } } - @Override LocationInfoCache createCache() { return new LocationInfoCache( new InnerLocationInfoCache(fId)); } - } - public ICache<Map<String, Object>> getLocationInfo(String symbol_id) { - return mapCache(new LocationInfoCacheKey(symbol_id)); + return mapCache(new IdKey<MyCache>(MyCache.class, symbol_id) { + @Override MyCache createCache() { return new MyCache(); } + }); } /** diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/AbstractCache.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/AbstractCache.java index f24920923..b2b1c4a23 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/AbstractCache.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/AbstractCache.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.concurrent.CancellationException; import org.eclipse.core.runtime.IStatus; +import org.eclipse.tcf.debug.test.services.ResetMap.IResettable; import org.eclipse.tcf.protocol.Protocol; /** @@ -29,7 +30,7 @@ import org.eclipse.tcf.protocol.Protocol; * </p> * @since 2.2 */ -public abstract class AbstractCache<V> implements ICache<V> { +public abstract class AbstractCache<V> implements ICache<V>, IResettable { private static final Throwable INVALID_STATUS = new Throwable("Cache invalid"); //$NON-NLS-1$ @@ -102,7 +103,7 @@ public abstract class AbstractCache<V> implements ICache<V> { return fError; } - public void update(Callback rm) { + public void wait(Callback rm) { assert Protocol.isDispatchThread(); boolean first = false; diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/ICache.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/ICache.java index ff770bc30..4f319068d 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/ICache.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/ICache.java @@ -51,7 +51,7 @@ public interface ICache<V> { * @param cb * Callback that is called when cache becomes valid. */ - public void update(Callback cb); + public void wait(Callback cb); /** * Returns <code>true</code> if the cache is currently valid. I.e. diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TokenCache.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TokenCache.java index a7a784efd..b05815666 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TokenCache.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TokenCache.java @@ -40,6 +40,15 @@ public abstract class TokenCache<V> extends AbstractCache<V> implements IResetta } @Override + public void set(V data, Throwable error, boolean valid) { + super.set(data, error, valid); + // If new value was set to the cache but a command is still + // outstanding. Cancel the command. + IToken token = fToken.getAndSet(null); + if (token != null) token.cancel(); + } + + @Override protected void canceled() { IToken token = fToken.getAndSet(null); token.cancel(); diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/Transaction.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/Transaction.java index bd491e494..3689162e5 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/Transaction.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/Transaction.java @@ -29,7 +29,7 @@ public abstract class Transaction<V> implements Future<V>, Runnable { * validate a cache object that is stale (or has never obtained a value from * the source) */ - private static final InvalidCacheException INVALID_CACHE_EXCEPTION = new InvalidCacheException(); + public static final InvalidCacheException INVALID_CACHE_EXCEPTION = new InvalidCacheException(); /** The request object we've been given to set the transaction results in */ private DataCallback<V> fRm; @@ -185,7 +185,7 @@ public abstract class Transaction<V> implements Future<V>, Runnable { // update itself from its source, and schedule a re-attempt of the // transaction logic to occur when the stale/unset cache has been // updated - cache.update(new Callback(fRm) { + cache.wait(new Callback(fRm) { @Override protected void handleCompleted() { run(); @@ -235,7 +235,7 @@ public abstract class Transaction<V> implements Future<V>, Runnable { for (Object cacheObj : caches) { ICache<?> cache = (ICache<?>)cacheObj; if (!cache.isValid()) { - cache.update(countringRm); + cache.wait(countringRm); count++; } } @@ -262,7 +262,7 @@ public abstract class Transaction<V> implements Future<V>, Runnable { // Just sk the cache to update itself from its source, and schedule a // re-attempt of the transaction logic to occur when the stale/unset // cache has been updated - cache.update(new Callback(fRm) { + cache.wait(new Callback(fRm) { @Override protected void handleCompleted() { run(); @@ -311,7 +311,7 @@ public abstract class Transaction<V> implements Future<V>, Runnable { for (Object cacheObj : caches) { ICache<?> cache = (ICache<?>)cacheObj; if (!cache.isValid()) { - cache.update(countringRm); + cache.wait(countringRm); count++; } } diff --git a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TransactionCache.java b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TransactionCache.java index f862c650c..c910d6321 100644 --- a/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TransactionCache.java +++ b/tests/plugins/org.eclipse.tcf.debug.test/src/org/eclipse/tcf/debug/test/util/TransactionCache.java @@ -38,8 +38,8 @@ public abstract class TransactionCache<V> extends Transaction<V> implements ICac return fCache.getError(); } - public void update(Callback rm) { - fCache.update(rm); + public void wait(Callback rm) { + fCache.wait(rm); } public boolean isValid() { @@ -64,7 +64,7 @@ public abstract class TransactionCache<V> extends Transaction<V> implements ICac fDependsOnCallbacks = new ArrayList<Callback>(fDependsOn.size()); for (ICache<?> cache : fDependsOn) { assert cache.isValid(); - cache.update(new Callback() { + cache.wait(new Callback() { @Override protected void handleCompleted() { if (!isCancelled()) { |