/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2005 Canonical Ltd
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
16
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
17
1570.1.6 by Robert Collins
Update fast topological_sort to be a function and to have the topo_sort tests run against it.
18
"""Tests for topological sort."""
19
20
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
21
from bzrlib.tests import TestCase
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
22
from bzrlib.tsort import topo_sort, TopoSorter, MergeSorter, merge_sort
1185.16.114 by mbp at sourcefrog
Improved topological sort
23
from bzrlib.errors import GraphCycleError
3236.2.1 by Michael Hudson
test and fix
24
from bzrlib.revision import NULL_REVISION
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
25
1570.1.6 by Robert Collins
Update fast topological_sort to be a function and to have the topo_sort tests run against it.
26
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
27
class TopoSortTests(TestCase):
28
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
29
    def assertSortAndIterate(self, graph, result_list):
30
        """Check that sorting and iter_topo_order on graph works."""
31
        self.assertEquals(result_list, topo_sort(graph))
32
        self.assertEqual(result_list,
33
                         list(TopoSorter(graph).iter_topo_order()))
34
35
    def assertSortAndIterateRaise(self, exception_type, graph):
36
        """Try both iterating and topo_sorting graph and expect an exception."""
37
        self.assertRaises(exception_type, topo_sort, graph)
38
        self.assertRaises(exception_type,
39
                          list,
40
                          TopoSorter(graph).iter_topo_order())
41
4577.2.1 by Maarten Bosmans
Modify test_tsort_partial to accept multiple valid orderings.
42
    def assertSortAndIterateOrder(self, graph):
43
        """Check that sorting and iter_topo_order on graph really results in topological order.
44
45
        For every child in the graph, check if it comes after all of it's parents.
46
        """
47
        sort_result = topo_sort(graph)
48
        iter_result = list(TopoSorter(graph).iter_topo_order())
49
        for (node, parents) in graph:
50
            for parent in parents:
51
                self.assertTrue(sort_result.index(node) > sort_result.index(parent),
52
                    "parent %s must come before child %s:\n%s" % (parent, node, sort_result))
53
                self.assertTrue(iter_result.index(node) > iter_result.index(parent),
54
                    "parent %s must come before child %s:\n%s" % (parent, node, iter_result))
55
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
56
    def test_tsort_empty(self):
57
        """TopoSort empty list"""
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
58
        self.assertSortAndIterate([], [])
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
59
60
    def test_tsort_easy(self):
1185.16.114 by mbp at sourcefrog
Improved topological sort
61
        """TopoSort list with one node"""
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
62
        self.assertSortAndIterate({0: []}.items(), [0])
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
63
64
    def test_tsort_cycle(self):
1185.16.114 by mbp at sourcefrog
Improved topological sort
65
        """TopoSort traps graph with cycles"""
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
66
        self.assertSortAndIterateRaise(GraphCycleError,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
67
                                       {0: [1],
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
68
                                        1: [0]}.items())
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
69
1185.16.114 by mbp at sourcefrog
Improved topological sort
70
    def test_tsort_cycle_2(self):
71
        """TopoSort traps graph with longer cycle"""
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
72
        self.assertSortAndIterateRaise(GraphCycleError,
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
73
                                       {0: [1],
74
                                        1: [2],
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
75
                                        2: [0]}.items())
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
76
1185.16.113 by mbp at sourcefrog
Add topo_sort utility function
77
    def test_tsort_1(self):
78
        """TopoSort simple nontrivial graph"""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
79
        self.assertSortAndIterate({0: [3],
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
80
                                   1: [4],
81
                                   2: [1, 4],
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
82
                                   3: [],
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
83
                                   4: [0, 3]}.items(),
84
                                  [3, 0, 4, 1, 2])
1185.16.115 by mbp at sourcefrog
Another topo_sort test
85
86
    def test_tsort_partial(self):
