diff --git a/Ghidra/Features/FunctionGraph/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java b/Ghidra/Features/FunctionGraph/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java deleted file mode 100644 index e9e4787cf6..0000000000 --- a/Ghidra/Features/FunctionGraph/src/screen/java/help/screenshot/FunctionGraphPluginScreenShots.java +++ /dev/null @@ -1,1013 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package help.screenshot; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.awt.*; -import java.awt.geom.Point2D; -import java.awt.geom.Point2D.Double; -import java.awt.image.BufferedImage; -import java.io.File; -import java.util.*; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - -import javax.swing.*; - -import org.junit.*; - -import docking.*; -import docking.action.DockingAction; -import docking.menu.ActionState; -import docking.menu.MultiStateDockingAction; -import docking.util.image.Callout; -import docking.util.image.CalloutComponentInfo; -import docking.widgets.dialogs.MultiLineInputDialog; -import edu.uci.ics.jung.graph.Graph; -import edu.uci.ics.jung.visualization.VisualizationServer; -import edu.uci.ics.jung.visualization.VisualizationViewer; -import edu.uci.ics.jung.visualization.picking.PickedState; -import generic.test.TestUtils; -import ghidra.app.cmd.function.DeleteFunctionCmd; -import ghidra.app.cmd.label.AddLabelCmd; -import ghidra.app.plugin.core.functiongraph.AbstractFunctionGraphTest; -import ghidra.app.plugin.core.functiongraph.FGProvider; -import ghidra.app.plugin.core.functiongraph.graph.*; -import ghidra.app.plugin.core.functiongraph.graph.layout.FGLayoutProvider; -import ghidra.app.plugin.core.functiongraph.graph.vertex.FGVertex; -import ghidra.app.plugin.core.functiongraph.graph.vertex.GroupedFunctionGraphVertex; -import ghidra.app.plugin.core.functiongraph.mvc.*; -import ghidra.graph.viewer.GraphViewerUtils; -import ghidra.program.model.address.Address; -import ghidra.program.model.symbol.SourceType; -import ghidra.test.TestEnv; -import ghidra.util.Msg; -import ghidra.util.exception.AssertException; - -public class FunctionGraphPluginScreenShots extends AbstractFunctionGraphTest { - - private MyScreen screen; - private int width = 400; - private int height = 400; - - public FunctionGraphPluginScreenShots() { - super(); - } - - @Override - @Before - public void setUp() throws Exception { - - screen = new MyScreen(); - try { - screen.setUp(); - } - catch (Exception e) { - failWithException("Unepected exception in setup", e); - } - - super.setUp(); - - screen.program = program; - - setLayout(); - } - - @Override - @After - public void tearDown() throws Exception { - // We share the program--don't let the screen release it's copy - // screen.env.release(screen.program); - - super.tearDown(); - - screen.saveOrDisplayImage(testName.getMethodName()); - } - - @Override - protected TestEnv getEnv() { - return screen.env; - } - - @Override - protected String getStartingProgramName() { - return "WinHelloCPP.exe"; - } - - @Override - protected void openProgram() { - program = env.getProgram(getStartingProgramName()); - } - - @Override - protected String getStartingAddress() { - return "406630"; - } - - @Test - public void testFunctionGraphWindow() { - go("406630");// _strlen function - - setSize(750, 560);// size first, as the positioning is sensitive to the size - setZoom(1.0);// full zoom - centerDisplay(); - captureProviderWindow(); - } - - @Test - public void testFunctionGraph_Provider_Undefined() { - createUndefinedFunction(); - - isolateProvider(); - hideSatellite(); - - setSize(700, 500);// size first, as the positioning is sensitive to the size - setZoom(.25);// zoom out a bit to show more vertices - centerDisplay(); - captureProvider(); - cropAndRemoveHeader(388, 194); - } - - @Test - public void testFunctionGraph_Stale_Graph() { - String address = "406630"; - go(address);// _strlen function - - hideSatellite(); - - setSize(612, 300); - - // make a change to trigger the 'stale graph' message - changeLabel(getAddress(address)); - - captureProviderWindow(); - - cropAndKeepMessageSection(); - - drawRectangleAroundMessageText(); - } - - public void testFunctionGraph_Vertex_Header() { - String address = "406630"; - go(address);// _strlen function - - setSize(1000, 1000);// size first, as the positioning is sensitive to the size - setZoom(1.0);// full zoom - centerDisplay(); - - captureProvider(); - cropRootVertexHeader(); - } - - @Test - public void testFunctionGraph_Grouped_Vertex_Header() { - String functionAddress = "405d29"; - go(functionAddress);// ___updatetmbcinfo function - - setSize(1000, 1000);// size first, as the positioning is sensitive to the size - setZoom(1.0);// full zoom - - String a1 = "405d46"; - String a2 = "405d4c"; - FGVertex v1 = vertex(a1); - FGVertex v2 = vertex(a2); - - GroupedFunctionGraphVertex group = group(null, v1, v2); - centerDisplay(); - - captureProvider(); - cropVertexHeader(group); - } - - @Test - public void testFunctionGraph_Pre_Group() { - String functionAddress = "405d29"; - go(functionAddress);// ___updatetmbcinfo function - hideSatellite(); - - setNestedLayout(); - - setSize(1000, 600);// size first, as the positioning is sensitive to the size - setZoom(1d);// full zoom - - FGVertex root = vertex(functionAddress); - - String a1 = "405d46"; - String a2 = "405d4c"; - FGVertex v1 = vertex(a1); - FGVertex v2 = vertex(a2); - - pickVertices(v1, v2); - moveGraphToUpperLeftCorner(root); - - captureProvider(); - cropVertices(root, v1, v2); - -// createGroupButtonCallout_PlayArea(v1, "FunctionGraph_Pre_Group.png"); - createGroupButtonCallout(v1); - } - - @Test - public void testFunctionGraph_Post_Group() { - String functionAddress = "405d29"; - go(functionAddress);// ___updatetmbcinfo function - - setNestedLayout(); - - setSize(1000, 500);// size first, as the positioning is sensitive to the size - setZoom(.85); - - FGVertex root = vertex(functionAddress); - moveGraphToUpperLeftCorner(root); - - String a1 = "405d46"; - String a2 = "405d4c"; - FGVertex v1 = vertex(a1); - FGVertex v2 = vertex(a2); - - GroupedFunctionGraphVertex group = group(null, v1, v2); - - captureProvider(); - cropVertices(root, group); - } - - @Test - public void testFunctionGraph_Group_Text_Dialog() throws Exception { - String functionAddress = "405d29"; - go(functionAddress);// ___updatetmbcinfo function - - FGVertex root = vertex(functionAddress); - moveGraphToUpperLeftCorner(root); - - String a1 = "405d46"; - String a2 = "405d4c"; - FGVertex v1 = vertex(a1); - FGVertex v2 = vertex(a2); - - DialogComponentProvider dialog = showGroupTextDialog(v1, v2); - screen.captureDialog(dialog); - pressButtonByText(dialog.getComponent(), "Cancel"); - } - - @Test - public void testFunctionGraph_Provider_Header() { - - setSize(800, 400); - - captureProviderWindow(); - - GenericHeader providerHeader = getHeader(); - cropHeaderToActions(providerHeader); - } - - @Test - public void testFunctionGraph_Vertex_Drop_Shadow() { - // - // This image is a bit abnormal. It is a picture of a vertex next to itself after it - // has been zoomed out past its 'interaction threshold'. Further, both vertices are - // zoomed out past the point of readability. - // - String functionAddress = "4057c4"; - go(functionAddress);// __fflush_nolock - - setNestedLayout(); - - setSize(500, 500);// size first, as the positioning is sensitive to the size - double beforeThresholdZoom = GraphViewerUtils.INTERACTION_ZOOM_THRESHOLD + .01; - setZoom(beforeThresholdZoom); - moveGraphToUpperLeftCorner(); - - Image graphImage1 = captureGraph(); - - double pastThresholdZoom = GraphViewerUtils.INTERACTION_ZOOM_THRESHOLD - .01; - setZoom(pastThresholdZoom); - moveGraphToUpperLeftCorner(); - - Image graphImage2 = captureGraph(); - - // create an empty image onto which we will place both images, side-by-side - int bufferSpace = 50; - int graphWidth = graphImage1.getWidth(null) * 2 + bufferSpace; - int graphHeight = graphImage1.getHeight(null); - BufferedImage fullImage = screen.createEmptyImage(graphWidth, graphHeight); - - Graphics2D g = (Graphics2D) fullImage.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.drawImage(graphImage1, 0, 0, null); - - int xOffset = graphImage1.getWidth(null) + bufferSpace; - g.drawImage(graphImage2, xOffset, 0, null); - - int w = 3; - int x1 = graphImage1.getWidth(null) + (bufferSpace / 2) - (w / 2);// between images - int y1 = 10;// down a bit - - int h = (graphImage1.getHeight(null) - 10) - y1; - - g.setColor(Color.BLACK); - g.fillRect(x1, y1, w, h); - - screen.image = fullImage; - } - -// For Debug of callout -// public void testCallout() { -// go("406630"); // _strlen function -// -// setSize(750, 560); // size first, as the positioning is sensitive to the size -// centerDisplay(); -// -// doTestCallout(); -// } -// -// private void doTestCallout() { -// ComponentProvider provider = screen.getComponentProvider(FunctionGraphProvider.class); -// JComponent providerComponent = provider.getComponent(); -// DockableComponent parent = getDockableComponent(providerComponent); -// JButton component = getToolbarButton(provider, "Go To Function Entry Point"); -// -// Rectangle bounds = component.getBounds(); -// Point relativeLocation = bounds.getLocation(); -// Dimension size = bounds.getSize(); -// Point screenLocation = new Point(relativeLocation); -// SwingUtilities.convertPointToScreen(screenLocation, component.getParent()); -// CalloutComponentInfo info = -// new CalloutComponentInfo(parent, component, screenLocation, relativeLocation, size); -// -// createCallout(parent, info); -// showImage("FunctionGraphPlugin", "FunctionGraph_Post_Group.png"); -// } - -//================================================================================================== -// Private Methods -//================================================================================================== - - private Image captureGraph() { - FGController controller = getFunctionGraphController(); - FGView view = controller.getView(); - VisualizationViewer viewer = view.getPrimaryGraphViewer(); - FunctionGraph functionGraph = getFunctionGraph(); - Graph graph = functionGraph; - Collection vertices = graph.getVertices(); - Rectangle layoutBounds = - GraphViewerUtils.getBoundsForVerticesInLayoutSpace(viewer, vertices); - Rectangle viewBounds = - GraphViewerUtils.translateRectangleFromLayoutSpaceToViewSpace(viewer, layoutBounds); - - // add some padding - int padding = 40; - viewBounds.x -= padding; - viewBounds.y -= padding; - viewBounds.width += (2 * padding); - viewBounds.height += (2 * padding); - - FGProvider provider = screen.getProvider(FGProvider.class); - JComponent parent = provider.getComponent(); - DockableComponent dc = getDockableComponent(parent); - - viewBounds = SwingUtilities.convertRectangle(provider.getComponent(), viewBounds, dc); - - captureProvider(); - - screen.crop(viewBounds); - - return screen.image; - } - - private Image captureVertex(FGVertex v) { - - // make sure the vertex is showing - moveGraphToUpperLeftCorner(v); - - FGController controller = getFunctionGraphController(); - FGView view = controller.getView(); - VisualizationViewer viewer = view.getPrimaryGraphViewer(); - - FGProvider provider = screen.getProvider(FGProvider.class); - JComponent parent = provider.getComponent(); - DockableComponent dc = getDockableComponent(parent); - - Rectangle vertexBounds = GraphViewerUtils.getVertexBoundsInViewSpace(viewer, v); - JComponent component = v.getComponent(); - - vertexBounds = SwingUtilities.convertRectangle(component.getParent(), vertexBounds, dc); - - captureProvider(); - - screen.crop(vertexBounds); - - return screen.image; - } - - private void cropHeaderToActions(final GenericHeader header) { - final AtomicReference ref = new AtomicReference<>(); - runSwing(() -> { - int actionsWidth = header.getToolBarWidth(); - - Window window = windowForComponent(header); - Rectangle headerBounds = header.getBounds(); - Rectangle bounds = new Rectangle(headerBounds); - - // ugh--apparently the toolbar does not correctly calculate its minimum size - int padding = 30; - - bounds = SwingUtilities.convertRectangle(header.getParent(), headerBounds, window); - bounds.x = bounds.x + bounds.width - (actionsWidth + padding); - - padding = 8;// now some vertical padding - bounds.y -= padding; - bounds.height += (2 * padding); - - ref.set(bounds); - }); - - Rectangle bounds = ref.get(); - screen.crop(bounds); - } - - private GenericHeader getHeader() { - FGController controller = getFunctionGraphController(); - ComponentProvider provider = controller.getProvider(); - DockableComponent dc = getDockableComponent(provider.getComponent()); - return dc.getHeader(); - } - - private void createCallout(JComponent parentComponent, CalloutComponentInfo calloutInfo) { - // create image of parent with extra space for callout feature - Image parentImage = screen.captureComponent(parentComponent); - - Callout callout = new Callout(); - screen.image = callout.createCalloutOnImage(parentImage, calloutInfo); - -// createCalloutOnImage(parentImage, parentComponent, calloutInfo); - } - - private void createGroupButtonCallout(FGVertex v) { - - JButton component = getToolbarButton(v, "Group Vertices"); - FGProvider provider = screen.getProvider(FGProvider.class); - JComponent parent = provider.getComponent(); - - FGController controller = getFunctionGraphController(); - FGView view = controller.getView(); - VisualizationViewer viewer = view.getPrimaryGraphViewer(); - - Rectangle bounds = component.getBounds(); - Dimension size = bounds.getSize(); - Point location = bounds.getLocation(); - - JComponent vertexComponent = v.getComponent(); - Point newLocation = - SwingUtilities.convertPoint(component.getParent(), location, vertexComponent); - - Point relativePoint = GraphViewerUtils.translatePointFromVertexRelativeSpaceToViewSpace( - viewer, v, newLocation); - - Point screenLocation = new Point(relativePoint); - SwingUtilities.convertPointToScreen(screenLocation, parent); - - CalloutComponentInfo calloutInfo = new FGCalloutComponentInfo(parent, component, - screenLocation, relativePoint, size, viewer, v); - - createCallout(parent, calloutInfo); - } - - private JButton getToolbarButton(FGVertex vertex, String actionName) { - - JComponent component = vertex.getComponent(); - GenericHeader header = (GenericHeader) getInstanceField("genericHeader", component); - return getToolbarButton(header, actionName); - } - - private JButton getToolbarButton(GenericHeader header, String actionName) { - // get the header's 'toolBarMgr' - DockableToolBarManager - Object toolBarMgr = getInstanceField("toolBarMgr", header); - - // get the toolbar manager's 'toolBarManager' - ToolBarManager - Object toolBarManager = getInstanceField("toolBarManager", toolBarMgr); - - // get the tool bar manager's manager's 'toolBar' - JComponent toolbar = (JComponent) getInstanceField("toolBar", toolBarManager); - Component[] components = toolbar.getComponents(); - for (Component c : components) { - if (!(c instanceof JButton)) { - continue; - } - - String name = c.getName(); - if (actionName.equals(name)) { - return (JButton) c; - } - } - - Assert.fail("Could not find action button"); - return null; - } - - private void drawRectangleAroundMessageText() { - int imageHeight = screen.image.getHeight(null); - - int boxSize = 60; - int boxThickness = 3; - int x = 1; - int y = imageHeight - boxSize; - int w = 250; - int h = boxSize - boxThickness; - Rectangle rect = new Rectangle(x, y, w, h); - - // drop shadow - Color color = Color.GRAY; - screen.drawRectangle(color, rect, boxThickness); - - // box - x -= 1; - y -= 2; - color = new Color(0xB5, 0xDE, 0x2F); - rect.x = x; - rect.y = y; - screen.drawRectangle(color, rect, boxThickness); - } - - private void changeLabel(Address address) { - AddLabelCmd cmd = new AddLabelCmd(address, "Test.Label", SourceType.USER_DEFINED); - int id = program.startTransaction("Test"); - try { - cmd.applyTo(program); - } - finally { - program.endTransaction(id, true); - } - } - - private void cropRootVertexHeader() { - FunctionGraph functionGraph = getFunctionGraph(); - FGVertex rootVertex = functionGraph.getRootVertex(); - cropVertexHeader(rootVertex); - } - - private void cropVertexHeader(FGVertex vertex) { - FGPrimaryViewer viewer = getPrimaryGraphViewer(); - Rectangle bounds = GraphViewerUtils.getVertexBoundsInViewSpace(viewer, vertex); - - DockableComponent dockableComponent = getDockableComponent(viewer); - Point loc = SwingUtilities.convertPoint(viewer, bounds.getLocation(), dockableComponent); - bounds.setLocation(loc); - - // - // We want to keep the whole header, with a buffer space around it of about 10px - // - Rectangle area = new Rectangle(bounds); - int offset = 10; - area.x -= offset; - area.y -= offset; - area.width += (2 * offset); - area.height = 50; - screen.crop(area); - } - - private void cropVertices(FGVertex... vertices) { - - FGPrimaryViewer viewer = getPrimaryGraphViewer(); - List list = Arrays.asList(vertices); - Rectangle bounds = GraphViewerUtils.getBoundsForVerticesInLayoutSpace(viewer, list); - bounds = GraphViewerUtils.translateRectangleFromLayoutSpaceToViewSpace(viewer, bounds); - - DockableComponent dockableComponent = getDockableComponent(viewer); - bounds = SwingUtilities.convertRectangle(viewer, bounds, dockableComponent); - - // - // Put a buffer space around the area - // - Rectangle area = new Rectangle(bounds); - int offset = 20; - area.x -= offset; - area.y -= offset; - area.width += (2 * offset); - area.height += (2 * offset); - screen.crop(area); - } - - private void cropAndKeepMessageSection() { - int imageWidth = screen.image.getWidth(null); - int imageHeight = screen.image.getHeight(null); - - // keep about 100 pixels of display to get the message area and a bit above - Rectangle area = new Rectangle(); - area.x = 0; - area.y = imageHeight - 120; - area.width = imageWidth; - area.height = 120; - screen.crop(area); - } - - private void go(String address) { - goToAddress(address); - } - - private void centerDisplay() { - FunctionGraph functionGraph = getFunctionGraph(); - FGVertex v = functionGraph.getRootVertex(); - setVertexToCenterTop(v); - } - - private void moveGraphToUpperLeftCorner(final FGVertex anchorVertex) { - waitForBusyGraph(); - - runSwing(() -> { - FGPrimaryViewer viewer = getPrimaryGraphViewer(); - Point p = getOffsetFromUpperLeftForVertexInLayoutSpace(viewer, anchorVertex); - moveViewerLocationWithoutAnimation(p); - }); - } - - private void moveGraphToUpperLeftCorner() { - waitForBusyGraph(); - - final FunctionGraph functionGraph = getFunctionGraph(); - runSwing(() -> { - FGController controller = getFunctionGraphController(); - FGView view = controller.getView(); - VisualizationViewer viewer = view.getPrimaryGraphViewer(); - - FunctionGraph graph = functionGraph; - Collection vertices = graph.getVertices(); - Rectangle layoutBounds = - GraphViewerUtils.getBoundsForVerticesInLayoutSpace(viewer, vertices); - Rectangle viewBounds = - GraphViewerUtils.translateRectangleFromLayoutSpaceToViewSpace(viewer, layoutBounds); - - Point location = viewBounds.getLocation(); - Point layoutPoint = getOffsetFromUpperLeftForViewPointInLayoutSpace(viewer, location); - - moveViewerLocationWithoutAnimation(layoutPoint); - }); - } - - private Point getOffsetFromUpperLeftForVertexInLayoutSpace( - VisualizationServer viewer, V vertex) { - - // - // We need an offset from the current vertex to the center top of the viewer - // - Rectangle vertexBoundsInViewSpace = - GraphViewerUtils.getVertexBoundsInViewSpace(viewer, vertex); - Point vertexLocationInViewSpace = vertexBoundsInViewSpace.getLocation(); - - // this padding is enough to not see the edges for most operations--it can be increased - int xWithPadding = 20; - int yWithPadding = 20; - Double point = new Point2D.Double(xWithPadding, yWithPadding);// upper, left - - Point vertexPointInLayoutSpace = GraphViewerUtils.translatePointFromViewSpaceToLayoutSpace( - vertexLocationInViewSpace, viewer); - Point upperLeftInLayoutSpace = - GraphViewerUtils.translatePointFromViewSpaceToLayoutSpace(point, viewer); - - double offsetX = upperLeftInLayoutSpace.getX() - vertexPointInLayoutSpace.getX(); - double offsetY = upperLeftInLayoutSpace.getY() - vertexPointInLayoutSpace.getY(); - return new Point((int) offsetX, (int) offsetY); - } - - private Point getOffsetFromUpperLeftForViewPointInLayoutSpace( - VisualizationServer viewer, Point viewPoint) { - - // this padding is enough to not see the edges for most operations--it can be increased - int xWithPadding = 50; - int yWithPadding = 50; - Double offsetPoint = new Point2D.Double(xWithPadding, yWithPadding);// upper, left - - Point vertexPointInLayoutSpace = - GraphViewerUtils.translatePointFromViewSpaceToLayoutSpace(viewPoint, viewer); - Point viewOffsetPointInLayoutSpace = - GraphViewerUtils.translatePointFromViewSpaceToLayoutSpace(offsetPoint, viewer); - - double offsetX = viewOffsetPointInLayoutSpace.getX() - vertexPointInLayoutSpace.getX(); - double offsetY = viewOffsetPointInLayoutSpace.getY() - vertexPointInLayoutSpace.getY(); - return new Point((int) offsetX, (int) offsetY); - } - - private void isolateProvider() { - ComponentProvider provider = tool.getWindowManager().getComponentProvider(FGProvider.class); - screen.moveProviderToItsOwnWindow(provider); - } - - private void setSize(final int width, final int height) { - this.width = width; - this.height = height; - - final ComponentProvider provider = - tool.getWindowManager().getComponentProvider(FGProvider.class); - runSwing(() -> { - Window window = tool.getWindowManager().getProviderWindow(provider); - if (window == null) { - throw new AssertException("Could not find window for " + - "provider--is it showing?: " + provider.getName()); - } - - window.setSize(new Dimension(width, height)); - }); - } - - private void captureProvider() { - screen.captureIsolatedProvider(FGProvider.class, width, height); - } - - private void captureProviderWindow() { - screen.captureIsolatedProviderWindow(FGProvider.class, width, height); - } - - private void cropAndRemoveHeader(int w, int h) { - int imageWidth = screen.image.getWidth(null); - int x = (imageWidth / 2) - (w / 2); - int y = 20;// down a bit from the top - Rectangle newBounds = new Rectangle(x, y, w, h); - screen.crop(newBounds); - } - - private void createUndefinedFunction() { - String address = "00401c25"; - go(address); - - DeleteFunctionCmd cmd = new DeleteFunctionCmd(getAddress(address)); - int id = program.startTransaction("Test"); - try { - cmd.applyTo(program); - } - finally { - program.endTransaction(id, true); - } - } - - @Override - protected GroupedFunctionGraphVertex group(String groupName, FGVertex... vertices) { - - HashSet set = new HashSet<>(); - for (FGVertex v : vertices) { - set.add(v); - } - - pickVertices(set); - GroupedFunctionGraphVertex groupVertex = group(set, groupName); - - // for debugging - if (groupName != null) { - Object componentPanel = getComponent(groupVertex); - setInstanceField("title", componentPanel, groupName); - } - - return groupVertex; - } - - @Override - protected GroupedFunctionGraphVertex group(Set ungroupedVertices, - final String groupVertexText) { - // execute the group action - FGVertex aVertex = ungroupedVertices.iterator().next(); - JComponent component = getComponent(aVertex); - DockingAction action = (DockingAction) TestUtils.getInstanceField("groupAction", component); - performAction(action, graphProvider, false); - waitForAnimation(); - - final MultiLineInputDialog dialog = - waitForDialogComponent(tool.getToolFrame(), MultiLineInputDialog.class, 3000); - if (groupVertexText != null) { - final JTextArea inputTextArea = (JTextArea) getInstanceField("inputTextArea", dialog); - runSwing(() -> inputTextArea.setText(groupVertexText)); - } - - pressButtonByText(dialog.getComponent(), "OK"); - - if (groupVertexText != null) { - String value = dialog.getValue(); - assertEquals("Group vertex text was not set in the dialog", groupVertexText, value); - } - - waitForAnimation(); - - FGController controller = getFunctionGraphController(); - FGData data = controller.getFunctionGraphData(); - FunctionGraph fg = data.getFunctionGraph(); - return getGroupVertex(fg, aVertex.getVertexAddress()); - } - - private DialogComponentProvider showGroupTextDialog(FGVertex... vertices) { - HashSet set = new HashSet<>(); - for (FGVertex v : vertices) { - set.add(v); - } - - pickVertices(set); - - FGVertex aVertex = vertices[0]; - JComponent component = getComponent(aVertex); - DockingAction action = (DockingAction) TestUtils.getInstanceField("groupAction", component); - performAction(action, graphProvider, false); - waitForAnimation(); - - return waitForDialogComponent(tool.getToolFrame(), MultiLineInputDialog.class, 3000); - } - - @Override - protected GroupedFunctionGraphVertex getGroupVertex(FunctionGraph functionGraph, - Address address) { - FGVertex vertex = functionGraph.getVertexForAddress(address); - if (!(vertex instanceof GroupedFunctionGraphVertex)) { - if (vertex == null) { - Msg.debug(this, "Null vertex for address " + address + ". All vertices: "); - Collection vertices = functionGraph.getVertices(); - for (FGVertex v : vertices) { - Msg.debug(this, "\t" + v); - } - } - - Assert.fail("Did not find group vertex at " + address + ". Instead found " + vertex); - } - return (GroupedFunctionGraphVertex) vertex; - } - - private void pickVertices(FGVertex... vertices) { - pickVertices(new HashSet<>(Arrays.asList(vertices))); - } - - private void pickVertices(final Set vertices) { - runSwing(() -> { - PickedState pickedState = getPickedState(); - pickedState.clear(); - - for (FGVertex vertex : vertices) { - pickedState.pick(vertex, true); - } - }); - } - - private PickedState getPickedState() { - FGComponent functionGraphViewer = getGraphComponent(); - VisualizationViewer primaryViewer = - functionGraphViewer.getPrimaryViewer(); - return primaryViewer.getPickedVertexState(); - } - - private JComponent getComponent(final FGVertex vertex) { - final AtomicReference reference = new AtomicReference<>(); - runSwing(() -> reference.set(vertex.getComponent())); - return reference.get(); - } - - private void setNestedLayout() { - - Object actionManager = getInstanceField("actionManager", graphProvider); - @SuppressWarnings("unchecked") - final MultiStateDockingAction> action = - (MultiStateDockingAction>) getInstanceField( - "layoutAction", actionManager); - runSwing(() -> { - List>> states = - action.getAllActionStates(); - for (ActionState> state : states) { - Class layoutClass = state.getUserData(); - if (layoutClass.getSimpleName().equals("DecompilerNestedLayoutProvider")) { - action.setCurrentActionState(state); - return; - } - } - - throw new RuntimeException("Could not find layout!!"); - }); - } - - private void createGroupButtonCallout_PlayArea(final FGVertex v, final String imageName) { - - FGProvider provider = screen.getProvider(FGProvider.class); - Window window = windowForComponent(provider.getComponent()); - final JDialog dialog = new JDialog(window); - dialog.setModal(true); - - JPanel panel = new JPanel(new BorderLayout()); - JButton button = new JButton("Repaint"); - button.addActionListener(e -> new Thread() { - @Override - public void run() { - Thread.currentThread().setName("Show Image[" + System.identityHashCode(this) + "]"); - - createGroupButtonCallout(v); - screen.saveOrDisplayImage(imageName); - } - }.start()); - - JButton closeButton = new JButton("Close"); - closeButton.addActionListener(e -> dialog.setVisible(false)); - - panel.add(button); - panel.add(closeButton, BorderLayout.SOUTH); - dialog.getContentPane().add(panel); - - dialog.setSize(300, 200); - dialog.setLocation(1300, 100); - dialog.setVisible(true); - } - - @SuppressWarnings("rawtypes") - private void setLayout() { - long start = System.currentTimeMillis(); - Object actionManager = getInstanceField("actionManager", graphProvider); - final MultiStateDockingAction action = - (MultiStateDockingAction) getInstanceField("layoutAction", actionManager); - - Object minCrossState = null; - List states = action.getAllActionStates(); - for (Object state : states) { - if (((ActionState) state).getName().indexOf("Min Cross") != -1) { - minCrossState = state; - break; - } - } - - assertNotNull("Could not find min cross layout!", minCrossState); - - //@formatter:off - invokeInstanceMethod( "setCurrentActionState", - action, - new Class[] { ActionState.class }, - new Object[] { minCrossState }); - //@formatter:on - - runSwing(() -> action.actionPerformed(new ActionContext())); - - // wait for the threaded graph layout code - FGController controller = getFunctionGraphController(); - waitForBusyRunManager(controller); - waitForAnimation(); - getPrimaryGraphViewer().repaint(); - waitForPostedSwingRunnables(); - - long end = System.currentTimeMillis(); - Msg.debug(this, "relayout time: " + ((end - start) / 1000.0) + "s"); - } - -//================================================================================================== -// Inner Classes -//================================================================================================== - - private class MyScreen extends GhidraScreenShotGenerator { - - public MyScreen() { - super(); - } - - @Override - public void loadProgram() { - // do nothing, we will put our own copy inside the screen - } - - @Override - // overridden so that we use the outer class's name when finding the help topic - protected File getHelpTopic() { - Class clazz = FunctionGraphPluginScreenShots.class; - String simpleName = clazz.getSimpleName(); - simpleName = simpleName.replace("ScreenShots", ""); - File helpTopicDir = getHelpTopicDir(simpleName); - assertNotNull("Unable to find help topic for test file: " + clazz.getName(), - helpTopicDir); - return helpTopicDir; - } - } - - private class FGCalloutComponentInfo extends CalloutComponentInfo { - - private VisualizationViewer viewer; - private FGVertex vertex; - - FGCalloutComponentInfo(Component destinationComponent, Component component, - Point locationOnScreen, Point relativeLocation, Dimension size, - VisualizationViewer viewer, FGVertex vertex) { - - super(destinationComponent, component, locationOnScreen, relativeLocation, size); - this.viewer = viewer; - this.vertex = vertex; - } - - @Override - public Point convertPointToParent(Point location) { - // TODO: this won't work for now if the graph is scaled. This is because there is - // point information that is calculated by the client of this class that does - // not take into account the scaling of the graph. This is a known issue-- - // don't use this class when the graph is scaled. - return location; - } - } -} diff --git a/Ghidra/Test/IntegrationTest/build.gradle b/Ghidra/Test/IntegrationTest/build.gradle index f962f11fc3..628c2f7e6c 100644 --- a/Ghidra/Test/IntegrationTest/build.gradle +++ b/Ghidra/Test/IntegrationTest/build.gradle @@ -29,6 +29,8 @@ dependencies { // some tests use classes in Base/src/test and test.slow testCompile project(path: ':Base', configuration: 'testArtifacts') + compile project(path: ':Base', configuration: 'integrationTestArtifacts') + compile project(path: ':FunctionGraph', configuration: 'testArtifacts') } // For Java 9, we must explicitly export references to the internal classes we are using. diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java index 24ce6177ab..b8bc7586e4 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/RepositoryScreenShots.java @@ -15,8 +15,7 @@ */ package help.screenshot; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; import java.awt.*; import java.math.BigInteger; @@ -25,8 +24,7 @@ import java.util.List; import javax.swing.*; import javax.swing.border.TitledBorder; -import org.junit.Assert; -import org.junit.Test; +import org.junit.*; import docking.widgets.indexedscrollpane.IndexedScrollPane; import generic.test.TestUtils; @@ -69,7 +67,7 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { super(); } - // FIXME: JUnit4 ?? + @Before @Override public void setUp() throws Exception { super.setUp(); @@ -78,7 +76,7 @@ public class RepositoryScreenShots extends AbstractListingMergeManagerTest { env = mtf.getTestEnvironment(); } - // FIXME: JUnit4 ?? + @After @Override public void tearDown() throws Exception { mtfGenerator.showResults(); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java index 8057736af8..a98f5e8b98 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/test/FrontEndTestEnv.java @@ -339,6 +339,10 @@ public class FrontEndTestEnv { return new ArrayList<>(Arrays.asList(tools)); } + public Set getFrontEndActions() { + return AbstractDockingTest.getActionsByOwner(frontEndTool, "FrontEndPlugin"); + } + public DockingActionIf getAction(String actionName) { DockingActionIf action = AbstractDockingTest.getAction(frontEndTool, "FrontEndPlugin", actionName); @@ -409,7 +413,7 @@ public class FrontEndTestEnv { waitForTasks(); } - protected void editProgram(Program program, ModifyProgramCallback modifyProgramCallback) + public void editProgram(Program program, ModifyProgramCallback modifyProgramCallback) throws CancelledException, IOException { int transactionID = program.startTransaction("test"); try { @@ -424,7 +428,7 @@ public class FrontEndTestEnv { } } - protected void editProgram(DomainFile df, Object consumer, ModifyProgramCallback edit) + public void editProgram(DomainFile df, Object consumer, ModifyProgramCallback edit) throws Exception { Program program = (Program) df.getDomainObject(this, true, false, TaskMonitor.DUMMY); @@ -438,7 +442,7 @@ public class FrontEndTestEnv { } } - interface ModifyProgramCallback { + public interface ModifyProgramCallback { public void call(Program p) throws Exception; } } diff --git a/gradle/javaProject.gradle b/gradle/javaProject.gradle index 309fd5b7e4..265f061b26 100644 --- a/gradle/javaProject.gradle +++ b/gradle/javaProject.gradle @@ -79,8 +79,8 @@ sourceSets { screenShots { java { srcDir 'src/screen/java' - compileClasspath += main.output - runtimeClasspath += main.output + compileClasspath += main.output + test.output + integrationTest.output + runtimeClasspath += main.output + test.output + integrationTest.output } } pcodeTest { @@ -107,6 +107,7 @@ configurations { pcodeTestCompile.extendsFrom compile testArtifacts.extendsFrom testRuntime integrationTestArtifacts.extendsFrom integrationTestRuntime + screenShotsCompile.extendsFrom integrationTestCompile } task testJar(type: Jar) {