def test_autoloop(self): graph = sd3.cfa.graph.Graph() nodes = {} # Create nodes for i in range(1, 5): (nodes[i], _) = graph.add_node("%d" % i) graph.set_entry(nodes[1]) # Create edges nodes[1].add_successor(nodes[2]) # Self loop nodes[2].add_successor(nodes[3]) nodes[2].add_successor(nodes[2]) nodes[3].add_successor(nodes[4]) # Build its dominator graph dom_graph = sd3.cfa.dominator.build_graph(graph) # Find loops found_loops = sd3.cfa.loop.find_loops(graph, dom_graph) self.assertEqual(len(found_loops), 1) expected_loop = self._create_node_set(nodes, [2]) self.assertSetEqual(set(found_loops[0].get_node_list()), expected_loop)
def _build_graph(self): graph = sd3.cfa.graph.Graph() nodes = {} # Create nodes for i in range(1, 12): (nodes[i], _) = graph.add_node("%d" % i) graph.set_entry(nodes[1]) # Create edges nodes[1].add_successor(nodes[2]) nodes[1].add_successor(nodes[3]) nodes[2].add_successor(nodes[3]) nodes[3].add_successor(nodes[4]) nodes[4].add_successor(nodes[3]) nodes[4].add_successor(nodes[5]) nodes[4].add_successor(nodes[6]) nodes[5].add_successor(nodes[7]) nodes[6].add_successor(nodes[7]) nodes[7].add_successor(nodes[3]) nodes[7].add_successor(nodes[8]) nodes[8].add_successor(nodes[9]) nodes[8].add_successor(nodes[10]) nodes[9].add_successor(nodes[11]) nodes[10].add_successor(nodes[3]) nodes[10].add_successor(nodes[7]) nodes[10].add_successor(nodes[11]) nodes[11].add_successor(nodes[1]) return (graph, nodes)
def test_shortest_path(self): graph = sd3.cfa.graph.Graph() # Create nodes (node1, _) = graph.add_node(1) (node2, _) = graph.add_node(2) (node3, _) = graph.add_node(3) (node4, _) = graph.add_node(4) (node5, _) = graph.add_node(5) (node6, _) = graph.add_node(6) (node7, _) = graph.add_node(7) # Create edges node1.add_successor(node2) node1.add_successor(node5) node1.add_successor(node7) node2.add_successor(node3) node2.add_successor(node4) node3.add_successor(node4) node3.add_successor(node7) node5.add_successor(node3) node5.add_successor(node5) node5.add_successor(node6) node7.add_successor(node6) # Check some paths self.assertEqual(sd3.cfa.shortestpath.get(graph, node1, node3), 2) self.assertEqual(sd3.cfa.shortestpath.get(graph, node1, node4), 2) self.assertEqual(sd3.cfa.shortestpath.get(graph, node1, node6), 2) self.assertEqual(sd3.cfa.shortestpath.get(graph, node1, node7), 1) self.assertEqual(sd3.cfa.shortestpath.get(graph, node2, node4), 1) self.assertEqual(sd3.cfa.shortestpath.get(graph, node2, node1), sd3.cfa.shortestpath.INFINITE) self.assertEqual(sd3.cfa.shortestpath.get(graph, node5, node6), 1)
def _build_dominators_graph(self): graph = sd3.cfa.graph.Graph() node_map = {} # Create nodes for node in self.nodes: (graph_node, _) = graph.add_node(node.get_id()) parent_node = node.get_graph_node() graph_node.set_data(parent_node.get_data()) node_map[node] = graph_node # Create edges for node in self.nodes: graph_node = node_map[node] for dom in node.get_dominators(): graph_dom = node_map[dom] graph_dom.add_successor(graph_node) graph.set_entry(node_map[self.entry_node]) return graph
def test_graph(self): node_id = 1 second_node_id = 2 third_node_id = 2 # New graph is empty graph = sd3.cfa.graph.Graph() self.assertIsNone(graph.get_entry()) self.assertEqual(len(graph.get_node_list()), 0) # Forbid entry set on an unknown node node = sd3.cfa.graph.Node(node_id) self.assertRaises(KeyError, graph.set_entry, node) self.assertRaises(KeyError, graph.set_exit, node) # Test node add (node, is_new) = graph.add_node(node_id) self.assertEqual(node.get_id(), node_id) self.assertTrue(is_new) self.assertTrue(graph.has_node(node_id)) # Test node add with the same id (existing_node, is_new) = graph.add_node(node_id) self.assertEqual(existing_node.get_id(), node_id) self.assertFalse(is_new) # Test that node can be fetched self.assertIs(graph.get_node(node_id), node) # Test set entry with an invalid node fake_node = sd3.cfa.graph.Node(node_id) self.assertRaises(KeyError, graph.set_entry, fake_node) self.assertRaises(KeyError, graph.set_exit, fake_node) # Test valid entry set graph.set_entry(node) self.assertIs(graph.get_entry(), node) # Test valid exit set graph.set_exit(node) self.assertIs(graph.get_exit(), node) # Test node list (second_node, _) = graph.add_node(second_node_id) self.assertListEqual(graph.get_node_list(), [node, second_node]) # Test node iterator nodes_id = set() nodes_it = set() for it_node_id, it_node in graph.get_node_it(): nodes_id.add(it_node_id) nodes_it.add(it_node) self.assertSetEqual(nodes_id, {node_id, second_node_id}) self.assertSetEqual(nodes_it, {node, second_node}) # Test edges (third_node, _) = graph.add_node(third_node_id) node.add_successor(second_node) second_node.add_successor(third_node) edge_set = set() for edge in list(graph.get_edges_it()): edge_set.add((edge.get_src(), edge.get_dest())) expected_edge_set = set() expected_edge_set.add((node, second_node)) expected_edge_set.add((second_node, third_node)) self.assertSetEqual(edge_set, expected_edge_set) # Run draw to test that the function doesn't crash node_id_str = lambda n: "%s" % n.get_id() (fd, path) = tempfile.mkstemp(suffix=".png") graph.draw(path, node_id_str=node_id_str) os.close(fd) os.remove(path)
def test(self): graph = sd3.cfa.graph.Graph() nodes = {} # Create nodes for i in range(1, 12): (nodes[i], _) = graph.add_node("%d" % i) graph.set_entry(nodes[1]) # Create edges nodes[1].add_successor(nodes[2]) nodes[1].add_successor(nodes[3]) nodes[2].add_successor(nodes[3]) nodes[3].add_successor(nodes[4]) nodes[4].add_successor(nodes[3]) nodes[4].add_successor(nodes[5]) nodes[4].add_successor(nodes[6]) nodes[5].add_successor(nodes[7]) nodes[6].add_successor(nodes[7]) nodes[7].add_successor(nodes[3]) nodes[7].add_successor(nodes[8]) nodes[8].add_successor(nodes[9]) nodes[8].add_successor(nodes[10]) nodes[9].add_successor(nodes[11]) nodes[10].add_successor(nodes[3]) nodes[10].add_successor(nodes[7]) nodes[10].add_successor(nodes[11]) nodes[11].add_successor(nodes[1]) # Build dominator tree dom_graph = sd3.cfa.dominator.build_graph(graph) nodes = {} # Create nodes for i in range(1, 12): nodes[i] = dom_graph.get_node("%d" % i) node_list = list(nodes) self._test_successors(node_list, nodes[1], [nodes[2], nodes[3]]) self._test_successors(node_list, nodes[2], []) self._test_successors(node_list, nodes[3], [nodes[4]]) self._test_successors(node_list, nodes[4], [nodes[5], nodes[6], nodes[7]]) self._test_successors(node_list, nodes[5], []) self._test_successors(node_list, nodes[6], []) self._test_successors(node_list, nodes[7], [nodes[8]]) self._test_successors(node_list, nodes[8], [nodes[9], nodes[10], nodes[11]]) self._test_successors(node_list, nodes[9], []) self._test_successors(node_list, nodes[10], []) self._test_successors(node_list, nodes[11], []) # Test dominates function self.assertTrue(sd3.cfa.dominator.dominates(nodes[1], nodes[2])) self.assertTrue(sd3.cfa.dominator.dominates(nodes[1], nodes[5])) self.assertTrue(sd3.cfa.dominator.dominates(nodes[1], nodes[11])) self.assertTrue(sd3.cfa.dominator.dominates(nodes[4], nodes[9])) self.assertFalse(sd3.cfa.dominator.dominates(nodes[5], nodes[7])) self.assertFalse(sd3.cfa.dominator.dominates(nodes[10], nodes[8])) self.assertFalse(sd3.cfa.dominator.dominates(nodes[2], nodes[1])) # Run draw to test that the function doesn't crash (fd, path) = tempfile.mkstemp(suffix=".png") sd3.cfa.dominator.draw_graph(dom_graph, path)