mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-808 Added Display as Graph action to the Datatype Manager
This commit is contained in:
parent
22675e9f39
commit
ae40102420
7 changed files with 523 additions and 3 deletions
|
@ -725,8 +725,15 @@
|
|||
<P>For Typedefs, Pointers and Arrays, this action will navigate to the tree node of the
|
||||
type to which respective refers.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Type_Graph">Display Data Type as Graph</A></H3>
|
||||
<BLOCKQUOTE>
|
||||
<P>For Structures, Unions and Pointers, will generate a graph of the type, with nodes
|
||||
for each enclosed structure or pointed to type</P>
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
|
||||
<P class="providedbyplugin">Provided by: <I>DataTypeManagerPlugin</I></P>
|
||||
|
||||
|
|
|
@ -191,8 +191,9 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
|||
addLocalAction(new FindReferencesToFieldAction(plugin)); // DataType
|
||||
// addLocalAction( new FindDataTypesContainingAction(plugin) ); // DataType
|
||||
addLocalAction(new FindBaseDataTypeAction(plugin)); // DataType
|
||||
addLocalAction(new DisplayTypeAsGraphAction(plugin));
|
||||
|
||||
// toolbar actions
|
||||
// toolbar actions
|
||||
previousAction = new NextPreviousDataTypeAction(this, plugin.getName(), false);
|
||||
addLocalAction(previousAction);
|
||||
nextAction = new NextPreviousDataTypeAction(this, plugin.getName(), true);
|
||||
|
@ -344,8 +345,8 @@ public class DataTypesProvider extends ComponentProviderAdapter {
|
|||
isToolbarAction = false;
|
||||
}
|
||||
|
||||
return new DataTypesActionContext(this, plugin.getProgram(), archiveGTree,
|
||||
clickedNode, isToolbarAction);
|
||||
return new DataTypesActionContext(this, plugin.getProgram(), archiveGTree, clickedNode,
|
||||
isToolbarAction);
|
||||
}
|
||||
|
||||
@Override // overridden to handle special logic in plugin
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* ###
|
||||
* 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 javax.swing.tree.TreePath;
|
||||
|
||||
import docking.ActionContext;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.MenuData;
|
||||
import docking.widgets.tree.GTree;
|
||||
import docking.widgets.tree.GTreeNode;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
|
||||
import ghidra.app.plugin.core.datamgr.tree.DataTypeNode;
|
||||
import ghidra.app.services.GraphDisplayBroker;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.service.graph.GraphDisplayProvider;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
|
||||
/*
|
||||
* Action to display a Composite data type as a graph from the Data Type Manager
|
||||
*
|
||||
* The graphing is done recursively in a separate task
|
||||
*/
|
||||
public class DisplayTypeAsGraphAction extends DockingAction {
|
||||
|
||||
private DataTypeManagerPlugin plugin;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param plugin the plugin this action is contained in
|
||||
*/
|
||||
public DisplayTypeAsGraphAction(DataTypeManagerPlugin plugin) {
|
||||
super("Display Data Type as Graph", plugin.getName());
|
||||
this.plugin = plugin;
|
||||
|
||||
String menuGroup = "ZVeryLast"; // it's own group; on the bottom
|
||||
setPopupMenuData(new MenuData(new String[] { "Display as Graph" }, null, menuGroup));
|
||||
setHelpLocation(new HelpLocation("DataTypeManagerPlugin", "Type_Graph"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
GraphDisplayBroker broker = plugin.getTool().getService(GraphDisplayBroker.class);
|
||||
if (broker == null) {
|
||||
Msg.showError(this, null, "Missing Plugin", "The Graph plugin is not installed.\n" +
|
||||
"Please add the plugin implementing this service.");
|
||||
return;
|
||||
}
|
||||
GraphDisplayProvider service = broker.getDefaultGraphDisplayProvider();
|
||||
|
||||
GTree gTree = (GTree) context.getContextObject();
|
||||
TreePath[] selectionPaths = gTree.getSelectionPaths();
|
||||
|
||||
for (TreePath path : selectionPaths) {
|
||||
GTreeNode node = (GTreeNode) path.getLastPathComponent();
|
||||
if (!(node instanceof DataTypeNode)) {
|
||||
continue;
|
||||
}
|
||||
DataTypeNode dataTypeNode = (DataTypeNode) node;
|
||||
DataType dt = dataTypeNode.getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof Composite || dt instanceof Pointer) {
|
||||
TypeGraphTask task = new TypeGraphTask(dataTypeNode.getDataType(), service);
|
||||
new TaskLauncher(task, plugin.getTool().getToolFrame());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
boolean enabled = false;
|
||||
|
||||
if (!(context instanceof DataTypesActionContext)) {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
Object contextObject = context.getContextObject();
|
||||
GTree gtree = (GTree) contextObject;
|
||||
TreePath[] selectionPaths = gtree.getSelectionPaths();
|
||||
|
||||
for (TreePath path : selectionPaths) {
|
||||
|
||||
GTreeNode node = (GTreeNode) path.getLastPathComponent();
|
||||
if (!(node instanceof DataTypeNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DataTypeNode dtNode = (DataTypeNode) node;
|
||||
DataType dt = dtNode.getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof Composite || dt instanceof Pointer) {
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/* ###
|
||||
* 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 ghidra.program.model.data.*;
|
||||
import ghidra.service.graph.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.GraphException;
|
||||
import ghidra.util.task.Task;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/*
|
||||
* Task to recursively graph and display a data type
|
||||
*
|
||||
* Nodes are generated for pointers and embedded structures
|
||||
*/
|
||||
public class TypeGraphTask extends Task {
|
||||
|
||||
private DataType type;
|
||||
private String graphTitle;
|
||||
private GraphDisplayProvider graphService;
|
||||
|
||||
public static final String TYPE_ATTRIBUTE = "Type";
|
||||
public static final String EMBEDDED = "Composite";
|
||||
public static final String POINTER = "Reference";
|
||||
public static final String CONTENTS_ATTRIBUTE = "Contents";
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
* @param type the type to graph
|
||||
* @param graphService the GraphService that will display the graph
|
||||
*/
|
||||
public TypeGraphTask(DataType type, GraphDisplayProvider graphService) {
|
||||
super("Graph Data Type", true, false, true);
|
||||
this.type = type;
|
||||
if (this.type instanceof TypeDef) {
|
||||
this.type = ((TypeDef) this.type).getBaseDataType();
|
||||
}
|
||||
this.graphTitle = "Graph of Type: " + type.getName();
|
||||
this.graphService = graphService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
AttributedGraph graph = new AttributedGraph();
|
||||
try {
|
||||
if (type instanceof Pointer) {
|
||||
recursePointer((Pointer) type, graph, null, monitor);
|
||||
}
|
||||
if (type instanceof Composite) {
|
||||
recurseComposite((Composite) type, graph, null, null, monitor);
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
monitor.setMessage("Cancelling...");
|
||||
graphTitle = graphTitle + " (partial)";
|
||||
}
|
||||
|
||||
GraphDisplay display;
|
||||
try {
|
||||
display = graphService.getGraphDisplay(false, monitor);
|
||||
display.setGraph(graph, graphTitle, false, monitor);
|
||||
}
|
||||
catch (GraphException e) {
|
||||
Msg.showError(this, null, "Data Type Graph Error",
|
||||
"Unexpected error while graphing: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void recurseComposite(Composite struct, AttributedGraph graph,
|
||||
AttributedVertex lastVertex, String edgeType, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
AttributedVertex newVertex = new AttributedVertex(struct.getName());
|
||||
newVertex.setAttribute(CONTENTS_ATTRIBUTE, struct.toString());
|
||||
if (lastVertex == null) {
|
||||
graph.addVertex(newVertex);
|
||||
}
|
||||
else {
|
||||
AttributedEdge edge = graph.addEdge(lastVertex, newVertex);
|
||||
if (edgeType == POINTER) {
|
||||
edge.setAttribute("Color", "Blue");
|
||||
}
|
||||
edge.setAttribute(TYPE_ATTRIBUTE, edgeType);
|
||||
if (edge.hasAttribute("Weight")) {
|
||||
//did this already, don't cycle
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (DataTypeComponent inner : struct.getComponents()) {
|
||||
monitor.checkCanceled();
|
||||
DataType dt = inner.getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
|
||||
if (dt instanceof Pointer) {
|
||||
recursePointer((Pointer) dt, graph, newVertex, monitor);
|
||||
}
|
||||
else if (dt instanceof Composite) {
|
||||
recurseComposite((Composite) dt, graph, newVertex, EMBEDDED, monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recursePointer(Pointer pointer, AttributedGraph graph, AttributedVertex lastVertex,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
monitor.checkCanceled();
|
||||
DataType ptrType = pointer.getDataType();
|
||||
if (ptrType == null) {
|
||||
return;
|
||||
}
|
||||
if (ptrType instanceof TypeDef) {
|
||||
ptrType = ((TypeDef) ptrType).getBaseDataType();
|
||||
}
|
||||
|
||||
if (ptrType instanceof Pointer) {
|
||||
recursePointer((Pointer) ptrType, graph, lastVertex, monitor);
|
||||
}
|
||||
else if (ptrType instanceof Composite) {
|
||||
recurseComposite((Composite) ptrType, graph, lastVertex, POINTER, monitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.program.TestGraphDisplay;
|
||||
import ghidra.graph.program.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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue