~bzr-pqm/bzr/bzr.dev

2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
1
# Copyright (C) 2006 Canonical Ltd
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Whitebox tests for annotate functionality."""
18
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
19
import codecs
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
20
from cStringIO import StringIO
21
22
from bzrlib import (
23
    annotate,
24
    conflicts,
25
    errors,
26
    tests,
27
    trace,
28
    )
29
30
1551.9.19 by Aaron Bentley
Merge from bzr.dev
31
def annotation(text):
32
    return [tuple(l.split(' ', 1)) for l in text.splitlines(True)]
33
34
35
parent_1 = annotation("""\
36
rev1 a
37
rev2 b
38
rev3 c
39
rev4 d
40
rev5 e
41
""")
42
43
44
parent_2 = annotation("""\
45
rev1 a
46
rev3 c
47
rev4 d
48
rev6 f
49
rev7 e
50
rev8 h
51
""")
52
53
54
expected_2_1 = annotation("""\
55
rev1 a
56
blahblah b
57
rev3 c
58
rev4 d
59
rev7 e
60
""")
61
62
63
# a: in both, same value, kept
64
# b: in 1, kept
65
# c: in both, same value, kept
66
# d: in both, same value, kept
67
# e: 1 and 2 disagree, so it goes to blahblah
68
# f: in 2, but not in new, so ignored
69
# g: not in 1 or 2, so it goes to blahblah
70
# h: only in parent 2, so 2 gets it
71
expected_1_2_2 = annotation("""\
72
rev1 a
73
rev2 b
74
rev3 c
75
rev4 d
76
blahblah e
77
blahblah g
78
rev8 h
79
""")
80
81
82
new_1 = """\
83
a
84
b
85
c
86
d
87
e
88
""".splitlines(True)
89
90
91
new_2 = """\
92
a
93
b
94
c
95
d
96
e
97
g
98
h
99
""".splitlines(True)
100
101
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
102
class TestAnnotate(tests.TestCaseWithTransport):
103
104
    def create_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
105
        """create 2 trees with merges between them.
106
107
        rev-1 --+
108
         |      |
109
        rev-2  rev-1_1_1
110
         |      |
111
         +------+
112
         |
113
        rev-3
114
        """
115
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
116
        tree1 = self.make_branch_and_tree('tree1')
117
        self.build_tree_contents([('tree1/a', 'first\n')])
118
        tree1.add(['a'], ['a-id'])
119
        tree1.commit('a', rev_id='rev-1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
120
                     committer="joe@foo.com",
121
                     timestamp=1166046000.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
122
123
        tree2 = tree1.bzrdir.clone('tree2').open_workingtree()
124
125
        self.build_tree_contents([('tree1/a', 'first\nsecond\n')])
126
        tree1.commit('b', rev_id='rev-2',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
127
                     committer='joe@foo.com',
128
                     timestamp=1166046001.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
129
130
        self.build_tree_contents([('tree2/a', 'first\nthird\n')])
131
        tree2.commit('c', rev_id='rev-1_1_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
132
                     committer="barry@foo.com",
133
                     timestamp=1166046002.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
134
135
        num_conflicts = tree1.merge_from_branch(tree2.branch)
136
        self.assertEqual(1, num_conflicts)
137
138
        self.build_tree_contents([('tree1/a',
139
                                 'first\nsecond\nthird\n')])
140
        tree1.set_conflicts(conflicts.ConflictList())
141
        tree1.commit('merge 2', rev_id='rev-3',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
142
                     committer='sal@foo.com',
143
                     timestamp=1166046003.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
144
        return tree1, tree2
145
146
    def create_deeply_merged_trees(self):
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
147
        """Create some trees with a more complex merge history.
148
149
        rev-1 --+
150
         |      |
151
        rev-2  rev-1_1_1 --+
152
         |      |          |
153
         +------+          |
154
         |      |          |
155
        rev-3  rev-1_1_2  rev-1_1_1_1_1 --+
156
         |      |          |              |
157
         +------+          |              |
158
         |                 |              |
159
        rev-4             rev-1_1_1_1_2  rev-1_1_1_1_1_1_1
160
         |                 |              |
161
         +-----------------+              |
162
         |                                |
163
        rev-5                             |
164
         |                                |
165
         +--------------------------------+
166
         |
167
        rev-6