87
        """Topological sort with partial ordering.
88
4577.2.1 by Maarten Bosmans
Modify test_tsort_partial to accept multiple valid orderings.
89
        Multiple correct orderings are possible, so test for 
90
        correctness, not for exact match on the resulting list.
1185.16.115 by mbp at sourcefrog
Another topo_sort test
91
        """
4577.2.1 by Maarten Bosmans
Modify test_tsort_partial to accept multiple valid orderings.
92
        self.assertSortAndIterateOrder([(0, []),
1570.1.7 by Robert Collins
Replace the slow topo_sort routine with a much faster one for non trivial datasets.
93
                                   (1, [0]),
94
                                   (2, [0]),
95
                                   (3, [0]),
96
                                   (4, [1, 2, 3]),
97
                                   (5, [1, 2]),
98
                                   (6, [1, 2]),
99
                                   (7, [2, 3]),
4577.2.1 by Maarten Bosmans
Modify test_tsort_partial to accept multiple valid orderings.
100
                                   (8, [0, 1, 4, 5, 6])])
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
101
2490.2.31 by Aaron Bentley
Fix iter_topo_order to permit un-included parents
102
    def test_tsort_unincluded_parent(self):
103
        """Sort nodes, but don't include some parents in the output"""
104
        self.assertSortAndIterate([(0, [1]),
105
                                   (1, [2])],
106
                                   [1, 0])
107
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
108
109
class MergeSortTests(TestCase):
110
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
111
    def assertSortAndIterate(self, graph, branch_tip, result_list,
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
112
            generate_revno, mainline_revisions=None):
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
113
        """Check that merge based sorting and iter_topo_order on graph works."""
3613.1.1 by John Arbash Meinel
Fix the merge_sort code so that it properly increments.
114
        value = merge_sort(graph, branch_tip,
115
                           mainline_revisions=mainline_revisions,
116
                           generate_revno=generate_revno)
117
        if result_list != value:
118
            import pprint
119
            self.assertEqualDiff(pprint.pformat(result_list),
120
                                 pprint.pformat(value))
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
121
        self.assertEquals(result_list,
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
122
            merge_sort(graph, branch_tip, mainline_revisions=mainline_revisions,
123
                generate_revno=generate_revno))
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
124
        self.assertEqual(result_list,
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
125
            list(MergeSorter(
126
                graph,
127
                branch_tip,
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
128
                mainline_revisions=mainline_revisions,
129
                generate_revno=generate_revno,
130
                ).iter_topo_order()))
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
131
132
    def test_merge_sort_empty(self):
133
        # sorting of an emptygraph does not error
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
134
        self.assertSortAndIterate({}, None, [], False)
135
        self.assertSortAndIterate({}, None, [], True)
3236.2.1 by Michael Hudson
test and fix
136
        self.assertSortAndIterate({}, NULL_REVISION, [], False)
137
        self.assertSortAndIterate({}, NULL_REVISION, [], True)
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
138
139
    def test_merge_sort_not_empty_no_tip(self):
140
        # merge sorting of a branch starting with None should result
141
        # in an empty list: no revisions are dragged in.
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
142
        self.assertSortAndIterate({0: []}.items(), None, [], False)
143
        self.assertSortAndIterate({0: []}.items(), None, [], True)
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
144
145
    def test_merge_sort_one_revision(self):
146
        # sorting with one revision as the tip returns the correct fields:
147
        # sequence - 0, revision id, merge depth - 0, end_of_merge
148
        self.assertSortAndIterate({'id': []}.items(),
149
                                  'id',
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
150
                                  [(0, 'id', 0, True)],
151
                                  False)
152
        self.assertSortAndIterate({'id': []}.items(),
153
                                  'id',
154
                                  [(0, 'id', 0, (1,), True)],
155
                                  True)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
156
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
157
    def test_sequence_numbers_increase_no_merges(self):
158
        # emit a few revisions with no merges to check the sequence
159
        # numbering works in trivial cases
