591
591
def test__remove_simple_descendants(self):
592
592
graph = self.make_graph(ancestry_1)
593
self.assertRemoveDescendants(set(['rev1']), graph,
594
set(['rev1', 'rev2a', 'rev2b', 'rev3', 'rev4']))
593
self.assertRemoveDescendants({'rev1'}, graph,
594
{'rev1', 'rev2a', 'rev2b', 'rev3', 'rev4'})
596
596
def test__remove_simple_descendants_disjoint(self):
597
597
graph = self.make_graph(ancestry_1)
598
self.assertRemoveDescendants(set(['rev1', 'rev3']), graph,
599
set(['rev1', 'rev3']))
598
self.assertRemoveDescendants({'rev1', 'rev3'}, graph,
601
601
def test__remove_simple_descendants_chain(self):
602
602
graph = self.make_graph(ancestry_1)
603
self.assertRemoveDescendants(set(['rev1']), graph,
604
set(['rev1', 'rev2a', 'rev3']))
603
self.assertRemoveDescendants({'rev1'}, graph,
604
{'rev1', 'rev2a', 'rev3'})
606
606
def test__remove_simple_descendants_siblings(self):
607
607
graph = self.make_graph(ancestry_1)
608
self.assertRemoveDescendants(set(['rev2a', 'rev2b']), graph,
609
set(['rev2a', 'rev2b', 'rev3']))
608
self.assertRemoveDescendants({'rev2a', 'rev2b'}, graph,
609
{'rev2a', 'rev2b', 'rev3'})
611
611
def test_unique_lca_criss_cross(self):
612
612
"""Ensure we don't pick non-unique lcas in a criss-cross"""
652
652
def test_graph_difference(self):
653
653
graph = self.make_graph(ancestry_1)
654
654
self.assertEqual((set(), set()), graph.find_difference('rev1', 'rev1'))
655
self.assertEqual((set(), set(['rev1'])),
655
self.assertEqual((set(), {'rev1'}),
656
656
graph.find_difference(NULL_REVISION, 'rev1'))
657
self.assertEqual((set(['rev1']), set()),
657
self.assertEqual(({'rev1'}, set()),
658
658
graph.find_difference('rev1', NULL_REVISION))
659
self.assertEqual((set(['rev2a', 'rev3']), set(['rev2b'])),
659
self.assertEqual(({'rev2a', 'rev3'}, {'rev2b'}),
660
660
graph.find_difference('rev3', 'rev2b'))
661
self.assertEqual((set(['rev4', 'rev3', 'rev2a']), set()),
661
self.assertEqual(({'rev4', 'rev3', 'rev2a'}, set()),
662
662
graph.find_difference('rev4', 'rev2b'))
664
664
def test_graph_difference_separate_ancestry(self):
665
665
graph = self.make_graph(ancestry_2)
666
self.assertEqual((set(['rev1a']), set(['rev1b'])),
666
self.assertEqual(({'rev1a'}, {'rev1b'}),
667
667
graph.find_difference('rev1a', 'rev1b'))
668
self.assertEqual((set(['rev1a', 'rev2a', 'rev3a', 'rev4a']),
668
self.assertEqual(({'rev1a', 'rev2a', 'rev3a', 'rev4a'},
670
670
graph.find_difference('rev4a', 'rev1b'))
672
672
def test_graph_difference_criss_cross(self):
673
673
graph = self.make_graph(criss_cross)
674
self.assertEqual((set(['rev3a']), set(['rev3b'])),
674
self.assertEqual(({'rev3a'}, {'rev3b'}),
675
675
graph.find_difference('rev3a', 'rev3b'))
676
self.assertEqual((set([]), set(['rev3b', 'rev2b'])),
676
self.assertEqual((set([]), {'rev3b', 'rev2b'}),
677
677
graph.find_difference('rev2a', 'rev3b'))
679
679
def test_graph_difference_extended_history(self):
680
680
graph = self.make_graph(extended_history_shortcut)
681
self.assertEqual((set(['e']), set(['f'])),
681
self.assertEqual(({'e'}, {'f'}),
682
682
graph.find_difference('e', 'f'))
683
self.assertEqual((set(['f']), set(['e'])),
683
self.assertEqual(({'f'}, {'e'}),
684
684
graph.find_difference('f', 'e'))
686
686
def test_graph_difference_double_shortcut(self):
687
687
graph = self.make_graph(double_shortcut)
688
self.assertEqual((set(['d', 'f']), set(['e', 'g'])),
688
self.assertEqual(({'d', 'f'}, {'e', 'g'}),
689
689
graph.find_difference('f', 'g'))
691
691
def test_graph_difference_complex_shortcut(self):
692
692
graph = self.make_graph(complex_shortcut)
693
self.assertEqual((set(['m', 'i', 'e']), set(['n', 'h'])),
693
self.assertEqual(({'m', 'i', 'e'}, {'n', 'h'}),
694
694
graph.find_difference('m', 'n'))
696
696
def test_graph_difference_complex_shortcut2(self):
697
697
graph = self.make_graph(complex_shortcut2)
698
self.assertEqual((set(['t']), set(['j', 'u'])),
698
self.assertEqual(({'t'}, {'j', 'u'}),
699
699
graph.find_difference('t', 'u'))
701
701
def test_graph_difference_shortcut_extra_root(self):
702
702
graph = self.make_graph(shortcut_extra_root)
703
self.assertEqual((set(['e']), set(['f', 'g'])),
703
self.assertEqual(({'e'}, {'f', 'g'}),
704
704
graph.find_difference('e', 'f'))
706
706
def test_iter_topo_order(self):
792
792
graph = self.make_graph({'c': ['b', 'd'], 'd': ['e'], 'b': ['a'],
793
793
'a': [NULL_REVISION], 'e': [NULL_REVISION]})
794
self.assertEqual(set(['c']), graph.heads(['a', 'c', 'e']))
794
self.assertEqual({'c'}, graph.heads(['a', 'c', 'e']))
796
796
def test_heads_null(self):
797
797
graph = self.make_graph(ancestry_1)
798
self.assertEqual(set(['null:']), graph.heads(['null:']))
799
self.assertEqual(set(['rev1']), graph.heads(['null:', 'rev1']))
800
self.assertEqual(set(['rev1']), graph.heads(['rev1', 'null:']))
801
self.assertEqual(set(['rev1']), graph.heads(set(['rev1', 'null:'])))
802
self.assertEqual(set(['rev1']), graph.heads(('rev1', 'null:')))
798
self.assertEqual({'null:'}, graph.heads(['null:']))
799
self.assertEqual({'rev1'}, graph.heads(['null:', 'rev1']))
800
self.assertEqual({'rev1'}, graph.heads(['rev1', 'null:']))
801
self.assertEqual({'rev1'}, graph.heads({'rev1', 'null:'}))
802
self.assertEqual({'rev1'}, graph.heads(('rev1', 'null:')))
804
804
def test_heads_one(self):
805
805
# A single node will always be a head
806
806
graph = self.make_graph(ancestry_1)
807
self.assertEqual(set(['null:']), graph.heads(['null:']))
808
self.assertEqual(set(['rev1']), graph.heads(['rev1']))
809
self.assertEqual(set(['rev2a']), graph.heads(['rev2a']))
810
self.assertEqual(set(['rev2b']), graph.heads(['rev2b']))
811
self.assertEqual(set(['rev3']), graph.heads(['rev3']))
812
self.assertEqual(set(['rev4']), graph.heads(['rev4']))
807
self.assertEqual({'null:'}, graph.heads(['null:']))
808
self.assertEqual({'rev1'}, graph.heads(['rev1']))
809
self.assertEqual({'rev2a'}, graph.heads(['rev2a']))
810
self.assertEqual({'rev2b'}, graph.heads(['rev2b']))
811
self.assertEqual({'rev3'}, graph.heads(['rev3']))
812
self.assertEqual({'rev4'}, graph.heads(['rev4']))
814
814
def test_heads_single(self):
815
815
graph = self.make_graph(ancestry_1)
816
self.assertEqual(set(['rev4']), graph.heads(['null:', 'rev4']))
817
self.assertEqual(set(['rev2a']), graph.heads(['rev1', 'rev2a']))
818
self.assertEqual(set(['rev2b']), graph.heads(['rev1', 'rev2b']))
819
self.assertEqual(set(['rev3']), graph.heads(['rev1', 'rev3']))
820
self.assertEqual(set(['rev4']), graph.heads(['rev1', 'rev4']))
821
self.assertEqual(set(['rev4']), graph.heads(['rev2a', 'rev4']))
822
self.assertEqual(set(['rev4']), graph.heads(['rev2b', 'rev4']))
823
self.assertEqual(set(['rev4']), graph.heads(['rev3', 'rev4']))
816
self.assertEqual({'rev4'}, graph.heads(['null:', 'rev4']))
817
self.assertEqual({'rev2a'}, graph.heads(['rev1', 'rev2a']))
818
self.assertEqual({'rev2b'}, graph.heads(['rev1', 'rev2b']))
819
self.assertEqual({'rev3'}, graph.heads(['rev1', 'rev3']))
820
self.assertEqual({'rev4'}, graph.heads(['rev1', 'rev4']))
821
self.assertEqual({'rev4'}, graph.heads(['rev2a', 'rev4']))
822
self.assertEqual({'rev4'}, graph.heads(['rev2b', 'rev4']))
823
self.assertEqual({'rev4'}, graph.heads(['rev3', 'rev4']))
825
825
def test_heads_two_heads(self):
826
826
graph = self.make_graph(ancestry_1)
827
self.assertEqual(set(['rev2a', 'rev2b']),
827
self.assertEqual({'rev2a', 'rev2b'},
828
828
graph.heads(['rev2a', 'rev2b']))
829
self.assertEqual(set(['rev3', 'rev2b']),
829
self.assertEqual({'rev3', 'rev2b'},
830
830
graph.heads(['rev3', 'rev2b']))
832
832
def test_heads_criss_cross(self):
833
833
graph = self.make_graph(criss_cross)
834
self.assertEqual(set(['rev2a']),
834
self.assertEqual({'rev2a'},
835
835
graph.heads(['rev2a', 'rev1']))
836
self.assertEqual(set(['rev2b']),
836
self.assertEqual({'rev2b'},
837
837
graph.heads(['rev2b', 'rev1']))
838
self.assertEqual(set(['rev3a']),
838
self.assertEqual({'rev3a'},
839
839
graph.heads(['rev3a', 'rev1']))
840
self.assertEqual(set(['rev3b']),
840
self.assertEqual({'rev3b'},
841
841
graph.heads(['rev3b', 'rev1']))
842
self.assertEqual(set(['rev2a', 'rev2b']),
842
self.assertEqual({'rev2a', 'rev2b'},
843
843
graph.heads(['rev2a', 'rev2b']))
844
self.assertEqual(set(['rev3a']),
844
self.assertEqual({'rev3a'},
845
845
graph.heads(['rev3a', 'rev2a']))
846
self.assertEqual(set(['rev3a']),
846
self.assertEqual({'rev3a'},
847
847
graph.heads(['rev3a', 'rev2b']))
848
self.assertEqual(set(['rev3a']),
848
self.assertEqual({'rev3a'},
849
849
graph.heads(['rev3a', 'rev2a', 'rev2b']))
850
self.assertEqual(set(['rev3b']),
850
self.assertEqual({'rev3b'},
851
851
graph.heads(['rev3b', 'rev2a']))
852
self.assertEqual(set(['rev3b']),
852
self.assertEqual({'rev3b'},
853
853
graph.heads(['rev3b', 'rev2b']))
854
self.assertEqual(set(['rev3b']),
854
self.assertEqual({'rev3b'},
855
855
graph.heads(['rev3b', 'rev2a', 'rev2b']))
856
self.assertEqual(set(['rev3a', 'rev3b']),
856
self.assertEqual({'rev3a', 'rev3b'},
857
857
graph.heads(['rev3a', 'rev3b']))
858
self.assertEqual(set(['rev3a', 'rev3b']),
858
self.assertEqual({'rev3a', 'rev3b'},
859
859
graph.heads(['rev3a', 'rev3b', 'rev2a', 'rev2b']))
861
861
def test_heads_shortcut(self):
862
862
graph = self.make_graph(history_shortcut)
864
self.assertEqual(set(['rev2a', 'rev2b', 'rev2c']),
864
self.assertEqual({'rev2a', 'rev2b', 'rev2c'},
865
865
graph.heads(['rev2a', 'rev2b', 'rev2c']))
866
self.assertEqual(set(['rev3a', 'rev3b']),
866
self.assertEqual({'rev3a', 'rev3b'},
867
867
graph.heads(['rev3a', 'rev3b']))
868
self.assertEqual(set(['rev3a', 'rev3b']),
868
self.assertEqual({'rev3a', 'rev3b'},
869
869
graph.heads(['rev2a', 'rev3a', 'rev3b']))
870
self.assertEqual(set(['rev2a', 'rev3b']),
870
self.assertEqual({'rev2a', 'rev3b'},
871
871
graph.heads(['rev2a', 'rev3b']))
872
self.assertEqual(set(['rev2c', 'rev3a']),
872
self.assertEqual({'rev2c', 'rev3a'},
873
873
graph.heads(['rev2c', 'rev3a']))
875
875
def _run_heads_break_deeper(self, graph_dict, search):
992
992
search = graph._make_breadth_first_searcher(['head'])
993
self.assertEqual((set(['head']), set()), search.next_with_ghosts())
994
self.assertEqual((set(['present']), set()), search.next_with_ghosts())
995
self.assertEqual(set(['present']),
993
self.assertEqual(({'head'}, set()), search.next_with_ghosts())
994
self.assertEqual(({'present'}, set()), search.next_with_ghosts())
995
self.assertEqual({'present'},
996
996
search.stop_searching_any(['present']))
997
self.assertEqual((set(['other']), set(['other_ghost'])),
997
self.assertEqual(({'other'}, {'other_ghost'}),
998
998
search.start_searching(['other', 'other_ghost']))
999
self.assertEqual((set(['other_2']), set()), search.next_with_ghosts())
999
self.assertEqual(({'other_2'}, set()), search.next_with_ghosts())
1000
1000
self.assertRaises(StopIteration, search.next_with_ghosts)
1001
1001
# next includes them
1002
1002
search = graph._make_breadth_first_searcher(['head'])
1003
self.assertEqual(set(['head']), search.next())
1004
self.assertEqual(set(['present']), search.next())
1005
self.assertEqual(set(['present']),
1003
self.assertEqual({'head'}, search.next())
1004
self.assertEqual({'present'}, search.next())
1005
self.assertEqual({'present'},
1006
1006
search.stop_searching_any(['present']))
1007
1007
search.start_searching(['other', 'other_ghost'])
1008
self.assertEqual(set(['other_2']), search.next())
1008
self.assertEqual({'other_2'}, search.next())
1009
1009
self.assertRaises(StopIteration, search.next)
1011
1011
def assertSeenAndResult(self, instructions, search, next):
1042
1042
search = graph._make_breadth_first_searcher(['head'])
1043
1043
# At the start, nothing has been seen, to its all excluded:
1044
1044
state = search.get_state()
1045
self.assertEqual((set(['head']), set(['head']), set()),
1045
self.assertEqual(({'head'}, {'head'}, set()),
1047
1047
self.assertEqual(set(), search.seen)
1050
(set(['head']), (set(['head']), set(['child']), 1),
1050
({'head'}, ({'head'}, {'child'}, 1),
1051
1051
['head'], None, None),
1052
(set(['head', 'child']), (set(['head']), set([NULL_REVISION]), 2),
1052
({'head', 'child'}, ({'head'}, {NULL_REVISION}, 2),
1053
1053
['head', 'child'], None, None),
1054
(set(['head', 'child', NULL_REVISION]), (set(['head']), set(), 3),
1054
({'head', 'child', NULL_REVISION}, ({'head'}, set(), 3),
1055
1055
['head', 'child', NULL_REVISION], None, None),
1057
1057
self.assertSeenAndResult(expected, search, search.next)
1073
1073
search.start_searching(['head'])
1074
1074
# head has been seen:
1075
1075
state = search.get_state()
1076
self.assertEqual((set(['head']), set(['child']), set(['head'])),
1076
self.assertEqual(({'head'}, {'child'}, {'head'}),
1078
self.assertEqual(set(['head']), search.seen)
1078
self.assertEqual({'head'}, search.seen)
1081
1081
# stop at child, and start a new search at otherhead:
1082
1082
# - otherhead counts as seen immediately when start_searching is
1084
(set(['head', 'child', 'otherhead']),
1085
(set(['head', 'otherhead']), set(['child', 'otherchild']), 2),
1084
({'head', 'child', 'otherhead'},
1085
({'head', 'otherhead'}, {'child', 'otherchild'}, 2),
1086
1086
['head', 'otherhead'], ['otherhead'], ['child']),
1087
(set(['head', 'child', 'otherhead', 'otherchild']),
1088
(set(['head', 'otherhead']), set(['child', 'excluded']), 3),
1087
({'head', 'child', 'otherhead', 'otherchild'},
1088
({'head', 'otherhead'}, {'child', 'excluded'}, 3),
1089
1089
['head', 'otherhead', 'otherchild'], None, None),
1090
1090
# stop searching excluded now
1091
(set(['head', 'child', 'otherhead', 'otherchild', 'excluded']),
1092
(set(['head', 'otherhead']), set(['child', 'excluded']), 3),
1091
({'head', 'child', 'otherhead', 'otherchild', 'excluded'},
1092
({'head', 'otherhead'}, {'child', 'excluded'}, 3),
1093
1093
['head', 'otherhead', 'otherchild'], None, ['excluded']),
1095
1095
self.assertSeenAndResult(expected, search, search.next)
1221
1221
search = graph._make_breadth_first_searcher(['head'])
1225
(set(['head']), set([NULL_REVISION]), 1),
1225
({'head'}, {NULL_REVISION}, 1),
1226
1226
['head'], None, None),
1227
(set(['head', 'ghost', NULL_REVISION]),
1228
(set(['head', 'ghost']), set(['ghost']), 2),
1227
({'head', 'ghost', NULL_REVISION},
1228
({'head', 'ghost'}, {'ghost'}, 2),
1229
1229
['head', NULL_REVISION], ['ghost'], None),
1231
1231
self.assertSeenAndResult(expected, search, search.next)
1232
1232
self.assertRaises(StopIteration, search.next)
1233
self.assertEqual(set(['head', 'ghost', NULL_REVISION]), search.seen)
1233
self.assertEqual({'head', 'ghost', NULL_REVISION}, search.seen)
1234
1234
state = search.get_state()
1235
1235
self.assertEqual(
1236
(set(['ghost', 'head']), set(['ghost']),
1237
set(['head', NULL_REVISION])),
1236
({'ghost', 'head'}, {'ghost'},
1237
{'head', NULL_REVISION}),
1239
1239
# using next_with_ghosts:
1240
1240
search = graph._make_breadth_first_searcher(['head'])
1241
1241
self.assertSeenAndResult(expected, search, search.next_with_ghosts)
1242
1242
self.assertRaises(StopIteration, search.next)
1243
self.assertEqual(set(['head', 'ghost', NULL_REVISION]), search.seen)
1243
self.assertEqual({'head', 'ghost', NULL_REVISION}, search.seen)
1244
1244
state = search.get_state()
1245
1245
self.assertEqual(
1246
(set(['ghost', 'head']), set(['ghost']),
1247
set(['head', NULL_REVISION])),
1246
({'ghost', 'head'}, {'ghost'},
1247
{'head', NULL_REVISION}),