GP-0 Moved most graph tests into integration tests. Corrected failing

graph tests
This commit is contained in:
ghidra1
2021-05-20 16:21:24 -04:00
parent 70675fce99
commit 7c11bb5751
15 changed files with 132 additions and 392 deletions
@@ -1,348 +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 ghidra.graph.export;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.junit.*;
import ghidra.app.plugin.core.blockmodel.BlockModelServicePlugin;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.plugin.core.graph.GraphDisplayBrokerPlugin;
import ghidra.app.services.BlockModelService;
import ghidra.app.services.GraphDisplayBroker;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginException;
import ghidra.graph.exporter.*;
import ghidra.program.database.ProgramDB;
import ghidra.service.graph.*;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.test.TestEnv;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
import utilities.util.FileUtilities;
public class GraphExportTest extends AbstractGhidraHeadedIntegrationTest {
protected PluginTool tool;
protected ProgramDB program;
protected TestEnv env;
protected BlockModelService blockModelService;
protected CodeBrowserPlugin codeBrowser;
private GraphExporterDialog dialog;
@Before
public void setUp() throws Exception {
setErrorGUIEnabled(false);
env = new TestEnv();
tool = env.getTool();
initializeTool();
GraphDisplayBroker broker = tool.getService(GraphDisplayBroker.class);
GraphDisplayProvider exportProvider = broker.getGraphDisplayProvider("Graph Export");
AttributedGraph graph = createGraph();
GraphDisplay exporter = exportProvider.getGraphDisplay(false, TaskMonitor.DUMMY);
// run in swing so the test is not blocked when we mess with the dialog.
runSwing(() -> setGraph(graph, exporter), false);
waitForSwing();
}
private void setGraph(AttributedGraph graph, GraphDisplay exporter) {
try {
exporter.setGraph(graph, "Test", false, TaskMonitor.DUMMY);
}
catch (CancelledException e) {
// can't happen with dummy
}
}
@After
public void tearDown() {
env.dispose();
}
@Test
public void testCSV() throws Exception {
List<String> lines = processDialog(new CsvEdgeListGraphExporter());
assertOutput(lines,
"A,B",
"B,C",
"B,D",
"C,E",
"D,E");
}
@Test
public void testDIMACS() throws Exception {
List<String> lines = processDialog(new DimacsGraphExporter());
assertOutput(lines,
"c",
"c SOURCE: Generated using the JGraphT library",
"c",
"p edge 5 5",
"e A B",
"e B C",
"e B D",
"e C E",
"e D E");
}
@Test
public void testDOT() throws Exception {
List<String> lines = processDialog(new DotGraphExporter());
assertOutput(lines,
"digraph Ghidra {",
" \"A\" [ Type=\"X\" Inverted=\"true\" Name=\"A\" ];",
" \"B\" [ Type=\"Y\" Name=\"B\" ];",
" \"C\" [ Type=\"Y\" Name=\"C\" ];",
" \"D\" [ Type=\"Y\" Name=\"D\" ];",
" \"E\" [ Type=\"Z\" Name=\"E\" ];",
" \"A\" -> \"B\" [ EType=\"Fall\" ];",
" \"B\" -> \"C\" [ EType=\"JMP\" ];",
" \"B\" -> \"D\" [ EType=\"Fall\" ];",
" \"C\" -> \"E\" [ EType=\"Fall\" ];",
" \"D\" -> \"E\" [ EType=\"Call\" ];",
"}");
}
@Test
public void testGML() throws Exception {
List<String> lines = processDialog(new GmlGraphExporter());
assertOutput(lines,
"Creator \"JGraphT GML Exporter\"",
"Version 1",
"graph",
"[",
" label \"\"",
" directed 1",
" node",
" [",
" id A",
" ]",
" node",
" [",
" id B",
" ]",
" node",
" [",
" id C",
" ]",
" node",
" [",
" id D",
" ]",
" node",
" [",
" id E",
" ]",
" edge",
" [",
" id 1",
" source A",
" target B",
" ]",
" edge",
" [",
" id 2",
" source B",
" target C",
" ]",
" edge",
" [",
" id 3",
" source B",
" target D",
" ]",
" edge",
" [",
" id 4",
" source C",
" target E",
" ]",
" edge",
" [",
" id 5",
" source D",
" target E",
" ]",
"]");
}
@Test
public void testGRAPHML() throws Exception {
List<String> lines = processDialog(new GraphMlGraphExporter());
assertOutput(lines,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">",
" <graph edgedefault=\"directed\">",
" <node id=\"A\"/>",
" <node id=\"B\"/>",
" <node id=\"C\"/>",
" <node id=\"D\"/>",
" <node id=\"E\"/>",
" <edge id=\"1\" source=\"A\" target=\"B\"/>",
" <edge id=\"2\" source=\"B\" target=\"C\"/>",
" <edge id=\"3\" source=\"B\" target=\"D\"/>",
" <edge id=\"4\" source=\"C\" target=\"E\"/>",
" <edge id=\"5\" source=\"D\" target=\"E\"/>",
" </graph>",
"</graphml>");
}
@Test
public void testJSON() throws Exception {
List<String> lines = processDialog(new JsonGraphExporter());
assertOutput(lines,
"{\"creator\":\"JGraphT JSON Exporter\",\"version\":\"1\",\"nodes\":" +
"[{\"id\":\"A\",\"Type\":\"X\",\"Inverted\":\"true\",\"Name\":\"A\"}," +
"{\"id\":\"B\",\"Type\":\"Y\",\"Name\":\"B\"}," +
"{\"id\":\"C\",\"Type\":\"Y\",\"Name\":\"C\"}," +
"{\"id\":\"D\",\"Type\":\"Y\",\"Name\":\"D\"}," +
"{\"id\":\"E\",\"Type\":\"Z\",\"Name\":\"E\"}]," +
"\"edges\":[{\"id\":\"1\",\"source\":\"A\",\"target\":\"B\",\"EType\":\"Fall\"}," +
"{\"id\":\"2\",\"source\":\"B\",\"target\":\"C\",\"EType\":\"JMP\"}," +
"{\"id\":\"3\",\"source\":\"B\",\"target\":\"D\",\"EType\":\"Fall\"}," +
"{\"id\":\"4\",\"source\":\"C\",\"target\":\"E\",\"EType\":\"Fall\"}," +
"{\"id\":\"5\",\"source\":\"D\",\"target\":\"E\",\"EType\":\"Call\"}]}");
}
@Test
public void testMATRIX() throws Exception {
List<String> lines = processDialog(new MatrixGraphExporter());
assertOutput(lines,
"A B 1",
"B C 1",
"B D 1",
"C E 1",
"D E 1");
}
@Test
public void testVISIO() throws Exception {
List<String> lines = processDialog(new VisioGraphExporter());
assertOutput(lines,
"Shape,A,,A",
"Shape,B,,B",
"Shape,C,,C",
"Shape,D,,D",
"Shape,E,,E",
"Link,A-->B,,,A,B",
"Link,B-->C,,,B,C",
"Link,B-->D,,,B,D",
"Link,C-->E,,,C,E",
"Link,D-->E,,,D,E");
}
protected void initializeTool() throws Exception {
installPlugins();
showTool(tool);
}
protected void installPlugins() throws PluginException {
tool.addPlugin(BlockModelServicePlugin.class.getName());
tool.addPlugin(GraphDisplayBrokerPlugin.class.getName());
}
private List<String> processDialog(AttributedGraphExporter exporter) throws IOException {
dialog = getDialogComponent(GraphExporterDialog.class);
String filePath =
createTempFilePath("GraphExportTest", "." + exporter.getFileExtension());
runSwing(() -> dialog.setOutputFile(filePath));
dialog.setExporter(exporter);
pressButtonByText(dialog, "OK");
List<String> lines = FileUtilities.getLines(new File(filePath));
return lines;
}
private AttributedGraph createGraph() {
AttributedGraph graph = new AttributedGraph();
AttributedVertex vA = graph.addVertex("A");
AttributedVertex vB = graph.addVertex("B");
AttributedVertex vC = graph.addVertex("C");
AttributedVertex vD = graph.addVertex("D");
AttributedVertex vE = graph.addVertex("E");
// A
// |
// B
// / \
// C D
// \ /
// E
AttributedEdge e1 = graph.addEdge(vA, vB);
AttributedEdge e2 = graph.addEdge(vB, vC);
AttributedEdge e3 = graph.addEdge(vB, vD);
AttributedEdge e4 = graph.addEdge(vC, vE);
AttributedEdge e5 = graph.addEdge(vD, vE);
vA.setAttribute("Type", "X");
vB.setAttribute("Type", "Y");
vC.setAttribute("Type", "Y");
vD.setAttribute("Type", "Y");
vE.setAttribute("Type", "Z");
e1.setAttribute("EType", "Fall");
e2.setAttribute("EType", "JMP");
e3.setAttribute("EType", "Fall");
e4.setAttribute("EType", "Fall");
e5.setAttribute("EType", "Call");
vA.setAttribute("Inverted", "true");
return graph;
}
private void printLines(List<String> lines) {
Msg.debug(this, "\n" + testName.getMethodName());
for (String line : lines) {
Msg.debug(this, "\"" + line + "\",");
}
}
private void assertOutput(List<String> actual, String... expected) {
try {
for (int i = 0; i < expected.length; i++) {
if (i >= actual.size()) {
fail(testName.getMethodName() + ": output line " + (i + 1) + ": expected :\"" +
expected[i] +
"\", got: EOF");
}
assertEquals(testName.getMethodName() + ": output line " + (i + 1) + ": ",
expected[i],
actual.get(i));
}
}
catch (Throwable e) {
printLines(actual);
throw e;
}
}
}
@@ -0,0 +1,251 @@
/* ###
* 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 ghidra.app.plugin.core.datamgr.actions;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import ghidra.graph.TestGraphDisplay;
import ghidra.graph.TestGraphService;
import ghidra.program.model.data.*;
import ghidra.service.graph.*;
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
import ghidra.util.exception.GraphException;
import ghidra.util.task.Task;
import ghidra.util.task.TaskMonitor;
public class TypeGraphTaskTest extends AbstractGhidraHeadedIntegrationTest {
private Structure base;
private Structure other;
private Pointer pointer;
private Pointer otherPointer;
private TypeDef otherTypeDef;
private TestGraphService graphService;
@Before
public void setUp() throws Exception {
base = new StructureDataType("base structure", 16);
base.insert(0, new IntegerDataType());
other = new StructureDataType("another struct", 20);
other.insert(0, new IntegerDataType());
other.insert(1, new FloatDataType());
pointer = new PointerDataType(new IntegerDataType());
otherPointer = new PointerDataType(other);
otherTypeDef = new TypedefDataType("other_t", other);
graphService = new TestGraphService();
}
@Test
public void testSimpleStructure() throws GraphException {
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(1, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
}
@Test
public void testNestedStructure() throws GraphException {
base.insert(1, other);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.EMBEDDED, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testStructureWithPointer() throws GraphException {
base.insert(1, pointer);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(1, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
}
@Test
public void testPointerToStructure() throws GraphException {
base.insert(1, otherPointer);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.POINTER, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testEmbeddedAndPointer() throws GraphException {
base.insert(1, other);
base.insert(2, pointer);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.EMBEDDED, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testPointerToPointer() throws GraphException {
Pointer pointerToPointer = new PointerDataType(otherPointer);
base.insert(1, pointerToPointer);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.POINTER, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testEmbeddedTypedef() throws GraphException {
base.insert(1, otherTypeDef);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.EMBEDDED, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testPointerToTypedef() throws GraphException {
Pointer typedefPtr = new PointerDataType(otherTypeDef);
base.insert(1, typedefPtr);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
assertEquals(TypeGraphTask.POINTER, e1.getAttribute(TypeGraphTask.TYPE_ATTRIBUTE));
}
@Test
public void testPointerToSelf() throws GraphException {
Pointer selfPtr = new PointerDataType(base);
base.insert(1, selfPtr);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(1, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedEdge e1 = graph.getEdge(v1, v1);
assertNotNull(e1);
}
@Test
public void testPointerCycle() throws GraphException {
base.insert(1, otherPointer);
Pointer basePtr = new PointerDataType(base);
other.insert(1, basePtr);
Task task = new TypeGraphTask(base, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(base.getName());
assertNotNull(v1);
AttributedVertex v2 = graph.getVertex(other.getName());
assertNotNull(v2);
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
AttributedEdge e2 = graph.getEdge(v2, v1);
assertNotNull(e2);
}
}
@@ -0,0 +1,143 @@
/* ###
* 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 ghidra.graph;
import java.util.*;
import docking.action.DockingActionIf;
import docking.widgets.EventTrigger;
import ghidra.service.graph.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class TestGraphDisplay implements GraphDisplay {
private Set<String> definedVertexAttributes = new HashSet<>();
private Set<String> definedEdgeAttributes = new HashSet<>();
private AttributedGraph graph;
private String title;
private GraphDisplayListener listener;
private AttributedVertex focusedVertex;
private Set<AttributedVertex> currentSelection;
@Override
public void setGraphDisplayListener(GraphDisplayListener listener) {
this.listener = listener;
}
@Override
public void setFocusedVertex(AttributedVertex vertex, EventTrigger eventTrigger) {
focusedVertex = vertex;
}
@Override
public AttributedVertex getFocusedVertex() {
return focusedVertex;
}
@Override
public void selectVertices(Set<AttributedVertex> vertexList, EventTrigger eventTrigger) {
currentSelection = vertexList;
}
@Override
public Set<AttributedVertex> getSelectedVertices() {
return currentSelection;
}
@Override
public void close() {
// nothing
}
@Override
public void defineVertexAttribute(String name) {
definedVertexAttributes.add(name);
}
@Override
public void defineEdgeAttribute(String name) {
definedEdgeAttributes.add(name);
}
@Override
public void setVertexLabelAttribute(String attributeName, int alignment, int size,
boolean monospace,
int maxLines) {
// nothing
}
@Override
public void setGraph(AttributedGraph graph, String title, boolean append,
TaskMonitor monitor)
throws CancelledException {
if (append) {
this.graph = mergeGraphs(graph, this.graph);
}
else {
this.graph = graph;
}
this.title = title;
}
@Override
public void clear() {
// nothing
}
@Override
public void updateVertexName(AttributedVertex vertex, String newName) {
// nothing
}
@Override
public String getGraphTitle() {
return title;
}
@Override
public AttributedGraph getGraph() {
return graph;
}
public void focusChanged(AttributedVertex vertex) {
listener.locationFocusChanged(vertex);
}
public void selectionChanged(Set<AttributedVertex> vertices) {
listener.selectionChanged(vertices);
}
@Override
public void addAction(DockingActionIf action) {
// do nothing, actions are not supported by this display
}
private AttributedGraph mergeGraphs(AttributedGraph newGraph, AttributedGraph oldGraph) {
for (AttributedVertex vertex : oldGraph.vertexSet()) {
newGraph.addVertex(vertex);
}
for (AttributedEdge edge : oldGraph.edgeSet()) {
AttributedVertex from = oldGraph.getEdgeSource(edge);
AttributedVertex to = oldGraph.getEdgeTarget(edge);
AttributedEdge newEdge = newGraph.addEdge(from, to);
Map<String, String> attributeMap = edge.getAttributeMap();
for (String key : attributeMap.keySet()) {
newEdge.setAttribute(key, edge.getAttribute(key));
}
}
return newGraph;
}
}
@@ -0,0 +1,62 @@
/* ###
* 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 ghidra.graph;
import ghidra.framework.options.Options;
import ghidra.framework.plugintool.PluginTool;
import ghidra.service.graph.GraphDisplay;
import ghidra.service.graph.GraphDisplayProvider;
import ghidra.util.HelpLocation;
import ghidra.util.exception.GraphException;
import ghidra.util.task.TaskMonitor;
public class TestGraphService implements GraphDisplayProvider {
private TestGraphDisplay testDisplay = new TestGraphDisplay();
@Override
public String getName() {
return "Test Graph Service";
}
@Override
public GraphDisplay getGraphDisplay(boolean reuseGraph,
TaskMonitor monitor) throws GraphException {
return testDisplay;
}
@Override
public void initialize(PluginTool tool, Options options) {
// nothing
}
@Override
public void optionsChanged(Options options) {
// nothing
}
@Override
public void dispose() {
// nothing
}
@Override
public HelpLocation getHelpLocation() {
return null;
}
}
@@ -0,0 +1,139 @@
/* ###
* 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 ghidra.graph.program;
import org.junit.After;
import org.junit.Before;
import ghidra.app.plugin.core.blockmodel.BlockModelServicePlugin;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.services.BlockModelService;
import ghidra.app.services.ProgramManager;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginException;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.test.*;
public class AbstractBlockGraphTest extends AbstractGhidraHeadedIntegrationTest {
protected static final String CALLER_FUNCTION_ADDRESS = "01002200";
protected static final String SIMPLE_FUNCTION_ADDRESS = "01002239";
protected PluginTool tool;
protected ProgramDB program;
protected TestEnv env;
protected BlockModelService blockModelService;
private ToyProgramBuilder builder;
protected CodeBrowserPlugin codeBrowser;
@Before
public void setUp() throws Exception {
setErrorGUIEnabled(false);
env = new TestEnv();
tool = env.getTool();
initializeTool();
}
@After
public void tearDown() {
env.dispose();
}
protected void initializeTool() throws Exception {
installPlugins();
openProgram();
ProgramManager pm = tool.getService(ProgramManager.class);
pm.openProgram(program.getDomainFile());
showTool(tool);
blockModelService = tool.getService(BlockModelService.class);
}
protected void installPlugins() throws PluginException {
tool.addPlugin(CodeBrowserPlugin.class.getName());
tool.addPlugin(BlockModelServicePlugin.class.getName());
codeBrowser = env.getPlugin(CodeBrowserPlugin.class);
}
protected void openProgram() throws Exception {
builder = new ToyProgramBuilder("sample", true);
builder.createMemory("caller", "0x01002200", 8);
builder.createMemory("simple", "0x01002239", 8);
builder.createMemory("not_graphed", "0x01002300", 8);
buildCallerFunction();
buildSimpleFunction();
program = builder.getProgram();
}
private void buildCallerFunction() throws MemoryAccessException {
// just a function that calls another
builder.addBytesNOP("0x01002200", 1);
builder.addBytesCall("0x01002201", "0x01002239");// jump to C
builder.addBytesReturn("0x01002203");
builder.disassemble("0x01002200", 4, true);
builder.createFunction("0x01002200");
builder.createLabel("0x01002200", "entry");// function label
}
private void buildSimpleFunction() throws MemoryAccessException {
// just a function to render in the graph so that we can clear out settings/cache
// 01002239
/*
A
|->B
C
*/
// A
builder.addBytesNOP("0x01002239", 1);
builder.addBytesBranchConditional("0x0100223a", "0x0100223e");// jump to C
// B
builder.addBytesNOP("0x0100223c", 1);
builder.addBytesNOP("0x0100223d", 1);// fallthrough to C
// C
builder.addBytesNOP("0x0100223e", 1);
builder.addBytesReturn("0x0100223f");
builder.disassemble("0x01002239", 8, true);
builder.createFunction("0x01002239");
builder.createLabel("0x01002239", "simple");// function label
}
protected Address addr(long addr) {
return builder.getAddress(addr);
}
protected Address addr(String addressString) {
return builder.addr(addressString);
}
}
@@ -0,0 +1,128 @@
/* ###
* 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 ghidra.graph.program;
import java.nio.charset.StandardCharsets;
import org.junit.After;
import org.junit.Before;
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
import ghidra.app.services.ProgramManager;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginException;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.data.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.SourceType;
import ghidra.test.*;
public class AbstractDataReferenceGraphTest extends AbstractGhidraHeadedIntegrationTest {
protected PluginTool tool;
protected ProgramDB program;
protected TestEnv env;
private ToyProgramBuilder builder;
protected CodeBrowserPlugin codeBrowser;
@Before
public void setUp() throws Exception {
setErrorGUIEnabled(false);
env = new TestEnv();
tool = env.getTool();
initializeTool();
}
@After
public void tearDown() {
env.dispose();
}
protected void initializeTool() throws Exception {
installPlugins();
openProgram();
ProgramManager pm = tool.getService(ProgramManager.class);
pm.openProgram(program.getDomainFile());
showTool(tool);
}
protected void installPlugins() throws PluginException {
tool.addPlugin(CodeBrowserPlugin.class.getName());
codeBrowser = env.getPlugin(CodeBrowserPlugin.class);
}
protected void openProgram() throws Exception {
builder = new ToyProgramBuilder("sample", true);
builder.createMemory("data", "0x01000000", 64);
builder.createMemory("caller", "0x01002200", 8);
buildFunction();
buildData();
program = builder.getProgram();
}
private void buildData() throws Exception {
builder.createString("0x01000000", "thing here", StandardCharsets.US_ASCII, true,
StringDataType.dataType);
builder.createMemoryReference("0x0100000c", "0x0100000f", RefType.DATA,
SourceType.ANALYSIS);
builder.createString("0x0100000f", "another thing", StandardCharsets.US_ASCII, true,
StringDataType.dataType);
builder.addDataType(IntegerDataType.dataType);
builder.createMemoryReference("0x01000021", "0x0100000c", RefType.DATA,
SourceType.ANALYSIS);
Structure pointerStructure = new StructureDataType("pointer_thing", 0);
pointerStructure.setPackingEnabled(true);
pointerStructure.add(IntegerDataType.dataType, "num", null);
pointerStructure.add(PointerDataType.dataType, "ptr", null);
builder.addDataType(pointerStructure);
builder.applyDataType("0x0100001d", pointerStructure);
}
private void buildFunction() throws MemoryAccessException {
// just a function that calls another
builder.createMemoryReference("0x1002200", "0x01000000", RefType.DATA, SourceType.ANALYSIS);
builder.addBytesCall("0x01002201", "0x01002239");// jump to C
builder.addBytesReturn("0x01002203");
builder.disassemble("0x01002200", 4, true);
builder.createFunction("0x01002200");
builder.createLabel("0x01002200", "entry");// function label
}
protected Address addr(long addr) {
return builder.getAddress(addr);
}
protected Address addr(String addressString) {
return builder.addr(addressString);
}
protected AddressSet addrSet(long start, long end) {
return new AddressSet(addr(start), addr(end));
}
}
@@ -0,0 +1,121 @@
/* ###
* 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 ghidra.graph.program;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import ghidra.app.events.ProgramSelectionPluginEvent;
import ghidra.graph.TestGraphDisplay;
import ghidra.graph.TestGraphService;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.block.CodeBlockModel;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.service.graph.AttributedGraph;
import ghidra.service.graph.AttributedVertex;
import ghidra.util.task.TaskMonitor;
public class BlockGraphEventTest extends AbstractBlockGraphTest {
private TestGraphDisplay display;
private AttributedGraph graph;
@Override
public void setUp() throws Exception {
super.setUp();
String modelName = blockModelService.getActiveBlockModelName();
CodeBlockModel model =
blockModelService.getNewModelByName(modelName, program, true);
TestGraphService graphService = new TestGraphService();
BlockGraphTask task =
new BlockGraphTask("test", false, false, false, false,
tool, null, null, model, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
display = (TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
graph = display.getGraph();
}
@Test
public void testGhidraLocationChanged() {
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002239)));
assertEquals("01002239", display.getFocusedVertex().getId());
codeBrowser.goTo(new ProgramLocation(program, addr(0x1002200)));
assertEquals("01002200", display.getFocusedVertex().getId());
// also try a location that is not the start of a block
codeBrowser.goTo(new ProgramLocation(program, addr(0x100223a)));
assertEquals("01002239", display.getFocusedVertex().getId());
}
private AddressSet addrSet(long start, long end) {
return new AddressSet(addr(start), addr(end));
}
@Test
public void testGhidraSelectionChanged() {
setSelection(addrSet(0x1002239, 0x1002241));
Set<AttributedVertex> selected = new HashSet<>(display.getSelectedVertices());
assertEquals(3, selected.size());
assertTrue(selected.contains(graph.getVertex("01002239")));
assertTrue(selected.contains(graph.getVertex("0100223c")));
assertTrue(selected.contains(graph.getVertex("0100223e")));
setSelection(new AddressSet(addr(0x1002200), addr(0x1002210)));
selected = new HashSet<>(display.getSelectedVertices());
assertEquals(2, selected.size());
assertTrue(selected.contains(graph.getVertex("01002200")));
assertTrue(selected.contains(graph.getVertex("01002203")));
}
@Test
public void testGraphNodeFocused() {
display.focusChanged(graph.getVertex("01002203"));
assertEquals(addr(0x01002203), codeBrowser.getCurrentLocation().getAddress());
display.focusChanged(graph.getVertex("0100223c"));
assertEquals(addr(0x0100223c), codeBrowser.getCurrentLocation().getAddress());
}
@Test
public void testGraphNodesSelected() {
display.selectionChanged(Set.of(graph.getVertex("01002239"), graph.getVertex("0100223c")));
ProgramSelection selection = codeBrowser.getCurrentSelection();
assertEquals(addr(0x01002239), selection.getMinAddress());
assertEquals(addr(0x0100223d), selection.getMaxAddress());
display.selectionChanged(Set.of(graph.getVertex("01002200"), graph.getVertex("01002203")));
selection = codeBrowser.getCurrentSelection();
assertEquals(addr(0x01002200), selection.getMinAddress());
assertEquals(addr(0x01002204), selection.getMaxAddress());
}
private void setSelection(final AddressSet addrSet) {
runSwing(
() -> tool.firePluginEvent(
new ProgramSelectionPluginEvent("test", new ProgramSelection(addrSet), program)),
true);
}
}
@@ -0,0 +1,236 @@
/* ###
* 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 ghidra.graph.program;
import static org.junit.Assert.*;
import java.util.Map;
import org.junit.Test;
import ghidra.graph.TestGraphDisplay;
import ghidra.graph.TestGraphService;
import ghidra.program.model.block.CodeBlockModel;
import ghidra.program.util.ProgramSelection;
import ghidra.service.graph.*;
import ghidra.util.task.TaskMonitor;
public class BlockGraphTaskTest extends AbstractBlockGraphTest {
private static final boolean SHOW_CODE = true;
private static final boolean DONT_SHOW_CODE = false;
@Test
public void testBlockGraph() throws Exception {
String modelName = blockModelService.getActiveBlockModelName();
CodeBlockModel model =
blockModelService.getNewModelByName(modelName, program, true);
TestGraphService graphService = new TestGraphService();
BlockGraphTask task =
new BlockGraphTask("test", false, DONT_SHOW_CODE, false, false,
tool, null, null, model, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(5, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex("01002200");
AttributedVertex v2 = graph.getVertex("01002203");
AttributedVertex v3 = graph.getVertex("01002239");
AttributedVertex v4 = graph.getVertex("0100223c");
AttributedVertex v5 = graph.getVertex("0100223e");
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNotNull(v4);
assertNotNull(v5);
assertEquals(5, graph.getEdgeCount());
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v1, v3);
AttributedEdge e3 = graph.getEdge(v3, v4);
AttributedEdge e4 = graph.getEdge(v4, v5);
AttributedEdge e5 = graph.getEdge(v3, v5);
assertNotNull(e1);
assertNotNull(e2);
assertNotNull(e3);
assertNotNull(e4);
assertNotNull(e5);
Map<String, String> map = v1.getAttributeMap();
assertEquals(2, map.size());
assertTrue(map.containsKey("Name"));
assertTrue(map.containsKey("VertexType"));
assertEquals("Entry", v3.getAttribute("VertexType"));
assertEquals("Body", v4.getAttribute("VertexType"));
assertEquals("Exit", v5.getAttribute("VertexType"));
map = e1.getAttributeMap();
assertEquals(2, map.size());
assertTrue(map.containsKey("Name"));
assertTrue(map.containsKey("EdgeType"));
assertEquals("Fall-Through", e3.getAttribute("EdgeType"));
assertEquals("Fall-Through", e4.getAttribute("EdgeType"));
assertEquals("Conditional-Jump", e5.getAttribute("EdgeType"));
}
@Test
public void testCodeBlockGraph() throws Exception {
String modelName = blockModelService.getActiveBlockModelName();
CodeBlockModel model =
blockModelService.getNewModelByName(modelName, program, true);
TestGraphService graphService = new TestGraphService();
BlockGraphTask task =
new BlockGraphTask("test", false, SHOW_CODE, false, false,
tool, null, null, model, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(5, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex("01002200");
AttributedVertex v2 = graph.getVertex("01002203");
AttributedVertex v3 = graph.getVertex("01002239");
AttributedVertex v4 = graph.getVertex("0100223c");
AttributedVertex v5 = graph.getVertex("0100223e");
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNotNull(v4);
assertNotNull(v5);
assertEquals(5, graph.getEdgeCount());
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v1, v3);
AttributedEdge e3 = graph.getEdge(v3, v4);
AttributedEdge e4 = graph.getEdge(v4, v5);
AttributedEdge e5 = graph.getEdge(v3, v5);
assertNotNull(e1);
assertNotNull(e2);
assertNotNull(e3);
assertNotNull(e4);
assertNotNull(e5);
Map<String, String> map = v3.getAttributeMap();
assertEquals(4, map.size());
assertTrue(map.containsKey("Name"));
assertTrue(map.containsKey("VertexType"));
assertTrue(map.containsKey("Code"));
assertTrue(map.containsKey("Symbols"));
assertEquals("simple", v3.getAttribute("Symbols"));
assertEquals("nop #0x1\nbreq 0x0100223e", v3.getAttribute("Code"));
}
@Test
public void testCallGraph() throws Exception {
String modelName = blockModelService.getActiveSubroutineModelName();
CodeBlockModel model =
blockModelService.getNewModelByName(modelName, program, true);
TestGraphService graphService = new TestGraphService();
BlockGraphTask task =
new BlockGraphTask("test", false, false, false, false,
tool, null, null, model, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex("01002200");
AttributedVertex v2 = graph.getVertex("01002239");
assertNotNull(v1);
assertNotNull(v2);
assertEquals(1, graph.getEdgeCount());
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(e1);
Map<String, String> map = v1.getAttributeMap();
assertEquals(2, map.size());
assertTrue(map.containsKey("Name"));
assertTrue(map.containsKey("VertexType"));
assertEquals("Entry", v1.getAttribute("VertexType"));
assertEquals("Entry", v2.getAttribute("VertexType"));
map = e1.getAttributeMap();
assertEquals(2, map.size());
assertTrue(map.containsKey("Name"));
assertTrue(map.containsKey("EdgeType"));
assertEquals("Unconditional-Call", e1.getAttribute("EdgeType"));
}
@Test
public void testBlockGraphWithSelection() throws Exception {
String modelName = blockModelService.getActiveBlockModelName();
CodeBlockModel model =
blockModelService.getNewModelByName(modelName, program, true);
TestGraphService graphService = new TestGraphService();
ProgramSelection sel = new ProgramSelection(addr(0x1002239), addr(0x1002247));
BlockGraphTask task =
new BlockGraphTask("test", false, DONT_SHOW_CODE, false, false,
tool, sel, null, model, graphService);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
AttributedGraph graph = display.getGraph();
assertEquals(3, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex("01002200");
AttributedVertex v2 = graph.getVertex("01002203");
AttributedVertex v3 = graph.getVertex("01002239");
AttributedVertex v4 = graph.getVertex("0100223c");
AttributedVertex v5 = graph.getVertex("0100223e");
assertNull(v1);
assertNull(v2);
assertNotNull(v3);
assertNotNull(v4);
assertNotNull(v5);
assertEquals(3, graph.getEdgeCount());
AttributedEdge e3 = graph.getEdge(v3, v4);
AttributedEdge e4 = graph.getEdge(v4, v5);
AttributedEdge e5 = graph.getEdge(v3, v5);
assertNotNull(e3);
assertNotNull(e4);
assertNotNull(e5);
}
}
@@ -0,0 +1,116 @@
/* ###
* 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 ghidra.graph.program;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import ghidra.graph.TestGraphDisplay;
import ghidra.graph.TestGraphService;
import ghidra.program.model.address.AddressSet;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.service.graph.AttributedVertex;
import ghidra.util.task.TaskMonitor;
public class DataReferenceGraphEventTest extends AbstractDataReferenceGraphTest {
private TestGraphDisplay display;
private DataReferenceGraph graph;
@Override
public void setUp() throws Exception {
super.setUp();
TestGraphService graphService = new TestGraphService();
ProgramLocation location = new ProgramLocation(program, addr(0x01000000));
// env.showTool(program);
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null, location,
graphService, 0, 10, DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
display = (TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph otherGraph = new DataReferenceGraph(program, 0);
otherGraph.graphFrom(addr(0x0100001d), DataReferenceGraph.Directions.BOTH_WAYS,
TaskMonitor.DUMMY);
display.setGraph(otherGraph, "testing", true, TaskMonitor.DUMMY);
graph = (DataReferenceGraph) display.getGraph();
}
@Test
public void testGhidraLocationChanged() {
codeBrowser.goTo(new ProgramLocation(program, addr(0x01002200)));
assertEquals("01002200",
display.getFocusedVertex().getAttribute(DataReferenceGraph.ADDRESS_ATTRIBUTE));
codeBrowser.goTo(new ProgramLocation(program, addr(0x1000000)));
assertEquals("01000000",
display.getFocusedVertex().getAttribute(DataReferenceGraph.ADDRESS_ATTRIBUTE));
// also try a location that is not the start of a block
codeBrowser.goTo(new ProgramLocation(program, addr(0x1000021)));
assertEquals("0100001d",
display.getFocusedVertex().getAttribute(DataReferenceGraph.ADDRESS_ATTRIBUTE));
}
@Test
public void testGhidraSelectionChanged() {
makeSelection(tool, program, addrSet(0x1000000, 0x100001c));
Set<AttributedVertex> selected = new HashSet<>(display.getSelectedVertices());
assertEquals(3, selected.size());
assertTrue(selected.contains(graph.getVertex(graph.makeName(addr("01000000")))));
assertTrue(selected.contains(graph.getVertex(graph.makeName(addr("0100000c")))));
assertTrue(selected.contains(graph.getVertex(graph.makeName(addr("0100000f")))));
makeSelection(tool, program, new AddressSet(addr(0x100000f), addr(0x1000021)));
selected = new HashSet<>(display.getSelectedVertices());
assertEquals(2, selected.size());
assertTrue(selected.contains(graph.getVertex(graph.makeName(addr("0100000f")))));
assertTrue(selected.contains(graph.getVertex(graph.makeName(addr("01000021")))));
}
@Test
public void testGraphNodeFocused() {
display.focusChanged(graph.getVertex(graph.makeName(addr(0x01002200))));
assertEquals(addr(0x01002200), codeBrowser.getCurrentLocation().getAddress());
display.focusChanged(graph.getVertex(graph.makeName(addr("01000000"))));
assertEquals(addr(0x01000000), codeBrowser.getCurrentLocation().getAddress());
}
@Test
public void testGraphNodesSelected() {
display.selectionChanged(Set.of(graph.getVertex(graph.makeName(addr("01000000"))),
graph.getVertex(graph.makeName(addr("0100000c")))));
ProgramSelection selection = codeBrowser.getCurrentSelection();
assertEquals(addr(0x01000000), selection.getMinAddress());
assertEquals(addr(0x0100000c), selection.getMaxAddress());
display.selectionChanged(Set.of(graph.getVertex(graph.makeName(addr("0100000f"))),
graph.getVertex(graph.makeName(addr("01000021")))));
selection = codeBrowser.getCurrentSelection();
assertEquals(addr(0x0100000f), selection.getMinAddress());
assertEquals(addr(0x01000024), selection.getMaxAddress());
}
}
@@ -0,0 +1,266 @@
/* ###
* 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 ghidra.graph.program;
import static org.junit.Assert.*;
import org.junit.Test;
import ghidra.graph.TestGraphDisplay;
import ghidra.graph.TestGraphService;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.service.graph.AttributedEdge;
import ghidra.service.graph.AttributedVertex;
import ghidra.util.exception.GraphException;
import ghidra.util.task.TaskMonitor;
public class DataReferenceGraphTaskTest extends AbstractDataReferenceGraphTest {
@Test
public void testGraphWithLimit() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100001d)), graphService, 1, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(e1);
}
@Test
public void testGraphWithoutLimit() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100001d)), graphService, 0, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(3, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3 = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v2, v3);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNotNull(e1);
assertNotNull(e2);
}
@Test
public void testGraphAdd() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100001d)), graphService, 1, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(e1);
DataReferenceGraphTask taskAdd = new DataReferenceGraphTask(tool, program,
addrSet(0x0100000c, 0x0100000c), display, 1, DataReferenceGraph.Directions.BOTH_WAYS);
taskAdd.monitoredRun(TaskMonitor.DUMMY);
graph = (DataReferenceGraph) display.getGraph();
assertEquals(3, graph.getVertexCount());
AttributedVertex v1Add = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2Add = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3Add = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedEdge e1Add = graph.getEdge(v1Add, v2Add);
AttributedEdge e2Add = graph.getEdge(v2Add, v3Add);
assertNotNull(v1Add);
assertNotNull(v2Add);
assertNotNull(v3Add);
assertNotNull(e1Add);
assertNotNull(e2Add);
}
@Test
public void testDirectionsBoth() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100000c)), graphService, 0, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(3, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3 = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v2, v3);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNotNull(e1);
assertNotNull(e2);
}
@Test
public void testDirectionsTo() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100000c)), graphService, 0, 10,
DataReferenceGraph.Directions.TO_ONLY);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3 = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v2, v3);
assertNotNull(v1);
assertNotNull(v2);
assertNull(v3);
assertNotNull(e1);
assertNull(e2);
}
@Test
public void testDirectionsFrom() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100000c)), graphService, 0, 10,
DataReferenceGraph.Directions.FROM_ONLY);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3 = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v2, v3);
assertNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNull(e1);
assertNotNull(e2);
}
@Test
public void testNodeWithType() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x0100001d)), graphService, 1, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
AttributedVertex vertex = graph.getVertex(graph.makeName(addr(0x0100001d)));
assertEquals("pointer_thing", vertex.getAttribute(DataReferenceGraph.DATA_ATTRIBUTE));
assertEquals("0100001d", vertex.getAttribute(DataReferenceGraph.ADDRESS_ATTRIBUTE));
assertNull(vertex.getAttribute(DataReferenceGraph.LABEL_ATTRIBUTE)); // no label at address
}
@Test
public void testCodeReference() throws GraphException {
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, null,
new ProgramLocation(program, addr(0x01002200)), graphService, 0, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
assertEquals(2, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x01002200)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x01000000)));
AttributedEdge e1 = graph.getEdge(v1, v2);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(e1);
assertEquals("TriangleDown", v1.getAttribute("Icon"));
}
@Test
public void testGraphSelection() throws GraphException {
ProgramSelection selection = new ProgramSelection(addr(0x01000000), addr(0x0100000c));
TestGraphService graphService = new TestGraphService();
DataReferenceGraphTask task = new DataReferenceGraphTask(false, false, tool, selection,
new ProgramLocation(program, addr(0x0100000c)), graphService, 0, 10,
DataReferenceGraph.Directions.BOTH_WAYS);
task.monitoredRun(TaskMonitor.DUMMY);
TestGraphDisplay display =
(TestGraphDisplay) graphService.getGraphDisplay(true, TaskMonitor.DUMMY);
DataReferenceGraph graph = (DataReferenceGraph) display.getGraph();
//there's an extra vertex at 0x0100000b as an artifact of selection construction
assertEquals(6, graph.getVertexCount());
AttributedVertex v1 = graph.getVertex(graph.makeName(addr(0x0100001d)));
AttributedVertex v2 = graph.getVertex(graph.makeName(addr(0x0100000c)));
AttributedVertex v3 = graph.getVertex(graph.makeName(addr(0x0100000f)));
AttributedVertex v4 = graph.getVertex(graph.makeName(addr(0x01002200)));
AttributedVertex v5 = graph.getVertex(graph.makeName(addr(0x01000000)));
AttributedEdge e3 = graph.getEdge(v4, v5);
AttributedEdge e1 = graph.getEdge(v1, v2);
AttributedEdge e2 = graph.getEdge(v2, v3);
assertNotNull(v1);
assertNotNull(v2);
assertNotNull(v3);
assertNotNull(v4);
assertNotNull(v5);
assertNotNull(e1);
assertNotNull(e2);
assertNotNull(e3);
}
}