/*******************************************************************************
* 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.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 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
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();
// 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>() {
@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));
if (pcShouldChange) {
StackTraceContext topFrame = frames.get(0);
Assert.assertFalse("Expected PC to be updated", pc.equals(topFrame.getInstructionAddress().toString()));
}
return null;
}
}.get();
}
}