168
        """
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
169
        tree1, tree2 = self.create_merged_trees()
170
171
        tree3 = tree2.bzrdir.clone('tree3').open_workingtree()
172
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
173
        tree2.commit('noop', rev_id='rev-1_1_2')
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
174
        self.assertEqual(0, tree1.merge_from_branch(tree2.branch))
175
        tree1.commit('noop merge', rev_id='rev-4')
176
177
        self.build_tree_contents([('tree3/a', 'first\nthird\nfourth\n')])
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
178
        tree3.commit('four', rev_id='rev-1_1_1_1_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
179
                     committer='jerry@foo.com',
180
                     timestamp=1166046003.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
181
182
        tree4 = tree3.bzrdir.clone('tree4').open_workingtree()
183
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
184
        tree3.commit('noop', rev_id='rev-1_1_1_1_2',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
185
                     committer='jerry@foo.com',
186
                     timestamp=1166046004.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
187
        self.assertEqual(0, tree1.merge_from_branch(tree3.branch))
188
        tree1.commit('merge four', rev_id='rev-5')
189
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
190
        self.build_tree_contents([('tree4/a',
191
                                   'first\nthird\nfourth\nfifth\nsixth\n')])
192
        tree4.commit('five and six', rev_id='rev-1_1_1_1_1_1_1',
2182.3.12 by John Arbash Meinel
Force the timezone properly during tests which look at dates.
193
                     committer='george@foo.com',
194
                     timestamp=1166046005.00, timezone=0)
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
195
        self.assertEqual(0, tree1.merge_from_branch(tree4.branch))
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
196
        tree1.commit('merge five and six', rev_id='rev-6')
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
197
        return tree1
198
199
    def test_annotate_shows_dotted_revnos(self):
200
        tree1, tree2 = self.create_merged_trees()
201
202
        sio = StringIO()
203
        annotate.annotate_file(tree1.branch, 'rev-3', 'a-id',
204
                               to_file=sio)
205
        self.assertEqualDiff('1     joe@foo | first\n'
206
                             '2     joe@foo | second\n'
207
                             '1.1.1 barry@f | third\n',
208
                             sio.getvalue())
209
210
    def test_annotate_limits_dotted_revnos(self):
211
        """Annotate should limit dotted revnos to a depth of 12"""
212
        tree1 = self.create_deeply_merged_trees()
213
214
        sio = StringIO()
215
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
216
                               to_file=sio, verbose=False, full=False)
217
        self.assertEqualDiff('1            joe@foo | first\n'
218
                             '2            joe@foo | second\n'
219
                             '1.1.1        barry@f | third\n'
220
                             '1.1.1.1.1    jerry@f | fourth\n'
221
                             '1.1.1.1.1.1> george@ | fifth\n'
222
                             '                     | sixth\n',
223
                             sio.getvalue())
224
225
        sio = StringIO()
226
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
227
                               to_file=sio, verbose=False, full=True)
228
        self.assertEqualDiff('1            joe@foo | first\n'
229
                             '2            joe@foo | second\n'
230
                             '1.1.1        barry@f | third\n'
231
                             '1.1.1.1.1    jerry@f | fourth\n'
232
                             '1.1.1.1.1.1> george@ | fifth\n'
233
                             '1.1.1.1.1.1> george@ | sixth\n',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
234
                             sio.getvalue())
235
236
        # verbose=True shows everything, the full revno, user id, and date
237
        sio = StringIO()
238
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
239
                               to_file=sio, verbose=True, full=False)
240
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
241
                             '2             joe@foo.com    20061213 | second\n'
242
                             '1.1.1         barry@foo.com  20061213 | third\n'
243
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
244
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
245
                             '                                      | sixth\n',
246
                             sio.getvalue())
247
248
        sio = StringIO()
249
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
250
                               to_file=sio, verbose=True, full=True)
251
        self.assertEqualDiff('1             joe@foo.com    20061213 | first\n'
252
                             '2             joe@foo.com    20061213 | second\n'
253
                             '1.1.1         barry@foo.com  20061213 | third\n'
254
                             '1.1.1.1.1     jerry@foo.com  20061213 | fourth\n'
255
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | fifth\n'
256
                             '1.1.1.1.1.1.1 george@foo.com 20061213 | sixth\n',
257
                             sio.getvalue())
2245.3.1 by John Arbash Meinel
bzr annotate should use Branch's dotted revnos.
258
259
    def test_annotate_uses_branch_context(self):
260
        """Dotted revnos should use the Branch context.
261
262
        When annotating a non-mainline revision, the annotation should still
263
        use dotted revnos from the mainline.
