mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-23 12:49:45 +00:00
Merge remote-tracking branch 'origin/GP-2194_Dan_torchDebuggerJMockit--SQUASHED'
This commit is contained in:
commit
c4ae03429e
@ -123,8 +123,15 @@ public class DebuggerModelServicePlugin extends Plugin
|
||||
synchronized (this) {
|
||||
this.root = r;
|
||||
}
|
||||
r.addListener(this.forRemoval);
|
||||
if (!r.isValid()) {
|
||||
boolean isInvalid = false;
|
||||
try {
|
||||
r.addListener(this.forRemoval);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
isInvalid = true;
|
||||
}
|
||||
isInvalid |= !r.isValid();
|
||||
if (isInvalid) {
|
||||
forRemoval.invalidated(root, root, "Who knows?");
|
||||
}
|
||||
CompletableFuture<? extends TargetFocusScope> findSuitable =
|
||||
|
@ -86,7 +86,7 @@ public class DebuggerLogicalBreakpointServiceTest extends AbstractGhidraHeadedDe
|
||||
|
||||
public synchronized void assertAgreesWithService() {
|
||||
waitForPass(() -> {
|
||||
assertEquals(breakpointService.getAllBreakpoints(), changeListener.current);
|
||||
assertEquals(breakpointService.getAllBreakpoints(), current);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.datastruct.CollectionChangeListener;
|
||||
import mockit.Mocked;
|
||||
import mockit.VerificationsInOrder;
|
||||
|
||||
/**
|
||||
* TODO: Cover the error cases, and cases where {@code null} is expected
|
||||
@ -64,52 +62,46 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
protected static final long TIMEOUT_MILLIS =
|
||||
SystemUtilities.isInTestingBatchMode() ? 5000 : Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Exists just for mocking, because jmockit does Bad Things (TM) to
|
||||
* CollectionChangeListener.of() if I try to mock one of those or a subclass directly. I'm
|
||||
* guessing the version we're using (1.44 as of this writing) is utterly ignorant of static
|
||||
* interface methods. What was the latest version of Java at the time?
|
||||
*
|
||||
* <p>
|
||||
* TODO: Check if a later version fixes this issue. If so, consider upgrading. If not, submit an
|
||||
* issue.
|
||||
*/
|
||||
interface CollectionChangeDelegate<E> {
|
||||
void elementAdded(E element);
|
||||
protected static class NoDuplicatesTrackingChangeListener<E>
|
||||
implements CollectionChangeListener<E> {
|
||||
Set<E> current = new HashSet<>();
|
||||
|
||||
void elementRemoved(E element);
|
||||
}
|
||||
|
||||
static class CollectionChangeDelegateWrapper<E> implements CollectionChangeListener<E> {
|
||||
protected final CollectionChangeDelegate<E> delegate;
|
||||
|
||||
public CollectionChangeDelegateWrapper(CollectionChangeDelegate<E> delegate) {
|
||||
assertNotNull("Did you remember the jmockit agent?", delegate);
|
||||
this.delegate = delegate;
|
||||
protected String formatObj(E e) {
|
||||
return String.format("%s@%08x", e.getClass().getSimpleName(),
|
||||
System.identityHashCode(e));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elementAdded(E element) {
|
||||
delegate.elementAdded(element);
|
||||
public synchronized void elementAdded(E element) {
|
||||
assertTrue(current.add(element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elementRemoved(E element) {
|
||||
delegate.elementRemoved(element);
|
||||
public synchronized void elementModified(E element) {
|
||||
assertTrue(current.contains(element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elementModified(E element) {
|
||||
// Not tested here
|
||||
public synchronized void elementRemoved(E element) {
|
||||
assertTrue(current.remove(element));
|
||||
}
|
||||
|
||||
public synchronized void sync(Collection<E> current) {
|
||||
this.current.clear();
|
||||
this.current.addAll(current);
|
||||
}
|
||||
|
||||
public synchronized void assertAgrees(Collection<E> expected) {
|
||||
assertEquals(Set.copyOf(expected), current);
|
||||
}
|
||||
}
|
||||
|
||||
@Mocked
|
||||
CollectionChangeDelegate<DebuggerModelFactory> factoryChangeListener;
|
||||
@Mocked
|
||||
CollectionChangeDelegate<DebuggerObjectModel> modelChangeListener;
|
||||
@Mocked
|
||||
CollectionChangeDelegate<TraceRecorder> recorderChangeListener;
|
||||
NoDuplicatesTrackingChangeListener<DebuggerModelFactory> factoryChangeListener =
|
||||
new NoDuplicatesTrackingChangeListener<>();
|
||||
NoDuplicatesTrackingChangeListener<DebuggerObjectModel> modelChangeListener =
|
||||
new NoDuplicatesTrackingChangeListener<>();
|
||||
NoDuplicatesTrackingChangeListener<TraceRecorder> recorderChangeListener =
|
||||
new NoDuplicatesTrackingChangeListener<>();
|
||||
|
||||
@Test
|
||||
public void testGetModelFactories() throws Exception {
|
||||
@ -120,41 +112,20 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
@Test
|
||||
public void testListenModelFactoryAdded() throws Exception {
|
||||
modelServiceInternal.setModelFactories(List.of());
|
||||
modelService.addFactoriesChangedListener(
|
||||
new CollectionChangeDelegateWrapper<>(factoryChangeListener));
|
||||
modelService.addFactoriesChangedListener(factoryChangeListener);
|
||||
modelServiceInternal.setModelFactories(List.of(mb.testFactory));
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
factoryChangeListener.elementAdded(mb.testFactory);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If this test fails, then many others probably failed because of a bug in jmockit. It seems to
|
||||
* patch static interface methods to return null, if it needs to mock any instance with the
|
||||
* interface in its type hierarchy.
|
||||
*/
|
||||
@Test
|
||||
public void testJMockitCanary() {
|
||||
assertEquals(CollectionChangeListener.class, CollectionChangeListener.of(Integer.class));
|
||||
factoryChangeListener.assertAgrees(modelService.getModelFactories());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenModelFactoryRemoved() throws Exception {
|
||||
modelServiceInternal.setModelFactories(List.of(mb.testFactory));
|
||||
// Strong ref
|
||||
CollectionChangeDelegateWrapper<DebuggerModelFactory> wrapper =
|
||||
new CollectionChangeDelegateWrapper<>(factoryChangeListener);
|
||||
modelService.addFactoriesChangedListener(wrapper);
|
||||
modelService.addFactoriesChangedListener(factoryChangeListener);
|
||||
factoryChangeListener.sync(modelService.getModelFactories());
|
||||
modelServiceInternal.setModelFactories(List.of());
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
factoryChangeListener.elementRemoved(mb.testFactory);
|
||||
}
|
||||
};
|
||||
factoryChangeListener.assertAgrees(modelService.getModelFactories());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -177,32 +148,21 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
|
||||
@Test
|
||||
public void testListenModelAdded() throws Exception {
|
||||
// Strong ref
|
||||
CollectionChangeDelegateWrapper<DebuggerObjectModel> wrapper =
|
||||
new CollectionChangeDelegateWrapper<>(modelChangeListener);
|
||||
modelService.addModelsChangedListener(wrapper);
|
||||
modelService.addModelsChangedListener(modelChangeListener);
|
||||
createTestModel();
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
modelChangeListener.elementAdded(mb.testModel);
|
||||
}
|
||||
};
|
||||
modelChangeListener.assertAgrees(modelService.getModels());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenModelRemoved() throws Exception {
|
||||
createTestModel();
|
||||
|
||||
modelService.addModelsChangedListener(
|
||||
new CollectionChangeDelegateWrapper<>(modelChangeListener));
|
||||
modelService.addModelsChangedListener(modelChangeListener);
|
||||
modelChangeListener.sync(modelService.getModels());
|
||||
modelService.removeModel(mb.testModel);
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
modelChangeListener.elementRemoved(mb.testModel);
|
||||
}
|
||||
};
|
||||
modelChangeListener.assertAgrees(modelService.getModels());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -222,18 +182,11 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
createTestModel();
|
||||
mb.createTestProcessesAndThreads();
|
||||
|
||||
// Strong ref
|
||||
CollectionChangeDelegateWrapper<TraceRecorder> wrapper =
|
||||
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
||||
modelService.addTraceRecordersChangedListener(wrapper);
|
||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
|
||||
modelService.addTraceRecordersChangedListener(recorderChangeListener);
|
||||
modelService.recordTarget(mb.testProcess1, createTargetTraceMapper(mb.testProcess1),
|
||||
ActionSource.AUTOMATIC);
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
recorderChangeListener.elementAdded(recorder);
|
||||
}
|
||||
};
|
||||
recorderChangeListener.assertAgrees(modelService.getTraceRecorders());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -243,19 +196,13 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
|
||||
TraceRecorder recorder = modelService.recordTarget(mb.testProcess1,
|
||||
createTargetTraceMapper(mb.testProcess1), ActionSource.AUTOMATIC);
|
||||
// Strong ref
|
||||
CollectionChangeDelegateWrapper<TraceRecorder> wrapper =
|
||||
new CollectionChangeDelegateWrapper<>(recorderChangeListener);
|
||||
modelService.addTraceRecordersChangedListener(wrapper);
|
||||
modelService.addTraceRecordersChangedListener(recorderChangeListener);
|
||||
recorderChangeListener.sync(modelService.getTraceRecorders());
|
||||
Trace trace = recorder.getTrace();
|
||||
recorder.stopRecording();
|
||||
waitForDomainObject(trace);
|
||||
|
||||
new VerificationsInOrder() {
|
||||
{
|
||||
recorderChangeListener.elementRemoved(recorder);
|
||||
}
|
||||
};
|
||||
recorderChangeListener.assertAgrees(modelService.getTraceRecorders());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -496,6 +443,20 @@ public class DebuggerModelServiceTest extends AbstractGhidraHeadedDebuggerGUITes
|
||||
public void testCurrentModelNullAfterClose() throws Throwable {
|
||||
createTestModel();
|
||||
|
||||
// Ensure the model is initialized before we close it
|
||||
waitOn(mb.testModel.fetchModelRoot());
|
||||
|
||||
modelService.activateModel(mb.testModel);
|
||||
assertEquals(mb.testModel, modelService.getCurrentModel());
|
||||
|
||||
waitOn(mb.testModel.close());
|
||||
assertNull(modelService.getCurrentModel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrentModelNullAfterCloseNoWait() throws Throwable {
|
||||
createTestModel();
|
||||
|
||||
modelService.activateModel(mb.testModel);
|
||||
assertEquals(mb.testModel, modelService.getCurrentModel());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user