| # Copyright 2010-2012 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from portage.tests import TestCase |
| from portage.util.digraph import digraph |
| #~ from portage.util import noiselimit |
| import portage.util |
| |
| class DigraphTest(TestCase): |
| |
| def _assertBFSEqual(self, result, expected): |
| result_stack = list(result) |
| result_stack.reverse() |
| expected_stack = list(reversed(expected)) |
| result_compared = [] |
| expected_compared = [] |
| while result_stack: |
| if not expected_stack: |
| result_compared.append(result_stack.pop()) |
| self.assertEqual(result_compared, expected_compared) |
| expected_set = expected_stack.pop() |
| if not isinstance(expected_set, list): |
| expected_set = [expected_set] |
| expected_set = set(expected_set) |
| while expected_set: |
| if not result_stack: |
| expected_compared.extend(expected_set) |
| self.assertEqual(result_compared, expected_compared) |
| obj = result_stack.pop() |
| try: |
| expected_set.remove(obj) |
| except KeyError: |
| expected_compared.extend(expected_set) |
| result_compared.append(obj) |
| self.assertEqual(result_compared, expected_compared) |
| else: |
| expected_compared.append(obj) |
| result_compared.append(obj) |
| if expected_stack: |
| expected_set = expected_stack.pop() |
| if not isinstance(expected_set, list): |
| expected_set = [expected_set] |
| expected_compared.extend(expected_set) |
| self.assertEqual(result_compared, expected_compared) |
| |
| def testBackwardCompatibility(self): |
| g = digraph() |
| f = g.copy() |
| g.addnode("A", None) |
| self.assertEqual("A" in g, True) |
| self.assertEqual(bool(g), True) |
| self.assertEqual(g.allnodes(), ["A"]) |
| self.assertEqual(g.allzeros(), ["A"]) |
| self.assertEqual(g.hasnode("A"), True) |
| |
| def testDigraphEmptyGraph(self): |
| g = digraph() |
| f = g.clone() |
| for x in g, f: |
| self.assertEqual(bool(x), False) |
| self.assertEqual(x.contains("A"), False) |
| self.assertEqual(x.firstzero(), None) |
| self.assertRaises(KeyError, x.remove, "A") |
| x.delnode("A") |
| self.assertEqual(list(x), []) |
| self.assertEqual(x.get("A"), None) |
| self.assertEqual(x.get("A", "default"), "default") |
| self.assertEqual(x.all_nodes(), []) |
| self.assertEqual(x.leaf_nodes(), []) |
| self.assertEqual(x.root_nodes(), []) |
| self.assertRaises(KeyError, x.child_nodes, "A") |
| self.assertRaises(KeyError, x.parent_nodes, "A") |
| self.assertEqual(x.hasallzeros(), True) |
| self.assertRaises(KeyError, list, x.bfs("A")) |
| self.assertRaises(KeyError, x.shortest_path, "A", "B") |
| self.assertRaises(KeyError, x.remove_edge, "A", "B") |
| self.assertEqual(x.get_cycles(), []) |
| x.difference_update("A") |
| portage.util.noiselimit = -2 |
| x.debug_print() |
| portage.util.noiselimit = 0 |
| |
| def testDigraphCircle(self): |
| g = digraph() |
| g.add("A", "B", -1) |
| g.add("B", "C", 0) |
| g.add("C", "D", 1) |
| g.add("D", "A", 2) |
| |
| f = g.clone() |
| for x in g, f: |
| self.assertEqual(bool(x), True) |
| self.assertEqual(x.contains("A"), True) |
| self.assertEqual(x.firstzero(), None) |
| self.assertRaises(KeyError, x.remove, "Z") |
| x.delnode("Z") |
| self.assertEqual(list(x), ["A", "B", "C", "D"]) |
| self.assertEqual(x.get("A"), "A") |
| self.assertEqual(x.get("A", "default"), "A") |
| self.assertEqual(x.all_nodes(), ["A", "B", "C", "D"]) |
| self.assertEqual(x.leaf_nodes(), []) |
| self.assertEqual(x.root_nodes(), []) |
| self.assertEqual(x.child_nodes("A"), ["D"]) |
| self.assertEqual(x.child_nodes("A", ignore_priority=2), []) |
| self.assertEqual(x.parent_nodes("A"), ["B"]) |
| self.assertEqual(x.parent_nodes("A", ignore_priority=-2), ["B"]) |
| self.assertEqual(x.parent_nodes("A", ignore_priority=-1), []) |
| self.assertEqual(x.hasallzeros(), False) |
| self._assertBFSEqual(x.bfs("A"), [(None, "A"), ("A", "D"), ("D", "C"), ("C", "B")]) |
| self.assertEqual(x.shortest_path("A", "D"), ["A", "D"]) |
| self.assertEqual(x.shortest_path("D", "A"), ["D", "C", "B", "A"]) |
| self.assertEqual(x.shortest_path("A", "D", ignore_priority=2), None) |
| self.assertEqual(x.shortest_path("D", "A", ignore_priority=-2), ["D", "C", "B", "A"]) |
| cycles = set(tuple(y) for y in x.get_cycles()) |
| self.assertEqual(cycles, set([("D", "C", "B", "A"), ("C", "B", "A", "D"), ("B", "A", "D", "C"), \ |
| ("A", "D", "C", "B")])) |
| x.remove_edge("A", "B") |
| self.assertEqual(x.get_cycles(), []) |
| x.difference_update(["D"]) |
| self.assertEqual(x.all_nodes(), ["A", "B", "C"]) |
| portage.util.noiselimit = -2 |
| x.debug_print() |
| portage.util.noiselimit = 0 |
| |
| def testDigraphTree(self): |
| g = digraph() |
| g.add("B", "A", -1) |
| g.add("C", "A", 0) |
| g.add("D", "C", 1) |
| g.add("E", "C", 2) |
| |
| f = g.clone() |
| for x in g, f: |
| self.assertEqual(bool(x), True) |
| self.assertEqual(x.contains("A"), True) |
| self.assertEqual(x.firstzero(), "B") |
| self.assertRaises(KeyError, x.remove, "Z") |
| x.delnode("Z") |
| self.assertEqual(set(x), set(["A", "B", "C", "D", "E"])) |
| self.assertEqual(x.get("A"), "A") |
| self.assertEqual(x.get("A", "default"), "A") |
| self.assertEqual(set(x.all_nodes()), set(["A", "B", "C", "D", "E"])) |
| self.assertEqual(set(x.leaf_nodes()), set(["B", "D", "E"])) |
| self.assertEqual(set(x.leaf_nodes(ignore_priority=0)), set(["A", "B", "D", "E"])) |
| self.assertEqual(x.root_nodes(), ["A"]) |
| self.assertEqual(set(x.root_nodes(ignore_priority=0)), set(["A", "B", "C"])) |
| self.assertEqual(set(x.child_nodes("A")), set(["B", "C"])) |
| self.assertEqual(x.child_nodes("A", ignore_priority=2), []) |
| self.assertEqual(x.parent_nodes("B"), ["A"]) |
| self.assertEqual(x.parent_nodes("B", ignore_priority=-2), ["A"]) |
| self.assertEqual(x.parent_nodes("B", ignore_priority=-1), []) |
| self.assertEqual(x.hasallzeros(), False) |
| self._assertBFSEqual(x.bfs("A"), [(None, "A"), [("A", "C"), ("A", "B")], [("C", "E"), ("C", "D")]]) |
| self.assertEqual(x.shortest_path("A", "D"), ["A", "C", "D"]) |
| self.assertEqual(x.shortest_path("D", "A"), None) |
| self.assertEqual(x.shortest_path("A", "D", ignore_priority=2), None) |
| cycles = set(tuple(y) for y in x.get_cycles()) |
| self.assertEqual(cycles, set()) |
| x.remove("D") |
| self.assertEqual(set(x.all_nodes()), set(["A", "B", "C", "E"])) |
| x.remove("C") |
| self.assertEqual(set(x.all_nodes()), set(["A", "B", "E"])) |
| portage.util.noiselimit = -2 |
| x.debug_print() |
| portage.util.noiselimit = 0 |
| self.assertRaises(KeyError, x.remove_edge, "A", "E") |
| |
| def testDigraphCompleteGraph(self): |
| g = digraph() |
| g.add("A", "B", -1) |
| g.add("B", "A", 1) |
| g.add("A", "C", 1) |
| g.add("C", "A", -1) |
| g.add("C", "B", 1) |
| g.add("B", "C", 1) |
| |
| f = g.clone() |
| for x in g, f: |
| self.assertEqual(bool(x), True) |
| self.assertEqual(x.contains("A"), True) |
| self.assertEqual(x.firstzero(), None) |
| self.assertRaises(KeyError, x.remove, "Z") |
| x.delnode("Z") |
| self.assertEqual(list(x), ["A", "B", "C"]) |
| self.assertEqual(x.get("A"), "A") |
| self.assertEqual(x.get("A", "default"), "A") |
| self.assertEqual(x.all_nodes(), ["A", "B", "C"]) |
| self.assertEqual(x.leaf_nodes(), []) |
| self.assertEqual(x.root_nodes(), []) |
| self.assertEqual(set(x.child_nodes("A")), set(["B", "C"])) |
| self.assertEqual(x.child_nodes("A", ignore_priority=0), ["B"]) |
| self.assertEqual(set(x.parent_nodes("A")), set(["B", "C"])) |
| self.assertEqual(x.parent_nodes("A", ignore_priority=0), ["C"]) |
| self.assertEqual(x.parent_nodes("A", ignore_priority=1), []) |
| self.assertEqual(x.hasallzeros(), False) |
| self._assertBFSEqual(x.bfs("A"), [(None, "A"), [("A", "C"), ("A", "B")]]) |
| self.assertEqual(x.shortest_path("A", "C"), ["A", "C"]) |
| self.assertEqual(x.shortest_path("C", "A"), ["C", "A"]) |
| self.assertEqual(x.shortest_path("A", "C", ignore_priority=0), ["A", "B", "C"]) |
| self.assertEqual(x.shortest_path("C", "A", ignore_priority=0), ["C", "A"]) |
| cycles = set(frozenset(y) for y in x.get_cycles()) |
| self.assertEqual(cycles, set([frozenset(["A", "B"]), frozenset(["A", "C"]), frozenset(["B", "C"])])) |
| x.remove_edge("A", "B") |
| cycles = set(frozenset(y) for y in x.get_cycles()) |
| self.assertEqual(cycles, set([frozenset(["A", "C"]), frozenset(["C", "B"])])) |
| x.difference_update(["C"]) |
| self.assertEqual(x.all_nodes(), ["A", "B"]) |
| portage.util.noiselimit = -2 |
| x.debug_print() |
| portage.util.noiselimit = 0 |
| |
| def testDigraphIgnorePriority(self): |
| |
| def always_true(dummy): |
| return True |
| |
| def always_false(dummy): |
| return False |
| |
| g = digraph() |
| g.add("A", "B") |
| |
| self.assertEqual(g.parent_nodes("A"), ["B"]) |
| self.assertEqual(g.parent_nodes("A", ignore_priority=always_false), ["B"]) |
| self.assertEqual(g.parent_nodes("A", ignore_priority=always_true), []) |
| |
| self.assertEqual(g.child_nodes("B"), ["A"]) |
| self.assertEqual(g.child_nodes("B", ignore_priority=always_false), ["A"]) |
| self.assertEqual(g.child_nodes("B", ignore_priority=always_true), []) |
| |
| self.assertEqual(g.leaf_nodes(), ["A"]) |
| self.assertEqual(g.leaf_nodes(ignore_priority=always_false), ["A"]) |
| self.assertEqual(g.leaf_nodes(ignore_priority=always_true), ["A", "B"]) |
| |
| self.assertEqual(g.root_nodes(), ["B"]) |
| self.assertEqual(g.root_nodes(ignore_priority=always_false), ["B"]) |
| self.assertEqual(g.root_nodes(ignore_priority=always_true), ["A", "B"]) |