264
        """
265
        tree1 = self.create_deeply_merged_trees()
266
267
        sio = StringIO()
268
        annotate.annotate_file(tree1.branch, 'rev-1_1_1_1_1_1_1', 'a-id',
269
                               to_file=sio, verbose=False, full=False)
270
        self.assertEqualDiff('1            joe@foo | first\n'
271
                             '1.1.1        barry@f | third\n'
272
                             '1.1.1.1.1    jerry@f | fourth\n'
273
                             '1.1.1.1.1.1> george@ | fifth\n'
274
                             '                     | sixth\n',
275
                             sio.getvalue())
276
2182.3.4 by John Arbash Meinel
add show-ids and test that nearby areas are collapsed without full
277
    def test_annotate_show_ids(self):
278
        tree1 = self.create_deeply_merged_trees()
279
280
        sio = StringIO()
281
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
282
                               to_file=sio, show_ids=True, full=False)
283
284
        # It looks better with real revision ids :)
285
        self.assertEqualDiff('            rev-1 | first\n'
286
                             '            rev-2 | second\n'
287
                             '        rev-1_1_1 | third\n'
288
                             '    rev-1_1_1_1_1 | fourth\n'
289
                             'rev-1_1_1_1_1_1_1 | fifth\n'
290
                             '                  | sixth\n',
291
                             sio.getvalue())
292
293
        sio = StringIO()
294
        annotate.annotate_file(tree1.branch, 'rev-6', 'a-id',
295
                               to_file=sio, show_ids=True, full=True)
296
297
        self.assertEqualDiff('            rev-1 | first\n'
298
                             '            rev-2 | second\n'
299
                             '        rev-1_1_1 | third\n'
300
                             '    rev-1_1_1_1_1 | fourth\n'
301
                             'rev-1_1_1_1_1_1_1 | fifth\n'
302
                             'rev-1_1_1_1_1_1_1 | sixth\n',
2182.3.3 by John Arbash Meinel
Add tests for annotate with dotted revnos.
303
                             sio.getvalue())
1551.9.19 by Aaron Bentley
Merge from bzr.dev
304
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
305
    def test_annotate_unicode_author(self):
306
        tree1 = self.make_branch_and_tree('tree1')
307
308
        self.build_tree_contents([('tree1/a', 'adi\xc3\xb3s')])
309
        tree1.add(['a'], ['a-id'])
310
        tree1.commit('a', rev_id='rev-1',
311
                     committer=u'Pepe P\xe9rez <pperez@ejemplo.com>',
312
                     timestamp=1166046000.00, timezone=0)
313
314
        self.build_tree_contents([('tree1/b', 'bye')])
315
        tree1.add(['b'], ['b-id'])
316
        tree1.commit('b', rev_id='rev-2',
317
                     committer=u'p\xe9rez',
318
                     timestamp=1166046000.00, timezone=0)
319
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
320
        # this passes if no exception is raised
321
        to_file = StringIO()
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
322
        annotate.annotate_file(tree1.branch, 'rev-1', 'a-id', to_file=to_file)
323
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
324
        sio = StringIO()
325
        to_file = codecs.getwriter('ascii')(sio)
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
326
        to_file.encoding = 'ascii' # codecs does not set it
327
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
2593.1.2 by Adeodato Simó
Improve tests a bit, actually checking for the replace encoding.
328
        self.assertEqualDiff('2   p?rez   | bye\n', sio.getvalue())
2593.1.1 by Adeodato Simó
Improve annotate to prevent unicode exceptions in certain situations.
329
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
330
        # test now with to_file.encoding = None
331
        to_file = tests.StringIOWrapper()
332
        to_file.encoding = None
333
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
334
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
335
336
        # and when it does not exist
337
        to_file = StringIO()
338
        annotate.annotate_file(tree1.branch, 'rev-2', 'b-id', to_file=to_file)
2593.1.5 by Adeodato Simó
Fix copy&paste bug in test, catched by John.
339
        self.assertContainsRe('2   p.rez   | bye\n', to_file.getvalue())
2593.1.3 by Adeodato Simó
Cope with to_file.encoding being None or not present.
340
1551.9.19 by Aaron Bentley
Merge from bzr.dev
341
342
class TestReannotate(tests.TestCase):
343
344
    def annotateEqual(self, expected, parents, newlines, revision_id):
345
        annotate_list = list(annotate.reannotate(parents, newlines,
346
                             revision_id))
347
        self.assertEqual(len(expected), len(annotate_list))
348
        for e, a in zip(expected, annotate_list):
349
            self.assertEqual(e, a)
350
351
    def test_reannotate(self):
352
        self.annotateEqual(parent_1, [parent_1], new_1, 'blahblah')
353
        self.annotateEqual(expected_2_1, [parent_2], new_1, 'blahblah')
354
        self.annotateEqual(expected_1_2_2, [parent_1, parent_2], new_2, 
355
                           'blahblah')