~bzr-pqm/bzr/bzr.dev

1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
1
# Copyright (C) 2005 by Canonical Ltd
2
# -*- coding: utf-8 -*-
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
3
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
8
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
13
#
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
19
"""Black-box tests for bzr log."""
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
20
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
21
import os
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
22
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
23
import bzrlib
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
24
from bzrlib.tests.blackbox import ExternalBase
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
25
from bzrlib.tests import TestCaseInTempDir
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
26
27
28
class TestLog(ExternalBase):
29
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
30
    def _prepare(self):
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
31
        self.runbzr("init")
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
32
        self.build_tree(['hello.txt', 'goodbye.txt', 'meep.txt'])
1540.2.6 by Robey Pointer
make 'log' and 'status' treat '-r N..' as implicitly '-r N..-1'
33
        self.runbzr("add hello.txt")
1553.4.2 by Michael Ellerman
Make bzr log -r .. work, fixes bug #4609. Add a bunch of tests to make sure
34
        self.runbzr("commit -m message1 hello.txt")
35
        self.runbzr("add goodbye.txt")
36
        self.runbzr("commit -m message2 goodbye.txt")
37
        self.runbzr("add meep.txt")
38
        self.runbzr("commit -m message3 meep.txt")
39
        self.full_log = self.runbzr("log")[0]
40
41
    def test_log_null_end_revspec(self):
42
        self._prepare()
43
        self.assertTrue('revno: 1\n' in self.full_log)
44
        self.assertTrue('revno: 2\n' in self.full_log)
45
        self.assertTrue('revno: 3\n' in self.full_log)
46
        self.assertTrue('message:\n  message1\n' in self.full_log)
47
        self.assertTrue('message:\n  message2\n' in self.full_log)
48
        self.assertTrue('message:\n  message3\n' in self.full_log)
49
50
        log = self.runbzr("log -r 1..")[0]
51
        self.assertEquals(log, self.full_log)
52
53
    def test_log_null_begin_revspec(self):
54
        self._prepare()
55
        log = self.runbzr("log -r ..3")[0]
56
        self.assertEquals(self.full_log, log)
57
58
    def test_log_null_both_revspecs(self):
59
        self._prepare()
60
        log = self.runbzr("log -r ..")[0]
61
        self.assertEquals(self.full_log, log)
62
63
    def test_log_negative_begin_revspec_full_log(self):
64
        self._prepare()
65
        log = self.runbzr("log -r -3..")[0]
66
        self.assertEquals(self.full_log, log)
67
68
    def test_log_negative_both_revspec_full_log(self):
69
        self._prepare()
70
        log = self.runbzr("log -r -3..-1")[0]
71
        self.assertEquals(self.full_log, log)
72
73
    def test_log_negative_both_revspec_partial(self):
74
        self._prepare()
75
        log = self.runbzr("log -r -3..-2")[0]
76
        self.assertTrue('revno: 1\n' in log)
77
        self.assertTrue('revno: 2\n' in log)
78
        self.assertTrue('revno: 3\n' not in log)
79
80
    def test_log_negative_begin_revspec(self):
81
        self._prepare()
82
        log = self.runbzr("log -r -2..")[0]
83
        self.assertTrue('revno: 1\n' not in log)
84
        self.assertTrue('revno: 2\n' in log)
85
        self.assertTrue('revno: 3\n' in log)
86
87
    def test_log_postive_revspecs(self):
88
        self._prepare()
89
        log = self.runbzr("log -r 1..3")[0]
90
        self.assertEquals(self.full_log, log)
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
91
1907.4.2 by Matthieu Moy
Make log work nicely with revno:N:path too.
92
    def test_log_revno_n_path(self):
93
        os.mkdir('branch1')
94
        os.chdir('branch1')
95
        self._prepare()
96
        os.chdir('..')
97
        os.mkdir('branch2')
98
        os.chdir('branch2')
99
        self._prepare()
100
        os.chdir('..')
101
        log = self.runbzr("log -r revno:2:branch1..revno:3:branch2",
102
                          retcode=3)[0]
103
        log = self.runbzr("log -r revno:1:branch2..revno:3:branch2")[0]
104
        self.assertEquals(self.full_log, log)
105
        log = self.runbzr("log -r revno:1:branch2")[0]
106
        self.assertTrue('revno: 1\n' in log)
107
        self.assertTrue('revno: 2\n' not in log)
108
        self.assertTrue('branch nick: branch2\n' in log)
109
        self.assertTrue('branch nick: branch1\n' not in log)
110
        
1624.1.3 by Robert Collins
Convert log to use the new tsort.merge_sort routine.
111
112
class TestLogMerges(ExternalBase):
113
114
    def test_merges_are_indented_by_level(self):
115
        self.build_tree(['parent/'])
116
        self.run_bzr('init', 'parent')
117
        self.run_bzr('commit', '-m', 'first post', '--unchanged', 'parent')
118
        self.run_bzr('branch', 'parent', 'child')
119
        self.run_bzr('commit', '-m', 'branch 1', '--unchanged', 'child')
120
        self.run_bzr('branch', 'child', 'smallerchild')
121
        self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
122
        os.chdir('child')
123
        self.run_bzr('merge', '../smallerchild')
124
        self.run_bzr('commit', '-m', 'merge branch 2')
125
        os.chdir('../parent')
126
        self.run_bzr('merge', '../child')
127
        self.run_bzr('commit', '-m', 'merge branch 1')
128
        out,err = self.run_bzr('log')
129
        # the log will look something like:
