~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_log.py

  • Committer: John Arbash Meinel
  • Date: 2007-03-15 22:35:35 UTC
  • mto: This revision was merged to the branch mainline in revision 2363.
  • Revision ID: john@arbash-meinel.com-20070315223535-d3d4964oe1hc8zhg
Add an overzealous test, for Unicode support of _iter_changes.
For both knowns and unknowns.
And include a basic, if suboptimal, fix.
I would rather defer the decoding until we've determined that we are going to return the tuple.
There is still something broken with added files, but I'll get to that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
2
# -*- coding: utf-8 -*-
 
3
#
 
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.
 
8
#
 
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.
 
13
#
 
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
 
 
19
"""Black-box tests for bzr log."""
 
20
 
 
21
import os
 
22
 
 
23
import bzrlib
 
24
from bzrlib.tests.blackbox import ExternalBase
 
25
from bzrlib.tests import TestCaseInTempDir, TestCaseWithTransport
 
26
 
 
27
 
 
28
class TestLog(ExternalBase):
 
29
 
 
30
    def _prepare(self):
 
31
        self.runbzr("init")
 
32
        self.build_tree(['hello.txt', 'goodbye.txt', 'meep.txt'])
 
33
        self.runbzr("add hello.txt")
 
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)
 
91
 
 
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
        
 
111
    def test_log_nonexistent_file(self):
 
112
        # files that don't exist in either the basis tree or working tree
 
113
        # should give an error
 
114
        wt = self.make_branch_and_tree('.')
 
115
        out, err = self.run_bzr('log', 'does-not-exist', retcode=3)
 
116
        self.assertContainsRe(
 
117
            err, 'Path does not have any revision history: does-not-exist')
 
118
 
 
119
class TestLogMerges(ExternalBase):
 
120
 
 
121
    def test_merges_are_indented_by_level(self):
 
122
        self.build_tree(['parent/'])
 
123
        self.run_bzr('init', 'parent')
 
124
        self.run_bzr('commit', '-m', 'first post', '--unchanged', 'parent')
 
125
        self.run_bzr('branch', 'parent', 'child')
 
126
        self.run_bzr('commit', '-m', 'branch 1', '--unchanged', 'child')
 
127
        self.run_bzr('branch', 'child', 'smallerchild')
 
128
        self.run_bzr('commit', '-m', 'branch 2', '--unchanged', 'smallerchild')
 
129
        os.chdir('child')
 
130
        self.run_bzr('merge', '../smallerchild')
 
131
        self.run_bzr('commit', '-m', 'merge branch 2')
 
132
        os.chdir('../parent')
 
133
        self.run_bzr('merge', '../child')
 
134
        self.run_bzr('commit', '-m', 'merge branch 1')
 
135
        out,err = self.run_bzr('log')
 
136
        # the log will look something like:
 
137
#        self.assertEqual("""\
 
138
#------------------------------------------------------------
 
139
#revno: 2
 
140
#committer: Robert Collins <foo@example.com>
 
141
#branch nick: parent
 
142
#timestamp: Tue 2006-03-28 22:31:40 +1100
 
143
#message:
 
144
#  merge branch 1
 
145
#    ------------------------------------------------------------
 
146
#    revno: 1.1.2  
 
147
#    merged: foo@example.com-20060328113140-91f43cfb46dc2863
 
148
#    committer: Robert Collins <foo@example.com>
 
149
#    branch nick: child
 
150
#    timestamp: Tue 2006-03-28 22:31:40 +1100
 
151
#    message:
 
152
#      merge branch 2
 
153
#        ------------------------------------------------------------
 
154
#        revno: 1.1.1.1
 
155
#        merged: foo@example.com-20060328113140-1ba24f850a0ef573
 
156
#        committer: Robert Collins <foo@example.com>
 
157
#        branch nick: smallerchild
 
158
#        timestamp: Tue 2006-03-28 22:31:40 +1100
 
159
#        message:
 
160
#          branch 2
 
161
#    ------------------------------------------------------------
 
162
#    revno: 1.1.1
 
163
#    merged: foo@example.com-20060328113140-5749a4757a8ac792
 
164
#    committer: Robert Collins <foo@example.com>
 
165
#    branch nick: child
 
166
#    timestamp: Tue 2006-03-28 22:31:40 +1100
 
167
#    message:
 
168
#      branch 1
 
169
#------------------------------------------------------------
 
170
#revno: 1
 
171
#committer: Robert Collins <foo@example.com>
 
172
#branch nick: parent
 
173
#timestamp: Tue 2006-03-28 22:31:39 +1100
 
174
#message:
 
175
#  first post
 
176
#""", out)
 
177
        # but we dont have a nice pattern matcher hooked up yet, so:
 
178
        # we check for the indenting of the commit message and the 
 
179
        # revision numbers 
 
180
        self.assertTrue('revno: 2' in out)
 
181
        self.assertTrue('  merge branch 1' in out)
 
182
        self.assertTrue('    revno: 1.1.2' in out)
 
183
        self.assertTrue('      merge branch 2' in out)
 
184
        self.assertTrue('        revno: 1.1.1.1' in out)
 
185
        self.assertTrue('          branch 2' in out)
 
186
        self.assertTrue('    revno: 1.1.1' in out)
 
