113
(8, [0, 1, 4, 5, 6])])
115
def test_tsort_unincluded_parent(self):
116
"""Sort nodes, but don't include some parents in the output"""
117
self.assertSortAndIterate([(0, [1]),
85
(8, [0, 1, 4, 5, 6])]),
86
[0, 1, 2, 3, 4, 5, 6, 7, 8])
122
89
class MergeSortTests(TestCase):
124
91
def assertSortAndIterate(self, graph, branch_tip, result_list,
125
generate_revno, mainline_revisions=None):
92
mainline_revisions=None):
126
93
"""Check that merge based sorting and iter_topo_order on graph works."""
127
value = merge_sort(graph, branch_tip,
128
mainline_revisions=mainline_revisions,
129
generate_revno=generate_revno)
130
if result_list != value:
131
self.assertEqualDiff(pprint.pformat(result_list),
132
pprint.pformat(value))
94
self.assertEquals(result_list,
95
merge_sort(graph, branch_tip, mainline_revisions=mainline_revisions))
133
96
self.assertEqual(result_list,
137
mainline_revisions=mainline_revisions,
138
generate_revno=generate_revno,
139
).iter_topo_order()))
100
mainline_revisions=mainline_revisions).iter_topo_order()))
141
102
def test_merge_sort_empty(self):
142
103
# sorting of an emptygraph does not error
143
self.assertSortAndIterate({}, None, [], False)
144
self.assertSortAndIterate({}, None, [], True)
145
self.assertSortAndIterate({}, NULL_REVISION, [], False)
146
self.assertSortAndIterate({}, NULL_REVISION, [], True)
104
self.assertSortAndIterate({}, None, [])
148
106
def test_merge_sort_not_empty_no_tip(self):
149
107
# merge sorting of a branch starting with None should result
150
108
# in an empty list: no revisions are dragged in.
151
self.assertSortAndIterate({0: []}.items(), None, [], False)
152
self.assertSortAndIterate({0: []}.items(), None, [], True)
109
self.assertSortAndIterate({0: []}.items(), None, [])
154
111
def test_merge_sort_one_revision(self):
155
112
# sorting with one revision as the tip returns the correct fields:
156
113
# sequence - 0, revision id, merge depth - 0, end_of_merge
157
114
self.assertSortAndIterate({'id': []}.items(),
159
[(0, 'id', 0, True)],
161
self.assertSortAndIterate({'id': []}.items(),
163
[(0, 'id', 0, (1,), True)],
116
[(0, 'id', 0, True)])
166
118
def test_sequence_numbers_increase_no_merges(self):
167
119
# emit a few revisions with no merges to check the sequence
168
120
# numbering works in trivial cases
199
139
[(0, 'C', 0, False),
200
140
(1, 'B', 1, True),
201
141
(2, 'A', 0, True),
205
self.assertSortAndIterate(
208
'C': ['A', 'B']}.items(),
210
[(0, 'C', 0, (2,), False),
211
(1, 'B', 1, (1,1,1), True),
212
(2, 'A', 0, (1,), True),
217
def test_merge_sort_race(self):
233
self.assertSortAndIterate(graph, 'F',
234
[(0, 'F', 0, (3,), False),
235
(1, 'D', 1, (2,2,1), False),
236
(2, 'C', 2, (2,1,1), True),
237
(3, 'B', 0, (2,), False),
238
(4, 'A', 0, (1,), True),
256
self.assertSortAndIterate(graph, 'F',
257
[(0, 'F', 0, (3,), False),
258
(1, 'D', 1, (2,1,2), False),
259
(2, 'C', 2, (2,2,1), True),
260
(3, 'X', 1, (2,1,1), True),
261
(4, 'B', 0, (2,), False),
262
(5, 'A', 0, (1,), True),
265
145
def test_merge_depth_with_nested_merges(self):
266
146
# the merge depth marker should reflect the depth of the revision
267
147
# in terms of merges out from the mainline
268
148
# revid, depth, parents:
293
173
(5, 'F', 2, True),
294
174
(6, 'G', 1, True),
295
175
(7, 'H', 0, True),
299
self.assertSortAndIterate(
310
[(0, 'A', 0, (3,), False),
311
(1, 'B', 1, (1,3,2), False),
312
(2, 'C', 1, (1,3,1), True),
313
(3, 'D', 0, (2,), False),
314
(4, 'E', 1, (1,1,2), False),
315
(5, 'F', 2, (1,2,1), True),
316
(6, 'G', 1, (1,1,1), True),
317
(7, 'H', 0, (1,), True),
322
def test_dotted_revnos_with_simple_merges(self):
327
# D E F 3, 1.1.2, 1.2.1
329
# G H I 4, 1.2.2, 1.3.1
334
self.assertSortAndIterate(
349
[(0, 'L', 0, (6,), False),
350
(1, 'K', 1, (1,3,2), False),
351
(2, 'I', 1, (1,3,1), True),
352
(3, 'J', 0, (5,), False),
353
(4, 'H', 1, (1,2,2), False),
354
(5, 'F', 1, (1,2,1), True),
355
(6, 'G', 0, (4,), False),
356
(7, 'E', 1, (1,1,2), False),
357
(8, 'C', 1, (1,1,1), True),
358
(9, 'D', 0, (3,), False),
359
(10, 'B', 0, (2,), False),
360
(11, 'A', 0, (1,), True),
364
# Adding a shortcut from the first revision should not change any of
365
# the existing numbers
366
self.assertSortAndIterate(
383
[(0, 'N', 0, (7,), False),
384
(1, 'M', 1, (1,4,1), True),
385
(2, 'L', 0, (6,), False),
386
(3, 'K', 1, (1,3,2), False),
387
(4, 'I', 1, (1,3,1), True),
388
(5, 'J', 0, (5,), False),
389
(6, 'H', 1, (1,2,2), False),
390
(7, 'F', 1, (1,2,1), True),
391
(8, 'G', 0, (4,), False),
392
(9, 'E', 1, (1,1,2), False),
393
(10, 'C', 1, (1,1,1), True),
394
(11, 'D', 0, (3,), False),
395
(12, 'B', 0, (2,), False),
396
(13, 'A', 0, (1,), True),
401
179
def test_end_of_merge_not_last_revision_in_branch(self):
402
180
# within a branch only the last revision gets an
403
181
# end of merge marker.
455
222
(5, 'F', 2, True),
456
223
(6, 'G', 1, True),
457
224
(7, 'H', 0, True),
461
self.assertSortAndIterate(
462
{'A': ['H', 'B', 'E'],
472
[(0, 'A', 0, (2,), False),
473
(1, 'B', 1, (1,3,2), False),
474
(2, 'C', 2, (1,4,1), True),
475
(3, 'D', 1, (1,3,1), True),
476
(4, 'E', 1, (1,1,2), False),
477
(5, 'F', 2, (1,2,1), True),
478
(6, 'G', 1, (1,1,1), True),
479
(7, 'H', 0, (1,), True),
484
228
def test_mainline_revs_partial(self):
550
277
[(0, 'A', 0, True),
553
mainline_revisions=[None, 'A']
555
self.assertSortAndIterate(
559
[(0, 'A', 0, (1,), True),
562
mainline_revisions=[None, 'A']
565
def test_mainline_revs_with_ghost(self):
566
# We have a mainline, but the end of it is actually a ghost
567
# The graph that is passed to tsort has had ghosts filtered out, but
568
# the mainline history has not.
569
self.assertSortAndIterate(
573
[(0, 'C', 0, (2,), False),
574
(1, 'B', 0, (1,), True),
576
True, mainline_revisions=['A', 'B', 'C'])
578
def test_parallel_root_sequence_numbers_increase_with_merges(self):
579
"""When there are parallel roots, check their revnos."""
580
self.assertSortAndIterate(
583
'C': ['A', 'B']}.items(),
585
[(0, 'C', 0, (2,), False),
586
(1, 'B', 1, (0,1,1), True),
587
(2, 'A', 0, (1,), True),
592
def test_revnos_are_globally_assigned(self):
593
"""revnos are assigned according to the revision they derive from."""
594
# in this test we setup a number of branches that all derive from
595
# the first revision, and then merge them one at a time, which
596
# should give the revisions as they merge numbers still deriving from
597
# the revision were based on.
598
# merge 3: J: ['G', 'I']
602
# merge 2: G: ['D', 'F']
606
# merge 1: D: ['A', 'C']
611
self.assertSortAndIterate(
624
[(0, 'J', 0, (4,), False),
625
(1, 'I', 1, (1,3,2), False),
626
(2, 'H', 1, (1,3,1), True),
627
(3, 'G', 0, (3,), False),
628
(4, 'F', 1, (1,2,2), False),
629
(5, 'E', 1, (1,2,1), True),
630
(6, 'D', 0, (2,), False),
631
(7, 'C', 1, (1,1,2), False),
632
(8, 'B', 1, (1,1,1), True),
633
(9, 'A', 0, (1,), True),
638
def test_roots_and_sub_branches_versus_ghosts(self):
639
"""Extra roots and their mini branches use the same numbering.
641
All of them use the 0-node numbering.
654
self.assertSortAndIterate(
675
[( 0, 'R', 0, (6,), False),
676
( 1, 'Q', 1, (0,4,5), False),
677
( 2, 'P', 2, (0,6,1), True),
678
( 3, 'O', 1, (0,4,4), False),
679
( 4, 'N', 1, (0,4,3), False),
680
( 5, 'M', 2, (0,5,1), True),
681
( 6, 'L', 1, (0,4,2), False),
682
( 7, 'K', 1, (0,4,1), True),
683
( 8, 'J', 0, (5,), False),
684
( 9, 'I', 1, (0,3,1), True),
685
(10, 'H', 0, (4,), False),
686
(11, 'G', 1, (0,1,3), False),
687
(12, 'F', 2, (0,2,1), True),
688
(13, 'E', 1, (0,1,2), False),
689
(14, 'D', 1, (0,1,1), True),
690
(15, 'C', 0, (3,), False),
691
(16, 'B', 0, (2,), False),
692
(17, 'A', 0, (1,), True),
279
mainline_revisions=[None, 'A']