Merge remote-tracking branch 'origin/GP-0_Dan_testFixes-20220802-1'

This commit is contained in:
Ryan Kurtz 2022-08-02 12:25:23 -04:00
commit 781c765e60
7 changed files with 83 additions and 35 deletions

View file

@ -1060,6 +1060,11 @@ public class DebuggerLogicalBreakpointServicePlugin extends Plugin
changeListeners.remove(l); changeListeners.remove(l);
} }
@Override
public CompletableFuture<Void> changesSettled() {
return CompletableFuture.supplyAsync(() -> null, executor);
}
protected MappedLogicalBreakpoint synthesizeLogicalBreakpoint(Program program, Address address, protected MappedLogicalBreakpoint synthesizeLogicalBreakpoint(Program program, Address address,
long length, Collection<TraceBreakpointKind> kinds) { long length, Collection<TraceBreakpointKind> kinds) {
/** /**

View file

@ -18,6 +18,7 @@ package ghidra.app.plugin.core.debug.service.modules;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
@ -596,6 +597,11 @@ public class DebuggerStaticMappingServicePlugin extends Plugin
changeListeners.remove(l); changeListeners.remove(l);
} }
@Override
public CompletableFuture<Void> changesSettled() {
return changeDebouncer.settled();
}
@Override @Override
public void processEvent(PluginEvent event) { public void processEvent(PluginEvent event) {
if (event instanceof ProgramOpenedPluginEvent) { if (event instanceof ProgramOpenedPluginEvent) {

View file

@ -147,6 +147,16 @@ public interface DebuggerLogicalBreakpointService {
*/ */
void removeChangeListener(LogicalBreakpointsChangeListener l); void removeChangeListener(LogicalBreakpointsChangeListener l);
/**
* Get a future which completes after pending changes have been processed
*
* <p>
* The returned future completes after all change listeners have been invoked
*
* @return the future
*/
CompletableFuture<Void> changesSettled();
static <T> T programOrTrace(ProgramLocation loc, static <T> T programOrTrace(ProgramLocation loc,
BiFunction<? super Program, ? super Address, ? extends T> progFunc, BiFunction<? super Program, ? super Address, ? extends T> progFunc,
BiFunction<? super Trace, ? super Address, ? extends T> traceFunc) { BiFunction<? super Trace, ? super Address, ? extends T> traceFunc) {

View file

@ -16,6 +16,7 @@
package ghidra.app.services; package ghidra.app.services;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import com.google.common.collect.Range; import com.google.common.collect.Range;
@ -400,6 +401,16 @@ public interface DebuggerStaticMappingService {
*/ */
void removeChangeListener(DebuggerStaticMappingChangeListener l); void removeChangeListener(DebuggerStaticMappingChangeListener l);
/**
* Get a future which completes when pending changes have all settled
*
* <p>
* The returned future completes after all change listeners have been invoked.
*
* @return the future
*/
CompletableFuture<Void> changesSettled();
/** /**
* Collect likely matches for destination programs for the given trace module * Collect likely matches for destination programs for the given trace module
* *

View file

@ -20,6 +20,7 @@ import static org.junit.Assert.*;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.Before; import org.junit.Before;
@ -63,12 +64,14 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
protected DebuggerBreakpointsPlugin breakpointsPlugin; protected DebuggerBreakpointsPlugin breakpointsPlugin;
protected DebuggerBreakpointsProvider breakpointsProvider; protected DebuggerBreakpointsProvider breakpointsProvider;
protected DebuggerStaticMappingService mappingService; protected DebuggerStaticMappingService mappingService;
protected DebuggerLogicalBreakpointService breakpointService;
@Before @Before
public void setUpBreakpointsProviderTest() throws Exception { public void setUpBreakpointsProviderTest() throws Exception {
breakpointsPlugin = addPlugin(tool, DebuggerBreakpointsPlugin.class); breakpointsPlugin = addPlugin(tool, DebuggerBreakpointsPlugin.class);
breakpointsProvider = waitForComponentProvider(DebuggerBreakpointsProvider.class); breakpointsProvider = waitForComponentProvider(DebuggerBreakpointsProvider.class);
mappingService = tool.getService(DebuggerStaticMappingService.class); mappingService = tool.getService(DebuggerStaticMappingService.class);
breakpointService = tool.getService(DebuggerLogicalBreakpointService.class);
} }
protected void waitAndFlush(TraceRecorder recorder) throws Throwable { protected void waitAndFlush(TraceRecorder recorder) throws Throwable {
@ -538,7 +541,7 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
} }
@Test @Test
public void testActionFilters() throws Exception { public void testActionFilters() throws Throwable {
createTestModel(); createTestModel();
mb.createTestProcessesAndThreads(); mb.createTestProcessesAndThreads();
@ -561,14 +564,23 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
addLiveBreakpoint(recorder1, 0x55550321); addLiveBreakpoint(recorder1, 0x55550321);
addLiveMemoryAndBreakpoint(mb.testProcess3, recorder3); addLiveMemoryAndBreakpoint(mb.testProcess3, recorder3);
addLiveBreakpoint(recorder3, 0x55550321); addLiveBreakpoint(recorder3, 0x55550321);
waitRecorder(recorder1);
waitRecorder(recorder3);
addStaticMemoryAndBreakpoint(); addStaticMemoryAndBreakpoint();
// Note, no program breakpoint for 0321... // Note, no program breakpoint for 0321...
programManager.openProgram(program); programManager.openProgram(program);
traceManager.openTrace(trace1); traceManager.openTrace(trace1);
CompletableFuture<Void> mappingsSettled = mappingService.changesSettled();
CompletableFuture<Void> breakpointsSettled = breakpointService.changesSettled();
traceManager.openTrace(trace3); traceManager.openTrace(trace3);
// Because mapping service debounces, wait for breakpoints to be reconciled waitForSwing();
waitOn(mappingsSettled);
waitOn(breakpointsSettled);
waitForSwing();
LogicalBreakpointTableModel bptModel = breakpointsProvider.breakpointTableModel; LogicalBreakpointTableModel bptModel = breakpointsProvider.breakpointTableModel;
waitForPass(() -> {
List<LogicalBreakpointRow> data = copyModelData(bptModel); List<LogicalBreakpointRow> data = copyModelData(bptModel);
assertEquals(2, data.size()); assertEquals(2, data.size());
LogicalBreakpointRow row1 = data.get(0); LogicalBreakpointRow row1 = data.get(0);
@ -590,13 +602,11 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
// OK, back to work // OK, back to work
assertEquals(2, lb1.getTraceBreakpoints().size()); assertEquals(2, lb1.getTraceBreakpoints().size());
assertEquals(2, lb2.getTraceBreakpoints().size()); assertEquals(2, lb2.getTraceBreakpoints().size());
});
List<LogicalBreakpointRow> breakData = copyModelData(bptModel);
List<BreakpointLocationRow> filtLocs = List<BreakpointLocationRow> filtLocs =
breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
for (LogicalBreakpointRow breakRow : breakData) { for (LogicalBreakpointRow breakRow : data) {
assertEquals(2, breakRow.getLocationCount()); assertEquals(2, breakRow.getLocationCount());
} }
assertEquals(4, filtLocs.size()); assertEquals(4, filtLocs.size());
@ -605,9 +615,9 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
performAction(breakpointsProvider.actionFilterByCurrentTrace); performAction(breakpointsProvider.actionFilterByCurrentTrace);
// No trace active, so empty :) // No trace active, so empty :)
breakData = bptModel.getModelData(); data = copyModelData(bptModel);
filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
for (LogicalBreakpointRow breakRow : breakData) { for (LogicalBreakpointRow breakRow : data) {
assertEquals(0, breakRow.getLocationCount()); assertEquals(0, breakRow.getLocationCount());
} }
assertEquals(0, filtLocs.size()); assertEquals(0, filtLocs.size());
@ -615,9 +625,9 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
traceManager.activateTrace(trace1); traceManager.activateTrace(trace1);
waitForSwing(); waitForSwing();
breakData = bptModel.getModelData(); data = copyModelData(bptModel);
filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
for (LogicalBreakpointRow breakRow : breakData) { for (LogicalBreakpointRow breakRow : data) {
assertEquals(1, breakRow.getLocationCount()); assertEquals(1, breakRow.getLocationCount());
} }
assertEquals(2, filtLocs.size()); assertEquals(2, filtLocs.size());
@ -626,14 +636,14 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
performAction(breakpointsProvider.actionFilterLocationsByBreakpoints); performAction(breakpointsProvider.actionFilterLocationsByBreakpoints);
// No breakpoint selected, so no change, yet. // No breakpoint selected, so no change, yet.
breakData = bptModel.getModelData(); data = copyModelData(bptModel);
filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
for (LogicalBreakpointRow breakRow : breakData) { for (LogicalBreakpointRow breakRow : data) {
assertEquals(1, breakRow.getLocationCount()); assertEquals(1, breakRow.getLocationCount());
} }
assertEquals(2, filtLocs.size()); assertEquals(2, filtLocs.size());
breakpointsProvider.setSelectedBreakpoints(Set.of(breakData.get(0).getLogicalBreakpoint())); breakpointsProvider.setSelectedBreakpoints(Set.of(data.get(0).getLogicalBreakpoint()));
waitForSwing(); waitForSwing();
filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
@ -642,9 +652,9 @@ public class DebuggerBreakpointsProviderTest extends AbstractGhidraHeadedDebugge
assertTrue(breakpointsProvider.actionFilterByCurrentTrace.isEnabled()); assertTrue(breakpointsProvider.actionFilterByCurrentTrace.isEnabled());
performAction(breakpointsProvider.actionFilterByCurrentTrace); performAction(breakpointsProvider.actionFilterByCurrentTrace);
breakData = bptModel.getModelData(); data = copyModelData(bptModel);
filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData(); filtLocs = breakpointsProvider.locationFilterPanel.getTableFilterModel().getModelData();
for (LogicalBreakpointRow breakRow : breakData) { for (LogicalBreakpointRow breakRow : data) {
assertEquals(2, breakRow.getLocationCount()); assertEquals(2, breakRow.getLocationCount());
} }
assertEquals(2, filtLocs.size()); assertEquals(2, filtLocs.size());

View file

@ -547,16 +547,19 @@ public class DebuggerModelProviderTest extends AbstractGhidraHeadedDebuggerGUITe
modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[2]")); modelProvider.setPath(TraceObjectKeyPath.parse("Processes[0].Threads[2]"));
waitForSwing(); waitForSwing();
AbstractNode nodeThread2 = modelProvider.objectsTreePanel.getSelectedItem(); AbstractNode nodeThread2 =
waitForValue(() -> modelProvider.objectsTreePanel.getSelectedItem());
assertEquals(1, nodeThread2.getChildren().size()); assertEquals(1, nodeThread2.getChildren().size());
performAction(modelProvider.actionShowPrimitivesInTree, modelProvider, true); performAction(modelProvider.actionShowPrimitivesInTree, modelProvider, true);
assertTrue(modelProvider.isShowPrimitivesInTree()); assertTrue(modelProvider.isShowPrimitivesInTree());
nodeThread2 = waitForValue(() -> modelProvider.objectsTreePanel.getSelectedItem());
assertEquals(3, nodeThread2.getChildren().size()); assertEquals(3, nodeThread2.getChildren().size());
assertEquals(nodeThread2, modelProvider.objectsTreePanel.getSelectedItem()); assertEquals(nodeThread2, modelProvider.objectsTreePanel.getSelectedItem());
performAction(modelProvider.actionShowPrimitivesInTree, modelProvider, true); performAction(modelProvider.actionShowPrimitivesInTree, modelProvider, true);
assertFalse(modelProvider.isShowPrimitivesInTree()); assertFalse(modelProvider.isShowPrimitivesInTree());
nodeThread2 = waitForValue(() -> modelProvider.objectsTreePanel.getSelectedItem());
assertEquals(1, nodeThread2.getChildren().size()); assertEquals(1, nodeThread2.getChildren().size());
assertEquals(nodeThread2, modelProvider.objectsTreePanel.getSelectedItem()); assertEquals(nodeThread2, modelProvider.objectsTreePanel.getSelectedItem());
} }

View file

@ -112,6 +112,9 @@ public class AsyncDebouncer<T> {
/** /**
* Receive the next settled event * Receive the next settled event
* *
* <p>
* The returned future completes <em>after</em> all registered listeners have been invoked.
*
* @return a future which completes with the value of the next settled event. * @return a future which completes with the value of the next settled event.
*/ */
public synchronized CompletableFuture<T> settled() { public synchronized CompletableFuture<T> settled() {