mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 13:42:06 +00:00
Merge remote-tracking branch 'origin/GP-0-dragonmacher-test-fixes-9-22-21'
This commit is contained in:
commit
761fffc004
@ -189,8 +189,8 @@ class FGActionManager {
|
||||
return !(context instanceof FunctionGraphVertexLocationInFullViewModeActionContext);
|
||||
}
|
||||
};
|
||||
zoomOutAction.setPopupMenuData(
|
||||
new MenuData(new String[] { "Zoom Out" }, popuEndPopupGroup));
|
||||
zoomOutAction
|
||||
.setPopupMenuData(new MenuData(new String[] { "Zoom Out" }, popuEndPopupGroup));
|
||||
zoomOutAction.setKeyBindingData(new KeyBindingData(
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, DockingUtils.CONTROL_KEY_MODIFIER_MASK)));
|
||||
zoomOutAction.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Zoom"));
|
||||
@ -325,8 +325,8 @@ class FGActionManager {
|
||||
menuData.setMenuSubGroup(Integer.toString(vertexGroupingSubgroupOffset++));
|
||||
editLabelAction.setDescription("Change the label for the code block");
|
||||
editLabelAction.setPopupMenuData(menuData);
|
||||
editLabelAction.setHelpLocation(
|
||||
new HelpLocation("FunctionGraphPlugin", "Vertex_Action_Label"));
|
||||
editLabelAction
|
||||
.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Vertex_Action_Label"));
|
||||
|
||||
DockingAction fullViewAction = new DockingAction("Vertex View Mode", plugin.getName()) {
|
||||
@Override
|
||||
@ -717,8 +717,8 @@ class FGActionManager {
|
||||
};
|
||||
selectHoveredEdgesAction.setPopupMenuData(new MenuData(
|
||||
new String[] { selectionMenuName, "From Hovered Edges" }, popupSelectionGroup2));
|
||||
selectHoveredEdgesAction.setHelpLocation(
|
||||
new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
selectHoveredEdgesAction
|
||||
.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
|
||||
DockingAction selectFocusedEdgesAction =
|
||||
new DockingAction("Make Selection From Focused Edges", plugin.getName()) {
|
||||
@ -751,8 +751,8 @@ class FGActionManager {
|
||||
};
|
||||
selectFocusedEdgesAction.setPopupMenuData(new MenuData(
|
||||
new String[] { selectionMenuName, "From Focused Edges" }, popupSelectionGroup2));
|
||||
selectFocusedEdgesAction.setHelpLocation(
|
||||
new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
selectFocusedEdgesAction
|
||||
.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
|
||||
DockingAction clearCurrentSelectionAction =
|
||||
new DockingAction("Clear Current Selection", plugin.getName()) {
|
||||
@ -775,8 +775,8 @@ class FGActionManager {
|
||||
};
|
||||
clearCurrentSelectionAction.setPopupMenuData(new MenuData(
|
||||
new String[] { selectionMenuName, "Clear Graph Selection" }, popupSelectionGroup3));
|
||||
clearCurrentSelectionAction.setHelpLocation(
|
||||
new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
clearCurrentSelectionAction
|
||||
.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Path_Selection"));
|
||||
|
||||
DockingAction selectAllAction =
|
||||
new DockingAction("Select All Code Units", plugin.getName()) {
|
||||
@ -815,12 +815,12 @@ class FGActionManager {
|
||||
return isValidContext(context);
|
||||
}
|
||||
};
|
||||
selectAllAction.setKeyBindingData(
|
||||
new KeyBindingData(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK));
|
||||
selectAllAction
|
||||
.setKeyBindingData(new KeyBindingData(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK));
|
||||
selectAllAction.setPopupMenuData(new MenuData(
|
||||
new String[] { selectionMenuName, "Select All Code Units" }, popupSelectionGroup3));
|
||||
selectAllAction.setHelpLocation(
|
||||
new HelpLocation("FunctionGraphPlugin", "Code_Unit_Selection"));
|
||||
selectAllAction
|
||||
.setHelpLocation(new HelpLocation("FunctionGraphPlugin", "Code_Unit_Selection"));
|
||||
|
||||
provider.addLocalAction(chooseFormatsAction);
|
||||
provider.addLocalAction(homeAction);
|
||||
@ -885,9 +885,7 @@ class FGActionManager {
|
||||
// icon to be blank in the menu, but to use this icon on the toolbar.
|
||||
layoutAction.setDefaultIcon(ResourceManager.loadImage("images/preferences-system.png"));
|
||||
|
||||
List<ActionState<FGLayoutProvider>> actionStates =
|
||||
loadActionStatesForLayoutProviders();
|
||||
|
||||
List<ActionState<FGLayoutProvider>> actionStates = loadActionStatesForLayoutProviders();
|
||||
for (ActionState<FGLayoutProvider> actionState : actionStates) {
|
||||
layoutAction.addActionState(actionState);
|
||||
}
|
||||
@ -900,15 +898,19 @@ class FGActionManager {
|
||||
}
|
||||
|
||||
private List<ActionState<FGLayoutProvider>> loadActionStatesForLayoutProviders() {
|
||||
|
||||
List<FGLayoutProvider> layoutInstances = plugin.getLayoutProviders();
|
||||
return createActionStates(layoutInstances);
|
||||
}
|
||||
|
||||
private List<ActionState<FGLayoutProvider>> createActionStates(
|
||||
List<FGLayoutProvider> layoutProviders) {
|
||||
List<ActionState<FGLayoutProvider>> list = new ArrayList<>();
|
||||
HelpLocation layoutHelpLocation =
|
||||
new HelpLocation("FunctionGraphPlugin", "Function_Graph_Action_Layout");
|
||||
for (FGLayoutProvider layout : layoutInstances) {
|
||||
for (FGLayoutProvider layout : layoutProviders) {
|
||||
|
||||
ActionState<FGLayoutProvider> layoutState = new ActionState<>(
|
||||
layout.getLayoutName(), layout.getActionIcon(), layout);
|
||||
ActionState<FGLayoutProvider> layoutState =
|
||||
new ActionState<>(layout.getLayoutName(), layout.getActionIcon(), layout);
|
||||
layoutState.setHelpLocation(layoutHelpLocation);
|
||||
list.add(layoutState);
|
||||
}
|
||||
@ -1157,9 +1159,8 @@ class FGActionManager {
|
||||
private void makeSelectionFromAddresses(AddressSet addresses) {
|
||||
ProgramSelection selection = new ProgramSelection(addresses);
|
||||
plugin.getTool()
|
||||
.firePluginEvent(
|
||||
new ProgramSelectionPluginEvent("Spoof!", selection,
|
||||
provider.getCurrentProgram()));
|
||||
.firePluginEvent(new ProgramSelectionPluginEvent("Spoof!", selection,
|
||||
provider.getCurrentProgram()));
|
||||
}
|
||||
|
||||
private void ungroupVertices(Set<GroupedFunctionGraphVertex> groupVertices) {
|
||||
@ -1214,6 +1215,11 @@ class FGActionManager {
|
||||
layoutAction.setCurrentActionState(state);
|
||||
}
|
||||
|
||||
void setLayouts(List<FGLayoutProvider> layouts) {
|
||||
List<ActionState<FGLayoutProvider>> states = createActionStates(layouts);
|
||||
layoutAction.setActionStates(states);
|
||||
}
|
||||
|
||||
ActionState<FGLayoutProvider> getCurrentLayoutState() {
|
||||
return layoutAction.getCurrentState();
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ import ghidra.app.plugin.core.clipboard.ClipboardPlugin;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.*;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.layout.TestFGLayoutProvider;
|
||||
import ghidra.app.plugin.core.functiongraph.graph.vertex.*;
|
||||
import ghidra.app.plugin.core.functiongraph.mvc.*;
|
||||
import ghidra.app.services.*;
|
||||
@ -74,6 +75,7 @@ import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.test.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.task.RunManager;
|
||||
|
||||
public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
@ -552,11 +554,19 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
protected void showFunctionGraphProvider() {
|
||||
|
||||
ComponentProvider provider = tool.getComponentProvider("Function Graph");
|
||||
FGProvider provider = (FGProvider) tool.getComponentProvider("Function Graph");
|
||||
tool.showComponentProvider(provider, true);
|
||||
|
||||
graphProvider = waitForComponentProvider(FGProvider.class);
|
||||
assertNotNull("Graph not shown", graphProvider);
|
||||
|
||||
installTestGraphLayout(provider);
|
||||
}
|
||||
|
||||
protected void installTestGraphLayout(FGProvider provider) {
|
||||
FGActionManager actionManager = provider.getActionManager();
|
||||
List<FGLayoutProvider> layouts = List.of(new TestFGLayoutProvider());
|
||||
runSwing(() -> actionManager.setLayouts(layouts));
|
||||
}
|
||||
|
||||
protected ProgramSelection makeSingleVertexSelectionInCodeBrowser() {
|
||||
@ -1003,7 +1013,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
combined.add(groupedVertex);
|
||||
pickVertices(combined);
|
||||
|
||||
// execute the 'add to group' action
|
||||
// execute the 'add to group' action
|
||||
JComponent component = getComponent(groupedVertex);
|
||||
DockingAction action =
|
||||
(DockingAction) TestUtils.getInstanceField("addToGroupAction", component);
|
||||
@ -1025,7 +1035,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
Collection<FGEdge> ungroupedEdges) {
|
||||
for (FGEdge edge : ungroupedEdges) {
|
||||
//
|
||||
// note: the edges we are given *may* be linked to disposed vertices, so we have
|
||||
// note: the edges we are given *may* be linked to disposed vertices, so we have
|
||||
// to locate the edge in the graph that may represent the given edge.
|
||||
//
|
||||
FGEdge currentEdge = getCurrentEdge(functionGraph, edge);
|
||||
@ -1222,12 +1232,6 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
protected FGData create12345Graph() {
|
||||
|
||||
//
|
||||
// Note: we are manipulating the graph for testing by removing vertices. Some layouts
|
||||
// do not handle this well, so we will use one we know works.
|
||||
//
|
||||
setMinCrossLayout();
|
||||
|
||||
// function sscanf
|
||||
FGData funtionGraphData = graphFunction("100415a");
|
||||
|
||||
@ -1316,7 +1320,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
// This tests verifies that a group will not be created if there is only one vertex
|
||||
// found upon restoring settings. If we want to put that code back, then this test
|
||||
// is again valid.
|
||||
//
|
||||
//
|
||||
public void dontTestRestoringWhenCodeBlocksHaveChanged_DoesntRegroup() {
|
||||
int transactionID = -1;
|
||||
try {
|
||||
@ -1390,38 +1394,38 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
FunctionGraph functionGraph = graphData.getFunctionGraph();
|
||||
Graph<FGVertex, FGEdge> graph = functionGraph;
|
||||
|
||||
Set<FGVertex> ungroupedVertices = selectVertices( functionGraph,
|
||||
"01002d2b" /* Another Local*/,
|
||||
|
||||
Set<FGVertex> ungroupedVertices = selectVertices( functionGraph,
|
||||
"01002d2b" /* Another Local*/,
|
||||
"01002d1f" /* MyLocal */);
|
||||
Set<FGEdge> ungroupedEdges = getEdges(graph, ungroupedVertices);
|
||||
assertEquals("Did not grab all known edges for vertices", 4, ungroupedEdges.size());
|
||||
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
|
||||
assertVerticesRemoved(graph, ungroupedVertices);
|
||||
assertEdgesRemoved(graph, ungroupedEdges);
|
||||
|
||||
|
||||
// -1 because one one of the edges was between two of the vertices being grouped
|
||||
int expectedGroupedEdgeCount = ungroupedEdges.size() - 1;
|
||||
GroupedFunctionGraphVertex groupedVertex =
|
||||
validateNewGroupedVertexFromVertices(functionGraph, ungroupedVertices,
|
||||
validateNewGroupedVertexFromVertices(functionGraph, ungroupedVertices,
|
||||
expectedGroupedEdgeCount);
|
||||
|
||||
|
||||
ungroup(groupedVertex);
|
||||
|
||||
|
||||
assertVertexRemoved(graph, groupedVertex);
|
||||
assertVerticesAdded(graph, ungroupedVertices);
|
||||
assertEdgesAdded(functionGraph, ungroupedEdges);
|
||||
assertSelected(ungroupedVertices);
|
||||
|
||||
|
||||
}
|
||||
// @formatter:on
|
||||
|
||||
protected void doTestGroupingProperlyTranslatesEdgesFromGroupedVerticesToRealVertices() {
|
||||
//
|
||||
// WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
|
||||
// This is not a junit test in that it is long, involved, hidden and complicated. We
|
||||
// WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!!
|
||||
// This is not a junit test in that it is long, involved, hidden and complicated. We
|
||||
// need to test this functionality, but we don't have a jComplicatedTest, so we will do
|
||||
// it here.
|
||||
//
|
||||
@ -1429,32 +1433,32 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
//
|
||||
// Desired Behavior: We want to be able to group vertices, group grouped vertices and then
|
||||
// ungroup them in any order. For us to be able to do this, our group
|
||||
// vertices must store enough edge information to be able to ungroup
|
||||
// vertices must store enough edge information to be able to ungroup
|
||||
// and find vertices for edges *whether or now those vertices have been
|
||||
// grouped or ungrouped*
|
||||
//
|
||||
// Original Bug: We had a bug loosely described here:
|
||||
//
|
||||
// Original Bug: We had a bug loosely described here:
|
||||
// 0) Start with a directed graph of vertices.
|
||||
// 1) Create two separate group vertices (A and B), such that A has an edge to B.
|
||||
// 2) Create a third group vertex (Z) that contains a non-grouped vertex (B) *and* one
|
||||
// 2) Create a third group vertex (Z) that contains a non-grouped vertex (B) *and* one
|
||||
// of the other groups.
|
||||
// 3) Now, ungroup the 1 remaining originally grouped vertex (A).
|
||||
// 4) **At this point, the code could not determine which endpoint to pick for the edge
|
||||
// 4) **At this point, the code could not determine which endpoint to pick for the edge
|
||||
// that used to be from Z->A. Which vertex inside of A represented the connection
|
||||
// pointing into Z (by way of B).
|
||||
//
|
||||
// The fix is mentioned in the Desired Behavior section.
|
||||
//
|
||||
// The fix is mentioned in the Desired Behavior section.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
|
||||
0) Initial Graph
|
||||
|
||||
|
||||
1 -> 2 -> 3 -> 4
|
||||
|
|
||||
*
|
||||
5
|
||||
|
||||
|
||||
*/
|
||||
|
||||
create12345Graph();
|
||||
@ -1469,7 +1473,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
FGVertex v4 = vertex("1004196");
|
||||
FGVertex v5 = vertex("100419c");
|
||||
|
||||
// verify initial graph
|
||||
// verify initial graph
|
||||
verifyEdge(v1, v2);
|
||||
verifyEdge(v2, v3);
|
||||
verifyEdge(v3, v4);
|
||||
@ -1478,12 +1482,12 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
/*
|
||||
1) Create two separate group vertices (A and B), such that A has an edge to B.
|
||||
|
||||
|
||||
A (v:{1,2} e:{1->2, 2->3}) -> B (v:{3,4} e:{2->3,3->4,3->5})
|
||||
|
|
||||
*
|
||||
5
|
||||
|
||||
|
||||
*/
|
||||
|
||||
GroupedFunctionGraphVertex groupA = group("A", v1, v2);
|
||||
@ -1494,13 +1498,13 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
verifyEdgeCount(2);// no other edges
|
||||
|
||||
/*
|
||||
2) Create a third group vertex (Z) that contains a non-grouped vertex *and* one
|
||||
2) Create a third group vertex (Z) that contains a non-grouped vertex *and* one
|
||||
of the other groups (B).
|
||||
|
||||
|
||||
A (v:{1,2} e:{1->2, 2->3}) -> Z (
|
||||
v:{B (v:{3,4} e:{2->3,3->4,3->5}), 5}
|
||||
e:{2->3, 3->5}
|
||||
)
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
@ -1511,12 +1515,12 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
/*
|
||||
3) Now, ungroup the 1 remaining originally grouped vertex (A).
|
||||
|
||||
|
||||
1 -> 2 -> Z (
|
||||
v:{B (v:{3,4} e:{2->3,3->4,3->5}), 5}
|
||||
e:{2->3, 3->5}
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
ungroup(groupA);
|
||||
@ -1526,14 +1530,14 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
verifyEdgeCount(2);
|
||||
|
||||
/*
|
||||
|
||||
|
||||
4) Now, ungroup Z and go back to having one remaining group vertex (B)
|
||||
|
||||
|
||||
1 -> 2 -> -> B (v:{3,4} e:{2->3,3->4,3->5})
|
||||
|
|
||||
*
|
||||
5
|
||||
|
||||
|
||||
*/
|
||||
|
||||
ungroup(groupZ);
|
||||
@ -1545,12 +1549,12 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
/*
|
||||
5) Finally, ungroup the last group and make sure the graph is restored
|
||||
|
||||
|
||||
1 -> 2 -> 3 -> 4
|
||||
|
|
||||
*
|
||||
5
|
||||
|
||||
5
|
||||
|
||||
*/
|
||||
|
||||
ungroup(groupB);
|
||||
@ -1564,19 +1568,19 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
}
|
||||
|
||||
private void doTestRestoringWhenCodeBlocksHaveChanged_DoesntRegroup() {
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
// inside of the grouped vertex is no longer available when the graph attempts to restore
|
||||
// the group vertex user settings (i.e., when restarting Ghidra, the previously grouped
|
||||
// vertices should reappear).
|
||||
// vertices should reappear).
|
||||
//
|
||||
// In this test, we will be mutating a group of 2 nodes such
|
||||
// that one of the nodes has been split into two. This leaves only one vertex to
|
||||
// that one of the nodes has been split into two. This leaves only one vertex to
|
||||
// be found by the regrouping algorithm. Furthermore, the regrouping will not take place
|
||||
// if at least two vertices cannot be found.
|
||||
//
|
||||
|
||||
//
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
@ -1587,8 +1591,8 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// -01002cf5: 2 in, 1 out
|
||||
int expectedGroupedEdgeCount = 5;
|
||||
GroupedFunctionGraphVertex groupedVertex = validateNewGroupedVertexFromVertices(
|
||||
@ -1598,10 +1602,10 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
Address minAddress = addresses.getMinAddress();
|
||||
|
||||
//
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// our programs. So, we will instead just navigate away from the current function, clear
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// data saved in the program has been used to re-group.
|
||||
//
|
||||
graphFunction("0100415a");
|
||||
@ -1623,19 +1627,19 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
}
|
||||
|
||||
protected void doTestRestoringWhenCodeBlocksHaveChanged_WillRegroup() {
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
// inside of the grouped vertex is no longer available when the graph attempts to restore
|
||||
// the group vertex user settings (i.e., when restarting Ghidra, the previously grouped
|
||||
// vertices should reappear).
|
||||
//
|
||||
// In this test, we will be mutating a group of 3 nodes such
|
||||
// that one of the nodes has been split into two. This leaves 2 vertices to
|
||||
// that one of the nodes has been split into two. This leaves 2 vertices to
|
||||
// be found by the regrouping algorithm. Furthermore, the regrouping *will* still
|
||||
// take place, as at least two vertices cannot be found.
|
||||
//
|
||||
|
||||
//
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
@ -1646,8 +1650,8 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// -01002d11: 2 in, (1 out that was removed)
|
||||
// -01002d1f: 2 out (1 in that was removed)
|
||||
int expectedGroupedEdgeCount = 6;
|
||||
@ -1659,10 +1663,10 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
Address maxAddress = addresses.getMaxAddress();
|
||||
|
||||
//
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// our programs. So, we will instead just navigate away from the current function, clear
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// data saved in the program has been used to re-group.
|
||||
//
|
||||
graphFunction("0100415a");
|
||||
@ -1706,12 +1710,12 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
protected void doTestSymbolAddedWhenGrouped_SymbolInsideOfGroupNode() {
|
||||
//
|
||||
// By default, if the FunctionGraph detects a symbol addition to one of the code blocks
|
||||
// in the graph, then it will split the affected vertex (tested elsewhere).
|
||||
// in the graph, then it will split the affected vertex (tested elsewhere).
|
||||
// However, if the affected vertex is grouped, then the FG will not split the node, but
|
||||
// should still show the 'stale' indicator.
|
||||
//
|
||||
|
||||
//
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
@ -1722,8 +1726,8 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// -01002cf5: 2 in, 1 out
|
||||
int expectedGroupedEdgeCount = 5;
|
||||
GroupedFunctionGraphVertex groupedVertex = validateNewGroupedVertexFromVertices(
|
||||
@ -1748,8 +1752,8 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
return reference.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an edge that represents the given edge, which may no longer exist with
|
||||
/**
|
||||
* Finds an edge that represents the given edge, which may no longer exist with
|
||||
* the same (==) edge instances.
|
||||
*/
|
||||
private FGEdge getCurrentEdge(FunctionGraph functionGraph, FGEdge edge) {
|
||||
@ -1998,29 +2002,29 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
private void setMinCrossLayout() {
|
||||
Object actionManager = getInstanceField("actionManager", graphProvider);
|
||||
@SuppressWarnings("unchecked")
|
||||
final MultiStateDockingAction<Class<? extends FGLayoutProvider>> action =
|
||||
(MultiStateDockingAction<Class<? extends FGLayoutProvider>>) getInstanceField(
|
||||
"layoutAction", actionManager);
|
||||
final MultiStateDockingAction<FGLayoutProvider> action =
|
||||
(MultiStateDockingAction<FGLayoutProvider>) getInstanceField("layoutAction",
|
||||
actionManager);
|
||||
runSwing(() -> {
|
||||
List<ActionState<Class<? extends FGLayoutProvider>>> states =
|
||||
action.getAllActionStates();
|
||||
for (ActionState<Class<? extends FGLayoutProvider>> state : states) {
|
||||
Class<? extends FGLayoutProvider> layoutClass = state.getUserData();
|
||||
if (layoutClass.getSimpleName().contains("MinCross")) {
|
||||
List<ActionState<FGLayoutProvider>> states = action.getAllActionStates();
|
||||
for (ActionState<FGLayoutProvider> state : states) {
|
||||
FGLayoutProvider layoutProvider = state.getUserData();
|
||||
if (layoutProvider.getLayoutName().contains("MinCross")) {
|
||||
action.setCurrentActionState(state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new AssertException("Unable to find MinCross layout");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected FGData triggerPersistenceAndReload(String functionAddress) {
|
||||
//
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// our programs. So, we will instead just navigate away from the current function, clear
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// data saved in the program has been used to re-group.
|
||||
//
|
||||
String otherAddress = "0100415a";
|
||||
@ -2277,7 +2281,7 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
//==================================================================================================
|
||||
|
||||
protected void moveView(int amount) {
|
||||
Point translation = new Point(amount, amount);
|
||||
@ -2316,11 +2320,11 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
||||
DockingActionIf action = getAction(tool, "FunctionGraphPlugin", name);
|
||||
ToggleDockingAction displayAction = (ToggleDockingAction) action;
|
||||
setToggleActionSelected(displayAction, new ActionContext(), expectedVisible);
|
||||
//
|
||||
//
|
||||
// // make sure the action is not already in the state we expect
|
||||
// assertEquals(name + " action is not selected as expected", !expectedVisible,
|
||||
// displayAction.isSelected());
|
||||
//
|
||||
//
|
||||
// performAction(displayAction, true);
|
||||
}
|
||||
|
||||
|
@ -65,12 +65,12 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
@Test
|
||||
public void testGroupingPersistence() throws Exception {
|
||||
//
|
||||
// Round-trip test to ensure that a grouped graph will be restored after re-opening a
|
||||
//
|
||||
// Round-trip test to ensure that a grouped graph will be restored after re-opening a
|
||||
// program.
|
||||
//
|
||||
|
||||
//
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
@ -95,7 +95,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
// Record the edges for later validation. Note: we have to keep the string form, as the
|
||||
// toString() on the edges will call back to its vertices, which will later have been
|
||||
// disposed.
|
||||
Collection<FGEdge> oringalGroupedEdges = new HashSet<>(graph.getEdges());// copy so they don't get cleared
|
||||
Collection<FGEdge> oringalGroupedEdges = new HashSet<>(graph.getEdges());// copy so they don't get cleared
|
||||
List<String> originalEdgeStrings = new ArrayList<>(oringalGroupedEdges.size());
|
||||
for (FGEdge edge : oringalGroupedEdges) {
|
||||
originalEdgeStrings.add(edge.toString());
|
||||
@ -136,7 +136,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
/**
|
||||
* Tests that the app will recognize the case where the entry point to a function is invalid,
|
||||
* and generate the appropriate error message when trying to create a function graph.
|
||||
*
|
||||
*
|
||||
* Step 1: Make sure the function graph window is closed.
|
||||
* Step 2: Clear the entry point bytes
|
||||
* Step 3: Open the function graph window to generate the graph again.
|
||||
@ -144,8 +144,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
*/
|
||||
public void testInvalidFunctionEntryPoint() {
|
||||
|
||||
// First thing we need to do is close the function graph window. It's opened on
|
||||
// startup by default in this test suite but we want it closed until we clear the
|
||||
// First thing we need to do is close the function graph window. It's opened on
|
||||
// startup by default in this test suite but we want it closed until we clear the
|
||||
// function code bytes.
|
||||
this.getFunctionGraphController().getProvider().closeComponent();
|
||||
|
||||
@ -170,7 +170,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
runSwing(() -> clearAction.actionPerformed(context));
|
||||
waitForBusyTool(tool);
|
||||
|
||||
// Open the window; the tool will try to generate a new graph but should fail and generate
|
||||
// Open the window; the tool will try to generate a new graph but should fail and generate
|
||||
// an error message.
|
||||
DockingActionIf openGraphAction;
|
||||
openGraphAction = getAction(fgp, "Display Function Graph");
|
||||
@ -186,8 +186,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
@Test
|
||||
public void testGroupAndUngroup_WhenOneOfTheGroupIsAGroup() {
|
||||
//
|
||||
// This test seeks to ensure that you can group a selection of vertices when one of
|
||||
//
|
||||
// This test seeks to ensure that you can group a selection of vertices when one of
|
||||
// those vertices is itself a group.
|
||||
//
|
||||
|
||||
@ -217,7 +217,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
group(secondUngroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// 5 edges expected:
|
||||
// -ungrouped vertex: 1 in, 1 out
|
||||
// -grouped vertex : 1 in, 2 out
|
||||
expectedGroupedEdgeCount = 5;
|
||||
@ -248,7 +248,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
@Test
|
||||
public void testGroupingPersistence_WhenOneOfTheGroupIsAGroup() throws Exception {
|
||||
//
|
||||
//
|
||||
// This test seeks to ensure that groups within groups are persisted and restored.
|
||||
//
|
||||
|
||||
@ -284,7 +284,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//printEdges(outerUngroupedEdges);
|
||||
group(outerUngroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// 5 edges expected:
|
||||
// -ungrouped vertex: 1 in, 1 out
|
||||
// -grouped vertex : 1 in, 2 out
|
||||
expectedGroupedEdgeCount = 5;
|
||||
@ -353,8 +353,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
@Test
|
||||
public void testUngroupAll() {
|
||||
//
|
||||
// Group some vertices and then group that vertex with some vertices to create a
|
||||
//
|
||||
// Group some vertices and then group that vertex with some vertices to create a
|
||||
// recursively/nested grouping. Also create a second top-level group. Make sure the
|
||||
// ungroup all action will restore the original graph.
|
||||
//
|
||||
@ -434,8 +434,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
// The coloring algorithm:
|
||||
// 1) If the grouped vertices are not colored, then use the default group color
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 3) If all grouped vertices share the same color, then make the group that color
|
||||
//
|
||||
// This test is for 1)
|
||||
@ -459,7 +459,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyDefaultColor(v1, v2);
|
||||
@ -470,8 +470,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
// The coloring algorithm:
|
||||
// 1) If the grouped vertices are not colored, then use the default group color
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 3) If all grouped vertices share the same color, then make the group that color
|
||||
//
|
||||
// This test is for 2)
|
||||
@ -500,7 +500,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyColor(v1, newColor);
|
||||
@ -512,8 +512,8 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
// The coloring algorithm:
|
||||
// 1) If the grouped vertices are not colored, then use the default group color
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 2) If the grouped vertices are colored, but not all the same color,
|
||||
// then use the default group color=
|
||||
// 3) If all grouped vertices share the same color, then make the group that color
|
||||
//
|
||||
// This test is for 3)
|
||||
@ -543,7 +543,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyColor(v1, newColor);
|
||||
@ -572,7 +572,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyColor(v1, newGroupColor);
|
||||
@ -607,7 +607,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyColor(v1, newGroupColor);
|
||||
@ -642,7 +642,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
verifyColor(v1, newGroupColor);
|
||||
@ -666,7 +666,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
Color newGroupColor = Color.CYAN;
|
||||
color(group, newGroupColor);
|
||||
|
||||
//
|
||||
//
|
||||
// Trigger persistence
|
||||
//
|
||||
Address groupAddress = group.getVertexAddress();
|
||||
@ -683,7 +683,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
v1 = vertex("01002d06");
|
||||
@ -703,7 +703,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
FGVertex v2 = vertex("01002d0f");
|
||||
GroupedFunctionGraphVertex group = group("A", v1, v2);
|
||||
|
||||
//
|
||||
//
|
||||
// Trigger persistence
|
||||
//
|
||||
Address groupAddress = group.getVertexAddress();
|
||||
@ -720,7 +720,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
v1 = vertex("01002d06");
|
||||
@ -737,16 +737,16 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
//
|
||||
// Color just one of the vertices
|
||||
//
|
||||
//
|
||||
Color newColor = Color.RED;
|
||||
color(v1, newColor);
|
||||
|
||||
//
|
||||
// Group a node
|
||||
//
|
||||
//
|
||||
GroupedFunctionGraphVertex group = group("A", v1, v2);
|
||||
|
||||
//
|
||||
//
|
||||
// Trigger persistence
|
||||
//
|
||||
Address groupAddress = group.getVertexAddress();
|
||||
@ -763,7 +763,7 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
//
|
||||
ungroup(group);
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
v1 = vertex("01002d06");
|
||||
@ -781,16 +781,16 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
|
||||
//
|
||||
// Color just one of the vertices
|
||||
//
|
||||
//
|
||||
Color newColor = Color.RED;
|
||||
color(v1, newColor);
|
||||
|
||||
//
|
||||
// Group a node
|
||||
//
|
||||
//
|
||||
GroupedFunctionGraphVertex group = group("A", v1, v2);
|
||||
|
||||
//
|
||||
//
|
||||
// Trigger reset
|
||||
//
|
||||
Address groupAddress = group.getVertexAddress();
|
||||
@ -800,9 +800,9 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
// Make sure the group is gone
|
||||
//
|
||||
FGVertex vertex = graphData.getFunctionGraph().getVertexForAddress(groupAddress);
|
||||
assertFalse(vertex instanceof GroupedFunctionGraphVertex);// the group has been removed
|
||||
assertFalse(vertex instanceof GroupedFunctionGraphVertex);// the group has been removed
|
||||
|
||||
//
|
||||
//
|
||||
// Test the grouped vertices colors
|
||||
//
|
||||
v1 = vertex("01002d06");
|
||||
@ -838,11 +838,6 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
assertEquals(alpha, alphAfterGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSymbolAddedWhenGrouped_SymbolOutsideOfGroupNode() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
@ -853,85 +848,85 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
FunctionGraph functionGraph = graphData.getFunctionGraph();
|
||||
Graph<FGVertex, FGEdge> graph = functionGraph;
|
||||
|
||||
Set<FGVertex> ungroupedVertices = selectVertices( functionGraph,
|
||||
"01002d2b" /* Another Local*/,
|
||||
|
||||
Set<FGVertex> ungroupedVertices = selectVertices( functionGraph,
|
||||
"01002d2b" /* Another Local*/,
|
||||
"01002d1f" /* MyLocal */);
|
||||
Set<FGEdge> ungroupedEdges = getEdges(graph, ungroupedVertices);
|
||||
assertEquals("Did not grab all known edges for vertices", 4, ungroupedEdges.size());
|
||||
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
|
||||
assertVerticesRemoved(graph, ungroupedVertices);
|
||||
assertEdgesRemoved(graph, ungroupedEdges);
|
||||
|
||||
|
||||
// -1 because one one of the edges was between two of the vertices being grouped
|
||||
int expectedGroupedEdgeCount = ungroupedEdges.size() - 1;
|
||||
GroupedFunctionGraphVertex groupedVertex =
|
||||
validateNewGroupedVertexFromVertices(functionGraph, ungroupedVertices,
|
||||
validateNewGroupedVertexFromVertices(functionGraph, ungroupedVertices,
|
||||
expectedGroupedEdgeCount);
|
||||
|
||||
|
||||
ungroup(groupedVertex);
|
||||
|
||||
|
||||
assertVertexRemoved(graph, groupedVertex);
|
||||
assertVerticesAdded(graph, ungroupedVertices);
|
||||
assertEdgesAdded(functionGraph, ungroupedEdges);
|
||||
assertSelected(ungroupedVertices);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doTestRestoringWhenCodeBlocksHaveChanged_WillRegroup() {
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
//
|
||||
// Tests the behavior of how group vertices are restored when one or more of the vertices
|
||||
// inside of the grouped vertex is no longer available when the graph attempts to restore
|
||||
// the group vertex user settings (i.e., when restarting Ghidra, the previously grouped
|
||||
// vertices should reappear).
|
||||
//
|
||||
// In this test, we will be mutating a group of 3 nodes such
|
||||
// that one of the nodes has been split into two. This leaves 2 vertices to
|
||||
// that one of the nodes has been split into two. This leaves 2 vertices to
|
||||
// be found by the regrouping algorithm. Furthermore, the regrouping *will* still
|
||||
// take place, as at least two vertices cannot be found.
|
||||
//
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
FunctionGraph functionGraph = graphData.getFunctionGraph();
|
||||
|
||||
|
||||
Set<FGVertex> ungroupedVertices = selectVertices(functionGraph,
|
||||
"01002d11" /* LAB_01002d11 */, "01002cf5" /* ghidra */, "01002d1f" /* MyLocal */);
|
||||
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// -01002d11: 2 in, (1 out that was removed)
|
||||
// -01002d1f: 2 out (1 in that was removed)
|
||||
int expectedGroupedEdgeCount = 6;
|
||||
GroupedFunctionGraphVertex groupedVertex = validateNewGroupedVertexFromVertices(
|
||||
functionGraph, ungroupedVertices, expectedGroupedEdgeCount);
|
||||
|
||||
|
||||
AddressSetView addresses = groupedVertex.getAddresses();
|
||||
Address minAddress = addresses.getMinAddress();
|
||||
Address maxAddress = addresses.getMaxAddress();
|
||||
|
||||
|
||||
//
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// Ideally, we would like to save, close and re-open the program so that we can get
|
||||
// a round-trip saving and reloading. However, in the test environment, we cannot save
|
||||
// our programs. So, we will instead just navigate away from the current function, clear
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// the cache (to make sure that we read the settings again), and then verify that the
|
||||
// data saved in the program has been used to re-group.
|
||||
//
|
||||
graphFunction("0100415a");
|
||||
clearCache();
|
||||
|
||||
|
||||
//
|
||||
// Add a label to trigger a code block change
|
||||
//
|
||||
Address labelAddress = createLabel("01002d18");// in the middle of the LAB_01002d11 code block
|
||||
|
||||
|
||||
//
|
||||
// Relaunch the graph, which will use the above persisted group settings...
|
||||
//
|
||||
@ -941,22 +936,22 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
FGVertex expectedGroupVertex = functionGraph.getVertexForAddress(minAddress);
|
||||
assertTrue(expectedGroupVertex instanceof GroupedFunctionGraphVertex);
|
||||
assertEquals(maxAddress, expectedGroupVertex.getAddresses().getMaxAddress());
|
||||
|
||||
|
||||
// ...we expect that the two original grouped vertices have again been grouped...
|
||||
FGVertex splitVertex =
|
||||
functionGraph.getVertexForAddress(getAddress("01002d11") /* LAB_01002d11 */);
|
||||
assertTrue("The split vertex should not have been regrouped",
|
||||
!(splitVertex instanceof GroupedFunctionGraphVertex));
|
||||
|
||||
|
||||
FGVertex unchangedVertex =
|
||||
functionGraph.getVertexForAddress(getAddress("01002cf5") /* ghidra */);
|
||||
assertTrue("An unchanged vertex should have been regrouped: " + unchangedVertex,
|
||||
(unchangedVertex instanceof GroupedFunctionGraphVertex));
|
||||
|
||||
|
||||
unchangedVertex = functionGraph.getVertexForAddress(getAddress("01002d1f") /* MyLocal */);
|
||||
assertTrue("An unchanged vertex should have been regrouped: " + unchangedVertex,
|
||||
(unchangedVertex instanceof GroupedFunctionGraphVertex));
|
||||
|
||||
|
||||
// ...but the newly created code block has not
|
||||
FGVertex newlyCreatedVertex = functionGraph.getVertexForAddress(labelAddress);
|
||||
assertNotNull(newlyCreatedVertex);
|
||||
@ -966,34 +961,34 @@ public class FunctionGraphGroupVertices1Test extends AbstractFunctionGraphTest {
|
||||
protected void doTestSymbolAddedWhenGrouped_SymbolInsideOfGroupNode() {
|
||||
//
|
||||
// By default, if the FunctionGraph detects a symbol addition to one of the code blocks
|
||||
// in the graph, then it will split the affected vertex (tested elsewhere).
|
||||
// in the graph, then it will split the affected vertex (tested elsewhere).
|
||||
// However, if the affected vertex is grouped, then the FG will not split the node, but
|
||||
// should still show the 'stale' indicator.
|
||||
//
|
||||
|
||||
//
|
||||
|
||||
//
|
||||
// Pick a function and group some nodes.
|
||||
//
|
||||
FGData graphData = graphFunction("01002cf5");
|
||||
FunctionGraph functionGraph = graphData.getFunctionGraph();
|
||||
|
||||
|
||||
Set<FGVertex> ungroupedVertices =
|
||||
selectVertices(functionGraph, "01002d11" /* LAB_01002d11 */, "01002cf5" /* ghidra */);
|
||||
|
||||
|
||||
group(ungroupedVertices);
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
|
||||
// 5 edges expected:
|
||||
// -01002cf5: 2 out
|
||||
// -01002cf5: 2 in, 1 out
|
||||
int expectedGroupedEdgeCount = 5;
|
||||
GroupedFunctionGraphVertex groupedVertex = validateNewGroupedVertexFromVertices(
|
||||
functionGraph, ungroupedVertices, expectedGroupedEdgeCount);
|
||||
|
||||
|
||||
//
|
||||
// Add a label to trigger a code block change
|
||||
//
|
||||
Address labelAddress = createLabel("01002d18");// in the middle of the LAB_01002d11 code block
|
||||
|
||||
|
||||
//
|
||||
// Make sure the newly created code block does not have a corresponding vertex
|
||||
//
|
||||
|
@ -36,7 +36,7 @@ import resources.icons.EmptyIcon;
|
||||
* drop-down icon that allows users to change the state of the button. Also, by default, as
|
||||
* the user presses the button, it will execute the action corresponding to the current
|
||||
* state.
|
||||
*
|
||||
*
|
||||
* <p>Warning: if you use this action in a toolbar, then be sure to call the
|
||||
* {@link #MultiStateDockingAction(String, String, boolean) correct constructor}. If you call
|
||||
* another constructor, or pass false for this boolean above, your
|
||||
@ -50,7 +50,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
private static Icon EMPTY_ICON = new EmptyIcon(16, 16);
|
||||
|
||||
private List<ActionState<T>> actionStates = new ArrayList<>();
|
||||
private int currentStateIndex = 0;
|
||||
private int currentStateIndex = -1;
|
||||
private MultiActionDockingActionIf multiActionGenerator;
|
||||
private MultipleActionDockingToolbarButton multipleButton;
|
||||
|
||||
@ -66,7 +66,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
|
||||
/**
|
||||
* Call this constructor with this action will not be added to a toolbar
|
||||
*
|
||||
*
|
||||
* @param name the action name
|
||||
* @param owner the owner
|
||||
* @see #MultiStateDockingAction(String, String, boolean)
|
||||
@ -78,7 +78,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
/**
|
||||
* Use this constructor explicitly when this action is used in a toolbar, passing true
|
||||
* for <code>isToolbarAction</code> (see the javadoc header note).
|
||||
*
|
||||
*
|
||||
* @param name the action name
|
||||
* @param owner the owner
|
||||
* @param isToolbarAction true if this action is a toolbar action
|
||||
@ -110,7 +110,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
* <p>
|
||||
* Also, if the parameter is true, then the button will behave like a button in terms of
|
||||
* mouse feedback. If false, then the button will behave more like a label.
|
||||
*
|
||||
*
|
||||
* @param doPerformAction true to call {@link #doActionPerformed(ActionContext)} when the
|
||||
* user presses the button for this action (not the drop-down menu; see above)
|
||||
*/
|
||||
@ -133,7 +133,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
* default, the popup menu items will use the icons as provided by the {@link ActionState}.
|
||||
* By passing true to this method, icons will not be used in the popup menu. Instead, a
|
||||
* checkbox icon will be used to show the active action state.
|
||||
*
|
||||
*
|
||||
* @param useCheckboxForIcons true to use a checkbox
|
||||
*/
|
||||
public void setUseCheckboxForIcons(boolean useCheckboxForIcons) {
|
||||
@ -144,7 +144,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
* Sets the icon to use if the active action state does not supply an icon. This is useful if
|
||||
* you wish for your action states to not use icon, but desire the action itself to have an
|
||||
* icon.
|
||||
*
|
||||
*
|
||||
* @param icon the icon
|
||||
*/
|
||||
public void setDefaultIcon(Icon icon) {
|
||||
@ -165,7 +165,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
* This is the callback to be overridden when the child wishes to respond to user button
|
||||
* presses that are on the button and not the drop-down. This will only be called if
|
||||
* {@link #performActionOnPrimaryButtonClick} is true.
|
||||
*
|
||||
*
|
||||
* @param context the action context
|
||||
*/
|
||||
protected void doActionPerformed(ActionContext context) {
|
||||
@ -270,10 +270,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
}
|
||||
currentStateIndex = indexOf;
|
||||
|
||||
// we set the icon here to handle the odd case where this action is not used in a toolbar
|
||||
if (multipleButton != null) {
|
||||
setButtonState(actionState);
|
||||
}
|
||||
setButtonState(actionState);
|
||||
|
||||
ToolBarData tbd = getToolBarData();
|
||||
tbd.setIcon(getIcon(actionState));
|
||||
@ -317,6 +314,16 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
|
||||
private void setButtonState(ActionState<T> actionState) {
|
||||
|
||||
if (multipleButton == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionState == null) {
|
||||
multipleButton.setIcon(null);
|
||||
multipleButton.setToolTipText(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Icon icon = getIcon(actionState);
|
||||
multipleButton.setIcon(icon);
|
||||
multipleButton.setToolTipText(actionState.getName());
|
||||
@ -337,6 +344,9 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
}
|
||||
|
||||
public String getToolTipText() {
|
||||
if (actionStates.isEmpty()) {
|
||||
return getName() + ": <no action states installed>";
|
||||
}
|
||||
return getName() + ": " + getCurrentState().getName();
|
||||
}
|
||||
|
||||
@ -355,8 +365,7 @@ public abstract class MultiStateDockingAction<T> extends DockingAction {
|
||||
|
||||
setSelected(isSelected);
|
||||
|
||||
setMenuBarData(
|
||||
new MenuData(new String[] { actionState.getName() }));
|
||||
setMenuBarData(new MenuData(new String[] { actionState.getName() }));
|
||||
HelpLocation helpLocation = actionState.getHelpLocation();
|
||||
if (helpLocation != null) {
|
||||
setHelpLocation(helpLocation);
|
||||
|
Loading…
Reference in New Issue
Block a user