130
#        self.assertEqual("""\
131
#------------------------------------------------------------
132
#revno: 2
133
#committer: Robert Collins <foo@example.com>
134
#branch nick: parent
135
#timestamp: Tue 2006-03-28 22:31:40 +1100
136
#message:
137
#  merge branch 1
138
#    ------------------------------------------------------------
139
#    merged: foo@example.com-20060328113140-91f43cfb46dc2863
140
#    committer: Robert Collins <foo@example.com>
141
#    branch nick: child
142
#    timestamp: Tue 2006-03-28 22:31:40 +1100
143
#    message:
144
#      merge branch 2
145
#        ------------------------------------------------------------
146
#        merged: foo@example.com-20060328113140-1ba24f850a0ef573
147
#        committer: Robert Collins <foo@example.com>
148
#        branch nick: smallerchild
149
#        timestamp: Tue 2006-03-28 22:31:40 +1100
150
#        message:
151
#          branch 2
152
#    ------------------------------------------------------------
153
#    merged: foo@example.com-20060328113140-5749a4757a8ac792
154
#    committer: Robert Collins <foo@example.com>
155
#    branch nick: child
156
#    timestamp: Tue 2006-03-28 22:31:40 +1100
157
#    message:
158
#      branch 1
159
#------------------------------------------------------------
160
#revno: 1
161
#committer: Robert Collins <foo@example.com>
162
#branch nick: parent
163
#timestamp: Tue 2006-03-28 22:31:39 +1100
164
#message:
165
#  first post
166
#""", out)
167
        # but we dont have a nice pattern matcher hooked up yet, so:
168
        # we check for the indenting of the commit message:
169
        self.assertTrue('  merge branch 1' in out)
170
        self.assertTrue('      merge branch 2' in out)
171
        self.assertTrue('          branch 2' in out)
172
        self.assertTrue('      branch 1' in out)
173
        self.assertTrue('  first post' in out)
174
        self.assertEqual('', err)
1685.1.5 by John Arbash Meinel
Merged test_log.py.moved into test_log.py
175
176
177
class TestLogEncodings(TestCaseInTempDir):
178
179
    _mu = u'\xb5'
180
    _message = u'Message with \xb5'
181
182
    # Encodings which can encode mu
183
    good_encodings = [
184
        'utf-8',
185
        'latin-1',
186
        'iso-8859-1',
187
        'cp437', # Common windows encoding
188
        'cp1251', # Alexander Belchenko's windows encoding
189
        'cp1258', # Common windows encoding
190
    ]
191
    # Encodings which cannot encode mu
192
    bad_encodings = [
193
        'ascii',
194
        'iso-8859-2',
195
        'koi8_r',
196
    ]
197
198
    def setUp(self):
199
        TestCaseInTempDir.setUp(self)
200
        self.user_encoding = bzrlib.user_encoding
201
202
    def tearDown(self):
203
        bzrlib.user_encoding = self.user_encoding
204
        TestCaseInTempDir.tearDown(self)
205
206
    def create_branch(self):
207
        bzr = self.run_bzr
208
        bzr('init')
209
        open('a', 'wb').write('some stuff\n')
210
        bzr('add', 'a')
211
        bzr('commit', '-m', self._message)
212
213
    def try_encoding(self, encoding, fail=False):
214
        bzr = self.run_bzr
215
        if fail:
216
            self.assertRaises(UnicodeEncodeError,
217
                self._mu.encode, encoding)
218
            encoded_msg = self._message.encode(encoding, 'replace')
219
        else:
220
            encoded_msg = self._message.encode(encoding)
221
222
        old_encoding = bzrlib.user_encoding
223
        # This test requires that 'run_bzr' uses the current
224
        # bzrlib, because we override user_encoding, and expect
225
        # it to be used
226
        try:
227
            bzrlib.user_encoding = 'ascii'
228
            # We should be able to handle any encoding
229
            out, err = bzr('log', encoding=encoding)
230
            if not fail:
231
                # Make sure we wrote mu as we expected it to exist
232
                self.assertNotEqual(-1, out.find(encoded_msg))
233
                out_unicode = out.decode(encoding)
234
                self.assertNotEqual(-1, out_unicode.find(self._message))
235
            else:
236
                self.assertNotEqual(-1, out.find('Message with ?'))
237
        finally:
238
            bzrlib.user_encoding = old_encoding
239
240
    def test_log_handles_encoding(self):
241
        self.create_branch()
242
243
        for encoding in self.good_encodings:
244
            self.try_encoding(encoding)
245
246
    def test_log_handles_bad_encoding(self):
247
        self.create_branch()
248
249
        for encoding in self.bad_encodings:
250
            self.try_encoding(encoding, fail=True)
251
252
    def test_stdout_encoding(self):
253
        bzr = self.run_bzr
254
        bzrlib.user_encoding = "cp1251"
255
256
        bzr('init')
257
        self.build_tree(['a'])
258
        bzr('add', 'a')
259
        bzr('commit', '-m', u'\u0422\u0435\u0441\u0442')
260
        stdout, stderr = self.run_bzr('log', encoding='cp866')
261
262
        message = stdout.splitlines()[-1]
263
264
        # explanation of the check:
265
        # u'\u0422\u0435\u0441\u0442' is word 'Test' in russian
266
        # in cp866  encoding this is string '\x92\xa5\xe1\xe2'
267
        # in cp1251 encoding this is string '\xd2\xe5\xf1\xf2'
268
        # This test should check that output of log command
269
        # encoded to sys.stdout.encoding
270
        test_in_cp866 = '\x92\xa5\xe1\xe2'
271
        test_in_cp1251 = '\xd2\xe5\xf1\xf2'
272
        # Make sure the log string is encoded in cp866
273
        self.assertEquals(test_in_cp866, message[2:])
274
        # Make sure the cp1251 string is not found anywhere
275
        self.assertEquals(-1, stdout.find(test_in_cp1251))
276