160
        self.assertSortAndIterate(
161
            {'A': [],
162
             'B': ['A'],
163
             'C': ['B']}.items(),
164
            'C',
165
            [(0, 'C', 0, False),
166
             (1, 'B', 0, False),
167
             (2, 'A', 0, True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
168
             ],
169
            False
170
            )
171
        self.assertSortAndIterate(
172
            {'A': [],
173
             'B': ['A'],
174
             'C': ['B']}.items(),
175
            'C',
176
            [(0, 'C', 0, (3,), False),
177
             (1, 'B', 0, (2,), False),
178
             (2, 'A', 0, (1,), True),
179
             ],
180
            True
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
181
            )
182
183
    def test_sequence_numbers_increase_with_merges(self):
184
        # test that sequence numbers increase across merges
185
        self.assertSortAndIterate(
186
            {'A': [],
187
             'B': ['A'],
188
             'C': ['A', 'B']}.items(),
189
            'C',
190
            [(0, 'C', 0, False),
191
             (1, 'B', 1, True),
192
             (2, 'A', 0, True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
193
             ],
194
            False
195
            )
196
        self.assertSortAndIterate(
197
            {'A': [],
198
             'B': ['A'],
199
             'C': ['A', 'B']}.items(),
200
            'C',
201
            [(0, 'C', 0, (2,), False),
202
             (1, 'B', 1, (1,1,1), True),
203
             (2, 'A', 0, (1,), True),
204
             ],
205
            True
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
206
            )
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
207
208
    def test_merge_sort_race(self):
209
        # A
210
        # |
211
        # B-.
212
        # |\ \
213
        # | | C
214
        # | |/
215
        # | D
216
        # |/
217
        # F
218
        graph = {'A': [],
219
                 'B': ['A'],
220
                 'C': ['B'],
221
                 'D': ['B', 'C'],
222
                 'F': ['B', 'D'],
223
                 }
224
        self.assertSortAndIterate(graph, 'F',
225
            [(0, 'F', 0, (3,), False),
226
             (1, 'D', 1, (2,2,1), False),
3170.3.8 by John Arbash Meinel
Finish the rest of the review feedback.
227
             (2, 'C', 1, (2,1,1), True), # XXX: Shouldn't it be merge_depth=2?
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
228
             (3, 'B', 0, (2,), False),
229
             (4, 'A', 0, (1,), True),
230
             ], True)
231
        # A
232
        # |
233
        # B-.
234
        # |\ \
235
        # | X C
236
        # | |/
237
        # | D
238
        # |/
239
        # F
240
        graph = {'A': [],
241
                 'B': ['A'],
242
                 'C': ['B'],
243
                 'X': ['B'],
244
                 'D': ['X', 'C'],
245
                 'F': ['B', 'D'],
246
                 }
247
        self.assertSortAndIterate(graph, 'F',
248
            [(0, 'F', 0, (3,), False),
249
             (1, 'D', 1, (2,1,2), False),
250
             (2, 'C', 2, (2,2,1), True),
251
             (3, 'X', 1, (2,1,1), True),
252
             (4, 'B', 0, (2,), False),
253
             (5, 'A', 0, (1,), True),
254
             ], True)
255
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
256
    def test_merge_depth_with_nested_merges(self):
257
        # the merge depth marker should reflect the depth of the revision
258
        # in terms of merges out from the mainline
259
        # revid, depth, parents:
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
260
        #  A 0   [D, B]
261
        #  B  1  [C, F]
262
        #  C  1  [H]
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
263
        #  D 0   [H, E]
264
        #  E  1  [G, F]
265
        #  F   2 [G]
266
        #  G  1  [H]
267
        #  H 0
268
        self.assertSortAndIterate(
269
            {'A': ['D', 'B'],
270
             'B': ['C', 'F'],
271
             'C': ['H'],
272
             'D': ['H', 'E'],
273
             'E': ['G', 'F'],
274
             'F': ['G'],
275
             'G': ['H'],
276
             'H': []
277
             }.items(),
278
            'A',
279
            [(0, 'A', 0, False),
280
             (1, 'B', 1, False),
281
             (2, 'C', 1, True),
282
             (3, 'D', 0, False),
283
             (4, 'E', 1, False),
284
             (5, 'F', 2, True),
285
             (6, 'G', 1, True),
286
             (7, 'H', 0, True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
287
             ],
288
            False
289
            )
290
        self.assertSortAndIterate(
291
            {'A': ['D', 'B'],
292
             'B': ['C', 'F'],
293
             'C': ['H'],
294
             'D': ['H', 'E'],
295
             'E': ['G', 'F'],
296
             'F': ['G'],
297
             'G': ['H'],
298
             'H': []
299
             }.items(),
300
            'A',
301
            [(0, 'A', 0, (3,),  False),
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
302
             (1, 'B', 1, (1,3,2), False),
303
             (2, 'C', 1, (1,3,1), True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
304
             (3, 'D', 0, (2,), False),
305
             (4, 'E', 1, (1,1,2), False),
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
306
             (5, 'F', 2, (1,2,1), True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
307
             (6, 'G', 1, (1,1,1), True),
308
             (7, 'H', 0, (1,), True),
309
             ],
310
            True
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
311
            )
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
312
313
    def test_dotted_revnos_with_simple_merges(self):
314
        # A         1
315
        # |\
316
        # B C       2, 1.1.1
317
        # | |\
318
        # D E F     3, 1.1.2, 1.2.1
319
        # |/ /|
320
        # G H I     4, 1.2.2, 1.3.1
321
        # |/ /
322
        # J K       5, 1.3.2
323
        # |/
324
        # L         6
325
        self.assertSortAndIterate(
326
            {'A': [],
327
             'B': ['A'],
328
             'C': ['A'],
329
             'D': ['B'],
330
             'E': ['C'],
331
             'F': ['C'],
332
             'G': ['D', 'E'],
333
             'H': ['F'],
334
             'I': ['F'],
335
             'J': ['G', 'H'],
336
             'K': ['I'],
337
             'L': ['J', 'K'],
338
            }.items(),
339
            'L',
340
            [(0, 'L', 0, (6,), False),
3170.3.2 by John Arbash Meinel
Implement the new dotted revision numbering.
341
             (1, 'K', 1, (1,3,2), False),
342
             (2, 'I', 1, (1,3,1), True),
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
343
             (3, 'J', 0, (5,), False),
3170.3.2 by John Arbash Meinel
Implement the new dotted revision numbering.
344
             (4, 'H', 1, (1,2,2), False),
345
             (5, 'F', 1, (1,2,1), True),
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
346
             (6, 'G', 0, (4,), False),
347
             (7, 'E', 1, (1,1,2), False),
348
             (8, 'C', 1, (1,1,1), True),
349
             (9, 'D', 0, (3,), False),
350
             (10, 'B', 0, (2,), False),
351
             (11, 'A', 0, (1,),  True),
352
             ],
353
            True
354
            )
355
        # Adding a shortcut from the first revision should not change any of
356
        # the existing numbers
357
        self.assertSortAndIterate(
358
            {'A': [],
359
             'B': ['A'],
360
             'C': ['A'],
361
             'D': ['B'],
362
             'E': ['C'],
363
             'F': ['C'],
364
             'G': ['D', 'E'],
365
             'H': ['F'],
366
             'I': ['F'],
367
             'J': ['G', 'H'],
368
             'K': ['I'],
369
             'L': ['J', 'K'],
370
             'M': ['A'],
371
             'N': ['L', 'M'],
372
            }.items(),
373
            'N',
374
            [(0, 'N', 0, (7,), False),
3170.3.2 by John Arbash Meinel
Implement the new dotted revision numbering.
375
             (1, 'M', 1, (1,4,1), True),
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
376
             (2, 'L', 0, (6,), False),
3170.3.2 by John Arbash Meinel
Implement the new dotted revision numbering.
377
             (3, 'K', 1, (1,3,2), False),
378
             (4, 'I', 1, (1,3,1), True),
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
379
             (5, 'J', 0, (5,), False),
3170.3.2 by John Arbash Meinel
Implement the new dotted revision numbering.
380
             (6, 'H', 1, (1,2,2), False),
381
             (7, 'F', 1, (1,2,1), True),
3170.3.1 by John Arbash Meinel
Write up a simple test that is getting ready to fix up deeply nested dotted revnos.
382
             (8, 'G', 0, (4,), False),
383
             (9, 'E', 1, (1,1,2), False),
384
             (10, 'C', 1, (1,1,1), True),
385
             (11, 'D', 0, (3,), False),
386
             (12, 'B', 0, (2,), False),
387
             (13, 'A', 0, (1,),  True),
388
             ],
389
            True
390
            )
391
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
392
    def test_end_of_merge_not_last_revision_in_branch(self):
393
        # within a branch only the last revision gets an
394
        # end of merge marker.
395
        self.assertSortAndIterate(
396
            {'A': ['B'],
397
             'B': [],
398
             },
399
            'A',
400
            [(0, 'A', 0, False),
401
             (1, 'B', 0, True)
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
402
             ],
403
            False
404
            )
405
        self.assertSortAndIterate(
406
            {'A': ['B'],
407
             'B': [],
408
             },
409
            'A',
410
            [(0, 'A', 0, (2,), False),
411
             (1, 'B', 0, (1,), True)
412
             ],
413
            True
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
414
            )
415
416
    def test_end_of_merge_multiple_revisions_merged_at_once(self):
417
        # when multiple branches are merged at once, both of their
418
        # branch-endpoints should be listed as end-of-merge.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
419
        # Also, the order of the multiple merges should be
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
420
        # left-right shown top to bottom.
421
        # * means end of merge
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
422
        # A 0    [H, B, E]
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
423
        # B  1   [D, C]
424
        # C   2  [D]       *
425
        # D  1   [H]       *
426
        # E  1   [G, F]
427
        # F   2  [G]       *
428
        # G  1   [H]       *
429
        # H 0    []        *
430
        self.assertSortAndIterate(
431
            {'A': ['H', 'B', 'E'],
432
             'B': ['D', 'C'],
433
             'C': ['D'],
434
             'D': ['H'],
435
             'E': ['G', 'F'],
436
             'F': ['G'],
437
             'G': ['H'],
438
             'H': [],
439
             },
440
            'A',
441
            [(0, 'A', 0, False),
442
             (1, 'B', 1, False),
443
             (2, 'C', 2, True),
444
             (3, 'D', 1, True),
445
             (4, 'E', 1, False),
446
             (5, 'F', 2, True),
447
             (6, 'G', 1, True),
448
             (7, 'H', 0, True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
449
             ],
450
            False
451
            )
452
        self.assertSortAndIterate(
453
            {'A': ['H', 'B', 'E'],
454
             'B': ['D', 'C'],
455
             'C': ['D'],
456
             'D': ['H'],
457
             'E': ['G', 'F'],
458
             'F': ['G'],
459
             'G': ['H'],
460
             'H': [],
461
             },
462
            'A',
463
            [(0, 'A', 0, (2,), False),
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
464
             (1, 'B', 1, (1,3,2), False),
465
             (2, 'C', 2, (1,4,1), True),
466
             (3, 'D', 1, (1,3,1), True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
467
             (4, 'E', 1, (1,1,2), False),
3170.3.4 by John Arbash Meinel
Update the tests for the new revision numbering.
468
             (5, 'F', 2, (1,2,1), True),
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
469
             (6, 'G', 1, (1,1,1), True),
470
             (7, 'H', 0, (1,), True),
471
             ],
472
            True
1624.1.2 by Robert Collins
Add MergeSort facility to bzrlib.tsort.
473
            )
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
474
475
    def test_mainline_revs_partial(self):
476
        # when a mainline_revisions list is passed this must
477
        # override the graphs idea of mainline, and must also
478
        # truncate the output to the specified range, if needed.
479
        # so we test both at once: a mainline_revisions list that
480
        # disagrees with the graph about which revs are 'mainline'
481
        # and also truncates the output.
482
        # graph:
483
        # A 0 [E, B]
484
        # B 1 [D, C]
485
        # C 2 [D]
486
        # D 1 [E]
487
        # E 0
488
        # with a mainline of NONE,E,A (the inferred one) this will show the merge
489
        # depths above.
490
        # with a overriden mainline of NONE,E,D,B,A it should show:
491
        # A 0
492
        # B 0
493
        # C 1
494
        # D 0
495
        # E 0
496
        # and thus when truncated to D,B,A it should show
497
        # A 0
498
        # B 0
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
499
        # C 1
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
500
        # because C is brought in by B in this view and D
501
        # is the terminating revision id
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
502
        # this should also preserve revision numbers: C should still be 2.1.1
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
503
        self.assertSortAndIterate(
504
            {'A': ['E', 'B'],
505
             'B': ['D', 'C'],
506
             'C': ['D'],
507
             'D': ['E'],
508
             'E': []
509
             },
510
            'A',
511
            [(0, 'A', 0, False),
512
             (1, 'B', 0, False),
513
             (2, 'C', 1, True),
514
             ],
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
515
            False,
516
            mainline_revisions=['D', 'B', 'A']
517
            )
518
        self.assertSortAndIterate(
519
            {'A': ['E', 'B'],
520
             'B': ['D', 'C'],
521
             'C': ['D'],
522
             'D': ['E'],
523
             'E': []
524
             },
525
            'A',
526
            [(0, 'A', 0, (4,), False),
527
             (1, 'B', 0, (3,), False),
528
             (2, 'C', 1, (2,1,1), True),
529
             ],
530
            True,
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
531
            mainline_revisions=['D', 'B', 'A']
532
            )
533
534
    def test_mainline_revs_with_none(self):
535
        # a simple test to ensure that a mainline_revs
536
        # list which goes all the way to None works
537
        self.assertSortAndIterate(
538
            {'A': [],
539
             },
540
            'A',
541
            [(0, 'A', 0, True),
542
             ],
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
543
            False,
544
            mainline_revisions=[None, 'A']
545
            )
546
        self.assertSortAndIterate(
547
            {'A': [],
548
             },
549
            'A',
550
            [(0, 'A', 0, (1,), True),
551
             ],
552
            True,
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
553
            mainline_revisions=[None, 'A']
554
            )
555
3533.2.1 by John Arbash Meinel
(bug #243536) tsort.merge_sorted() should work even with a ghost in mainline.
556
    def test_mainline_revs_with_ghost(self):
557
        # We have a mainline, but the end of it is actually a ghost
558
        # The graph that is passed to tsort has had ghosts filtered out, but
559
        # the mainline history has not.
560
        self.assertSortAndIterate(
561
            {'B':[],
562
             'C':['B']}.items(),
563
            'C',
564
            [(0, 'C', 0, (2,), False),
565
             (1, 'B', 0, (1,), True),
566
             ],
567
             True, mainline_revisions=['A', 'B', 'C'])
568
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
569
    def test_parallel_root_sequence_numbers_increase_with_merges(self):
570
        """When there are parallel roots, check their revnos."""
571
        self.assertSortAndIterate(
572
            {'A': [],
573
             'B': [],
574
             'C': ['A', 'B']}.items(),
575
            'C',
576
            [(0, 'C', 0, (2,), False),
577
             (1, 'B', 1, (0,1,1), True),
578
             (2, 'A', 0, (1,), True),
579
             ],
580
            True
581
            )
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
582
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
583
    def test_revnos_are_globally_assigned(self):
584
        """revnos are assigned according to the revision they derive from."""
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
585
        # in this test we setup a number of branches that all derive from
586
        # the first revision, and then merge them one at a time, which
1988.4.1 by Robert Collins
bzrlib.tsort.merge_sorted now accepts 'generate_revnos'. This parameter
587
        # should give the revisions as they merge numbers still deriving from
588
        # the revision were based on.
589
        # merge 3: J: ['G', 'I']
590
        # branch 3:
591
        #  I: ['H']
592
        #  H: ['A']
593
        # merge 2: G: ['D', 'F']
594
        # branch 2:
595
        #  F: ['E']
596
        #  E: ['A']
597
        # merge 1: D: ['A', 'C']
598
        # branch 1:
599
        #  C: ['B']
600
        #  B: ['A']
601
        # root: A: []
602
        self.assertSortAndIterate(
603
            {'J': ['G', 'I'],
604
             'I': ['H',],
605
             'H': ['A'],
606
             'G': ['D', 'F'],
607
             'F': ['E'],
608
             'E': ['A'],
609
             'D': ['A', 'C'],
610
             'C': ['B'],
611
             'B': ['A'],
612
             'A': [],
613
             }.items(),
614
            'J',
615
            [(0, 'J', 0, (4,), False),
616
             (1, 'I', 1, (1,3,2), False),
617
             (2, 'H', 1, (1,3,1), True),
618
             (3, 'G', 0, (3,), False),
619
             (4, 'F', 1, (1,2,2), False),
620
             (5, 'E', 1, (1,2,1), True),
621
             (6, 'D', 0, (2,), False),
622
             (7, 'C', 1, (1,1,2), False),
623
             (8, 'B', 1, (1,1,1), True),
624
             (9, 'A', 0, (1,), True),
625
             ],
626
            True
627
            )
3613.1.1 by John Arbash Meinel
Fix the merge_sort code so that it properly increments.
628
629
    def test_roots_and_sub_branches_versus_ghosts(self):
630
        """Extra roots and their mini branches use the same numbering.
631
632
        All of them use the 0-node numbering.
633
        """
634
        #       A D   K
635
        #       | |\  |\
636
        #       B E F L M
637
        #       | |/  |/
638
        #       C G   N
639
        #       |/    |\
640
        #       H I   O P
641
        #       |/    |/
642
        #       J     Q
643
        #       |.---'
644
        #       R
645
        self.assertSortAndIterate(
646
            {'A': [],
647
             'B': ['A'],
648
             'C': ['B'],
649
             'D': [],
650
             'E': ['D'],
651
             'F': ['D'],
652
             'G': ['E', 'F'],
653
             'H': ['C', 'G'],
654
             'I': [],
655
             'J': ['H', 'I'],
656
             'K': [],
657
             'L': ['K'],
658
             'M': ['K'],
659
             'N': ['L', 'M'],
660
             'O': ['N'],
661
             'P': ['N'],
662
             'Q': ['O', 'P'],
663
             'R': ['J', 'Q'],
664
            }.items(),
665
            'R',
666
            [( 0, 'R', 0, (6,), False),
667
             ( 1, 'Q', 1, (0,4,5), False),
668
             ( 2, 'P', 2, (0,6,1), True),
669
             ( 3, 'O', 1, (0,4,4), False),
670
             ( 4, 'N', 1, (0,4,3), False),
671
             ( 5, 'M', 2, (0,5,1), True),
672
             ( 6, 'L', 1, (0,4,2), False),
673
             ( 7, 'K', 1, (0,4,1), True),
674
             ( 8, 'J', 0, (5,), False),
675
             ( 9, 'I', 1, (0,3,1), True),
676
             (10, 'H', 0, (4,), False),
677
             (11, 'G', 1, (0,1,3), False),
678
             (12, 'F', 2, (0,2,1), True),
679
             (13, 'E', 1, (0,1,2), False),
680
             (14, 'D', 1, (0,1,1), True),
681
             (15, 'C', 0, (3,), False),
682
             (16, 'B', 0, (2,), False),
683
             (17, 'A', 0, (1,), True),
684
             ],
685
            True
686
            )