187
        self.assertTrue('      branch 1' in out)
 
188
        self.assertTrue('revno: 1' in out)
 
189
        self.assertTrue('  first post' in out)
 
190
        self.assertEqual('', err)
 
191
 
 
192
 
 
193
class TestLogEncodings(TestCaseInTempDir):
 
194
 
 
195
    _mu = u'\xb5'
 
196
    _message = u'Message with \xb5'
 
197
 
 
198
    # Encodings which can encode mu
 
199
    good_encodings = [
 
200
        'utf-8',
 
201
        'latin-1',
 
202
        'iso-8859-1',
 
203
        'cp437', # Common windows encoding
 
204
        'cp1251', # Alexander Belchenko's windows encoding
 
205
        'cp1258', # Common windows encoding
 
206
    ]
 
207
    # Encodings which cannot encode mu
 
208
    bad_encodings = [
 
209
        'ascii',
 
210
        'iso-8859-2',
 
211
        'koi8_r',
 
212
    ]
 
213
 
 
214
    def setUp(self):
 
215
        TestCaseInTempDir.setUp(self)
 
216
        self.user_encoding = bzrlib.user_encoding
 
217
 
 
218
    def tearDown(self):
 
219
        bzrlib.user_encoding = self.user_encoding
 
220
        TestCaseInTempDir.tearDown(self)
 
221
 
 
222
    def create_branch(self):
 
223
        bzr = self.run_bzr
 
224
        bzr('init')
 
225
        open('a', 'wb').write('some stuff\n')
 
226
        bzr('add', 'a')
 
227
        bzr('commit', '-m', self._message)
 
228
 
 
229
    def try_encoding(self, encoding, fail=False):
 
230
        bzr = self.run_bzr
 
231
        if fail:
 
232
            self.assertRaises(UnicodeEncodeError,
 
233
                self._mu.encode, encoding)
 
234
            encoded_msg = self._message.encode(encoding, 'replace')
 
235
        else:
 
236
            encoded_msg = self._message.encode(encoding)
 
237
 
 
238
        old_encoding = bzrlib.user_encoding
 
239
        # This test requires that 'run_bzr' uses the current
 
240
        # bzrlib, because we override user_encoding, and expect
 
241
        # it to be used
 
242
        try:
 
243
            bzrlib.user_encoding = 'ascii'
 
244
            # We should be able to handle any encoding
 
245
            out, err = bzr('log', encoding=encoding)
 
246
            if not fail:
 
247
                # Make sure we wrote mu as we expected it to exist
 
248
                self.assertNotEqual(-1, out.find(encoded_msg))
 
249
                out_unicode = out.decode(encoding)
 
250
                self.assertNotEqual(-1, out_unicode.find(self._message))
 
251
            else:
 
252
                self.assertNotEqual(-1, out.find('Message with ?'))
 
253
        finally:
 
254
            bzrlib.user_encoding = old_encoding
 
255
 
 
256
    def test_log_handles_encoding(self):
 
257
        self.create_branch()
 
258
 
 
259
        for encoding in self.good_encodings:
 
260
            self.try_encoding(encoding)
 
261
 
 
262
    def test_log_handles_bad_encoding(self):
 
263
        self.create_branch()
 
264
 
 
265
        for encoding in self.bad_encodings:
 
266
            self.try_encoding(encoding, fail=True)
 
267
 
 
268
    def test_stdout_encoding(self):
 
269
        bzr = self.run_bzr
 
270
        bzrlib.user_encoding = "cp1251"
 
271
 
 
272
        bzr('init')
 
273
        self.build_tree(['a'])
 
274
        bzr('add', 'a')
 
275
        bzr('commit', '-m', u'\u0422\u0435\u0441\u0442')
 
276
        stdout, stderr = self.run_bzr('log', encoding='cp866')
 
277
 
 
278
        message = stdout.splitlines()[-1]
 
279
 
 
280
        # explanation of the check:
 
281
        # u'\u0422\u0435\u0441\u0442' is word 'Test' in russian
 
282
        # in cp866  encoding this is string '\x92\xa5\xe1\xe2'
 
283
        # in cp1251 encoding this is string '\xd2\xe5\xf1\xf2'
 
284
        # This test should check that output of log command
 
285
        # encoded to sys.stdout.encoding
 
286
        test_in_cp866 = '\x92\xa5\xe1\xe2'
 
287
        test_in_cp1251 = '\xd2\xe5\xf1\xf2'
 
288
        # Make sure the log string is encoded in cp866
 
289
        self.assertEquals(test_in_cp866, message[2:])
 
290
        # Make sure the cp1251 string is not found anywhere
 
291
        self.assertEquals(-1, stdout.find(test_in_cp1251))
 
292
 
 
293
 
 
294
class TestLogFile(TestCaseWithTransport):
 
295
 
 
296
    def test_log_local_branch_file(self):
 
297
        """We should be able to log files in local treeless branches"""
 
298
        tree = self.make_branch_and_tree('tree')
 
299
        self.build_tree(['tree/file'])
 
300
        tree.add('file')
 
301
        tree.commit('revision 1')
 
302
        tree.bzrdir.destroy_workingtree()
 
303
        self.run_bzr('log', 'tree/file')