~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006 by 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
"""Black-box tests for bzr handling non-ascii characters."""
 
19
 
 
20
import sys
 
21
import os
 
22
 
 
23
import bzrlib
 
24
from bzrlib.tests import TestCaseInTempDir, TestSkipped
 
25
from bzrlib.trace import mutter, note
 
26
import bzrlib.urlutils as urlutils
 
27
 
 
28
 
 
29
class TestNonAscii(TestCaseInTempDir):
 
30
    """Test that bzr handles files/committers/etc which are non-ascii."""
 
31
 
 
32
    def setUp(self):
 
33
        super(TestNonAscii, self).setUp()
 
34
        self._orig_email = os.environ.get('BZREMAIL', None)
 
35
        self._orig_encoding = bzrlib.user_encoding
 
36
 
 
37
        bzrlib.user_encoding = self.encoding
 
38
        email = self.info['committer'] + ' <joe@foo.com>'
 
39
        os.environ['BZREMAIL'] = email.encode(bzrlib.user_encoding)
 
40
        self.create_base()
 
41
 
 
42
    def tearDown(self):
 
43
        if self._orig_email is not None:
 
44
            os.environ['BZREMAIL'] = self._orig_email
 
45
        else:
 
46
            if os.environ.get('BZREMAIL', None) is not None:
 
47
                del os.environ['BZREMAIL']
 
48
        bzrlib.user_encoding = self._orig_encoding
 
49
        super(TestNonAscii, self).tearDown()
 
50
 
 
51
    def create_base(self):
 
52
        bzr = self.run_bzr
 
53
 
 
54
        fs_enc = sys.getfilesystemencoding()
 
55
        fname = self.info['filename']
 
56
        dir_name = self.info['directory']
 
57
        for thing in [fname, dir_name]:
 
58
            try:
 
59
                thing.encode(fs_enc)
 
60
            except UnicodeEncodeError:
 
61
                raise TestSkipped(('Unable to represent path %r'
 
62
                                   ' in filesystem encoding %s')
 
63
                                    % (thing, fs_enc))
 
64
 
 
65
        bzr('init')
 
66
        open('a', 'wb').write('foo\n')
 
67
        bzr('add', 'a')
 
68
        bzr('commit', '-m', 'adding a')
 
69
 
 
70
        open('b', 'wb').write('non-ascii \xFF\xFF\xFC\xFB\x00 in b\n')
 
71
        bzr('add', 'b')
 
72
        bzr('commit', '-m', self.info['message'])
 
73
 
 
74
        open(fname, 'wb').write('unicode filename\n')
 
75
        bzr('add', fname)
 
76
        bzr('commit', '-m', u'And a unicode file\n')
 
77
 
 
78
    def test_status(self):
 
79
        bzr = self.run_bzr_decode
 
80
 
 
81
        open(self.info['filename'], 'ab').write('added something\n')
 
82
        txt = bzr('status')
 
83
        self.assertEqual(u'modified:\n  %s\n' % (self.info['filename'],), txt)
 
84
 
 
85
        txt = bzr('status', encoding='ascii')
 
86
        expected = u'modified:\n  %s\n' % (
 
87
                    self.info['filename'].encode('ascii', 'replace'),)
 
88
        self.assertEqual(expected, txt)
 
89
 
 
90
    def test_cat(self):
 
91
        # bzr cat shouldn't change the contents
 
92
        # using run_bzr since that doesn't decode
 
93
        txt = self.run_bzr('cat', 'b')[0]
 
94
        self.assertEqual('non-ascii \xFF\xFF\xFC\xFB\x00 in b\n', txt)
 
95
 
 
96
        txt = self.run_bzr('cat', self.info['filename'])[0]
 
97
        self.assertEqual('unicode filename\n', txt)
 
98
 
 
99
    def test_cat_revision(self):
 
100
        bzr = self.run_bzr_decode
 
101
 
 
102
        committer = self.info['committer']
 
103
        txt = bzr('cat-revision', '-r', '1')
 
104
        self.failUnless(committer in txt,
 
105
                        'failed to find %r in %r' % (committer, txt))
 
106
 
 
107
        msg = self.info['message']
 
108
        txt = bzr('cat-revision', '-r', '2')
 
109
        self.failUnless(msg in txt, 'failed to find %r in %r' % (msg, txt))
 
110
 
 
111
    def test_mkdir(self):
 
112
        bzr = self.run_bzr_decode
 
113
 
 
114
        txt = bzr('mkdir', self.info['directory'])
 
115
        self.assertEqual(u'added %s\n' % self.info['directory'], txt)
 
116
 
 
117
        # The text should be garbled, but the command should succeed
 
118
        txt = bzr('mkdir', self.info['directory'] + '2', encoding='ascii')
 
119
        expected = u'added %s2\n' % (self.info['directory'],)
 
120
        expected = expected.encode('ascii', 'replace')
 
121
        self.assertEqual(expected, txt)
 
122
 
 
123
    def test_relpath(self):
 
124
        bzr = self.run_bzr_decode
 
125
 
 
126
        txt = bzr('relpath', self.info['filename'])
 
127
        self.assertEqual(self.info['filename'] + '\n', txt)
 
128
 
 
129
        bzr('relpath', self.info['filename'], encoding='ascii', retcode=3)
 
130
 
 
131
    def test_inventory(self):
 
132
        bzr = self.run_bzr_decode
 
133
 
 
134
        txt = bzr('inventory')
 
135
        self.assertEqual(['a', 'b', self.info['filename']],
 
136
                         txt.splitlines())
 
137
 
 
138
        # inventory should fail if unable to encode
 
139
        bzr('inventory', encoding='ascii', retcode=3)
 
140
 
 
141
        # We don't really care about the ids themselves,
 
142
        # but the command shouldn't fail
 
143
        txt = bzr('inventory', '--show-ids')
 
144
 
 
145
    def test_revno(self):
 
146
        # There isn't a lot to test here, since revno should always
 
147
        # be an integer
 
148
        bzr = self.run_bzr_decode
 
149
 
 
150
        self.assertEqual('3\n', bzr('revno'))
 
151
        self.assertEqual('3\n', bzr('revno', encoding='ascii'))
 
152
 
 
153
    def test_revision_info(self):
 
154
        bzr = self.run_bzr_decode
 
155
 
 
156
        bzr('revision-info', '-r', '1')
 
157
 
 
158
        # TODO: jam 20060105 If we support revisions with non-ascii characters,
 
159
        # this should be strict and fail.
 
160
        bzr('revision-info', '-r', '1', encoding='ascii')
 
161
 
 
162
    def test_mv(self):
 
163
        bzr = self.run_bzr_decode
 
164
 
 
165
        fname1 = self.info['filename']
 
166
        fname2 = self.info['filename'] + '2'
 
167
        dirname = self.info['directory']
 
168
 
 
169
        # fname1 already exists
 
170
        bzr('mv', 'a', fname1, retcode=3)
 
171
 
 
172
        txt = bzr('mv', 'a', fname2)
 
173
        self.assertEqual(u'a => %s\n' % fname2, txt)
 
174
        self.failIfExists('a')
 
175
        self.failUnlessExists(fname2)
 
176
 
 
177
        bzr('commit', '-m', 'renamed to non-ascii')
 
178
 
 
179
        bzr('mkdir', dirname)
 
180
        txt = bzr('mv', fname1, fname2, dirname)
 
181
        self.assertEqual([u'%s => %s/%s' % (fname1, dirname, fname1),
 
182
                          u'%s => %s/%s' % (fname2, dirname, fname2)]
 
183
                         , txt.splitlines())
 
184
 
 
185
        # The rename should still succeed
 
186
        newpath = u'%s/%s' % (dirname, fname2)
 
187
        txt = bzr('mv', newpath, 'a', encoding='ascii')
 
188
        self.failUnlessExists('a')
 
189
        self.assertEqual(newpath.encode('ascii', 'replace') + ' => a\n', txt)
 
190
 
 
191
    def test_branch(self):
 
192
        # We should be able to branch into a directory that
 
193
        # has a unicode name, even if we can't display the name
 
194
        bzr = self.run_bzr_decode
 
195
        bzr('branch', u'.', self.info['directory'])
 
196
        bzr('branch', u'.', self.info['directory'] + '2', encoding='ascii')
 
197
 
 
198
    def test_pull(self):
 
199
        # Make sure we can pull from paths that can't be encoded
 
200
        bzr = self.run_bzr_decode
 
201
 
 
202
        dirname1 = self.info['directory']
 
203
        dirname2 = self.info['directory'] + '2'
 
204
        bzr('branch', '.', dirname1)
 
205
        bzr('branch', dirname1, dirname2)
 
206
 
 
207
        os.chdir(dirname1)
 
208
        open('a', 'ab').write('more text\n')
 
209
        bzr('commit', '-m', 'mod a')
 
210
 
 
211
        pwd = os.getcwdu()
 
212
 
 
213
        os.chdir(u'../' + dirname2)
 
214
        txt = bzr('pull')
 
215
 
 
216
        self.assertEqual(u'Using saved location: %s/\n' % (pwd,), txt)
 
217
 
 
218
        os.chdir('../' + dirname1)
 
219
        open('a', 'ab').write('and yet more\n')
 
220
        bzr('commit', '-m', 'modifying a by ' + self.info['committer'])
 
221
 
 
222
        os.chdir('../' + dirname2)
 
223
        # We should be able to pull, even if our encoding is bad
 
224
        bzr('pull', '--verbose', encoding='ascii')
 
225
 
 
226
    def test_push(self):
 
227
        # TODO: Test push to an SFTP location
 
228
        # Make sure we can pull from paths that can't be encoded
 
229
        bzr = self.run_bzr_decode
 
230
 
 
231
        # TODO: jam 20060427 For drastically improving performance, we probably
 
232
        #       could create a local repository, so it wouldn't have to copy
 
233
        #       the files around as much.
 
234
 
 
235
        dirname = self.info['directory']
 
236
        bzr('push', dirname)
 
237
 
 
238
        open('a', 'ab').write('adding more text\n')
 
239
        bzr('commit', '-m', 'added some stuff')
 
240
 
 
241
        # TODO: check the output text is properly encoded
 
242
        bzr('push')
 
243
 
 
244
        f = open('a', 'ab')
 
245
        f.write('and a bit more: ')
 
246
        f.write(dirname.encode('utf-8'))
 
247
        f.write('\n')
 
248
        f.close()
 
249
 
 
250
        bzr('commit', '-m', u'Added some ' + dirname)
 
251
        bzr('push', '--verbose', encoding='ascii')
 
252
 
 
253
        bzr('push', '--verbose', dirname + '2')
 
254
 
 
255
        bzr('push', '--verbose', dirname + '3', encoding='ascii')
 
256
 
 
257
        bzr('push', '--verbose', '--create-prefix', dirname + '4/' + dirname + '5')
 
258
        bzr('push', '--verbose', '--create-prefix', dirname + '6/' + dirname + '7', encoding='ascii')
 
259
 
 
260
    def test_renames(self):
 
261
        bzr = self.run_bzr_decode
 
262
 
 
263
        fname = self.info['filename'] + '2'
 
264
        bzr('mv', 'a', fname)
 
265
        txt = bzr('renames')
 
266
        self.assertEqual(u'a => %s\n' % fname, txt)
 
267
 
 
268
        bzr('renames', retcode=3, encoding='ascii')
 
269
 
 
270
    def test_remove(self):
 
271
        bzr = self.run_bzr_decode
 
272
 
 
273
        fname = self.info['filename']
 
274
        txt = bzr('remove', fname, encoding='ascii')
 
275
 
 
276
    def test_remove_verbose(self):
 
277
        bzr = self.run_bzr_decode
 
278
 
 
279
        fname = self.info['filename']
 
280
        txt = bzr('remove', '--verbose', fname, encoding='ascii')
 
281
 
 
282
    def test_file_id(self):
 
283
        bzr = self.run_bzr_decode
 
284
 
 
285
        fname = self.info['filename']
 
286
        txt = bzr('file-id', fname)
 
287
 
 
288
        # TODO: jam 20060106 We don't support non-ascii file ids yet, 
 
289
        #       so there is nothing which would fail in ascii encoding
 
290
        #       This *should* be retcode=3
 
291
        txt = bzr('file-id', fname, encoding='ascii')
 
292
 
 
293
    def test_file_path(self):
 
294
        bzr = self.run_bzr_decode
 
295
 
 
296
        # Create a directory structure
 
297
        fname = self.info['filename']
 
298
        dirname = self.info['directory']
 
299
        bzr('mkdir', 'base')
 
300
        bzr('mkdir', 'base/' + dirname)
 
301
        path = '/'.join(['base', dirname, fname])
 
302
        bzr('mv', fname, path)
 
303
        bzr('commit', '-m', 'moving things around')
 
304
 
 
305
        txt = bzr('file-path', path)
 
306
 
 
307
        # TODO: jam 20060106 We don't support non-ascii file ids yet, 
 
308
        #       so there is nothing which would fail in ascii encoding
 
309
        #       This *should* be retcode=3
 
310
        txt = bzr('file-path', path, encoding='ascii')
 
311
 
 
312
    def test_revision_history(self):
 
313
        bzr = self.run_bzr_decode
 
314
 
 
315
        # TODO: jam 20060106 We don't support non-ascii revision ids yet, 
 
316
        #       so there is nothing which would fail in ascii encoding
 
317
        txt = bzr('revision-history')
 
318
 
 
319
    def test_ancestry(self):
 
320
        bzr = self.run_bzr_decode
 
321
 
 
322
        # TODO: jam 20060106 We don't support non-ascii revision ids yet, 
 
323
        #       so there is nothing which would fail in ascii encoding
 
324
        txt = bzr('ancestry')
 
325
 
 
326
    def test_diff(self):
 
327
        # TODO: jam 20060106 diff is a difficult one to test, because it 
 
328
        #       shouldn't encode the file contents, but it needs some sort
 
329
        #       of encoding for the paths, etc which are displayed.
 
330
        open(self.info['filename'], 'ab').write('newline\n')
 
331
        txt = self.run_bzr('diff', retcode=1)[0]
 
332
 
 
333
    def test_deleted(self):
 
334
        bzr = self.run_bzr_decode
 
335
 
 
336
        fname = self.info['filename']
 
337
        os.remove(fname)
 
338
        bzr('rm', fname)
 
339
 
 
340
        txt = bzr('deleted')
 
341
        self.assertEqual(fname+'\n', txt)
 
342
 
 
343
        txt = bzr('deleted', '--show-ids')
 
344
        self.failUnless(txt.startswith(fname))
 
345
 
 
346
        # Deleted should fail if cannot decode
 
347
        # Because it is giving the exact paths
 
348
        # which might be used by a front end
 
349
        bzr('deleted', encoding='ascii', retcode=3)
 
350
 
 
351
    def test_modified(self):
 
352
        bzr = self.run_bzr_decode
 
353
 
 
354
        fname = self.info['filename']
 
355
        open(fname, 'ab').write('modified\n')
 
356
 
 
357
        txt = bzr('modified')
 
358
        self.assertEqual(fname+'\n', txt)
 
359
 
 
360
        bzr('modified', encoding='ascii', retcode=3)
 
361
 
 
362
    def test_added(self):
 
363
        bzr = self.run_bzr_decode
 
364
 
 
365
        fname = self.info['filename'] + '2'
 
366
        open(fname, 'wb').write('added\n')
 
367
        bzr('add', fname)
 
368
 
 
369
        txt = bzr('added')
 
370
        self.assertEqual(fname+'\n', txt)
 
371
 
 
372
        bzr('added', encoding='ascii', retcode=3)
 
373
 
 
374
    def test_root(self):
 
375
        bzr = self.run_bzr_decode
 
376
 
 
377
        dirname = self.info['directory']
 
378
        bzr('root')
 
379
 
 
380
        bzr('branch', u'.', dirname)
 
381
 
 
382
        os.chdir(dirname)
 
383
 
 
384
        txt = bzr('root')
 
385
        self.failUnless(txt.endswith(dirname+'\n'))
 
386
 
 
387
        txt = bzr('root', encoding='ascii', retcode=3)
 
388
 
 
389
    def test_log(self):
 
390
        bzr = self.run_bzr_decode
 
391
 
 
392
        fname = self.info['filename']
 
393
 
 
394
        txt = bzr('log')
 
395
        self.assertNotEqual(-1, txt.find(self.info['committer']))
 
396
        self.assertNotEqual(-1, txt.find(self.info['message']))
 
397
 
 
398
        txt = bzr('log', '--verbose')
 
399
        self.assertNotEqual(-1, txt.find(fname))
 
400
 
 
401
        # Make sure log doesn't fail even if we can't write out
 
402
        txt = bzr('log', '--verbose', encoding='ascii')
 
403
        self.assertEqual(-1, txt.find(fname))
 
404
        self.assertNotEqual(-1, txt.find(fname.encode('ascii', 'replace')))
 
405
 
 
406
    def test_touching_revisions(self):
 
407
        bzr = self.run_bzr_decode
 
408
 
 
409
        fname = self.info['filename']
 
410
        txt = bzr('touching-revisions', fname)
 
411
        self.assertEqual(u'     3 added %s\n' % (fname,), txt)
 
412
 
 
413
        fname2 = self.info['filename'] + '2'
 
414
        bzr('mv', fname, fname2)
 
415
        bzr('commit', '-m', u'Renamed %s => %s' % (fname, fname2))
 
416
 
 
417
        txt = bzr('touching-revisions', fname2)
 
418
        expected_txt = (u'     3 added %s\n' 
 
419
                        u'     4 renamed %s => %s\n'
 
420
                        % (fname, fname, fname2))
 
421
        self.assertEqual(expected_txt, txt)
 
422
 
 
423
        bzr('touching-revisions', fname2, encoding='ascii', retcode=3)
 
424
 
 
425
    def test_ls(self):
 
426
        bzr = self.run_bzr_decode
 
427
 
 
428
        txt = bzr('ls')
 
429
        self.assertEqual(['a', 'b', self.info['filename']],
 
430
                         txt.splitlines())
 
431
        txt = bzr('ls', '--null')
 
432
        self.assertEqual(['a', 'b', self.info['filename'], ''],
 
433
                         txt.split('\0'))
 
434
 
 
435
        txt = bzr('ls', encoding='ascii', retcode=3)
 
436
        txt = bzr('ls', '--null', encoding='ascii', retcode=3)
 
437
 
 
438
    def test_unknowns(self):
 
439
        bzr = self.run_bzr_decode
 
440
 
 
441
        fname = self.info['filename'] + '2'
 
442
        open(fname, 'wb').write('unknown\n')
 
443
 
 
444
        # TODO: jam 20060112 bzr unknowns is the only one which 
 
445
        #       quotes paths do we really want it to?
 
446
        txt = bzr('unknowns')
 
447
        self.assertEqual(u'"%s"\n' % (fname,), txt)
 
448
 
 
449
        bzr('unknowns', encoding='ascii', retcode=3)
 
450
 
 
451
    def test_ignore(self):
 
452
        bzr = self.run_bzr_decode
 
453
 
 
454
        fname2 = self.info['filename'] + '2.txt'
 
455
        open(fname2, 'wb').write('ignored\n')
 
456
 
 
457
        txt = bzr('unknowns')
 
458
        self.assertEqual(u'"%s"\n' % (fname2,), txt)
 
459
 
 
460
        bzr('ignore', './' + fname2)
 
461
        txt = bzr('unknowns')
 
462
        self.assertEqual(u'', txt)
 
463
 
 
464
        fname3 = self.info['filename'] + '3.txt'
 
465
        open(fname3, 'wb').write('unknown 3\n')
 
466
        txt = bzr('unknowns')
 
467
        self.assertEqual(u'"%s"\n' % (fname3,), txt)
 
468
 
 
469
        # Ignore should not care what the encoding is
 
470
        # (right now it doesn't print anything)
 
471
        bzr('ignore', fname3, encoding='ascii')
 
472
        txt = bzr('unknowns')
 
473
        self.assertEqual('', txt)
 
474
 
 
475
        # Now try a wildcard match
 
476
        fname4 = self.info['filename'] + '4.txt'
 
477
        open(fname4, 'wb').write('unknown 4\n')
 
478
        bzr('ignore', '*.txt')
 
479
        txt = bzr('unknowns')
 
480
        self.assertEqual('', txt)
 
481
 
 
482
        os.remove('.bzrignore')
 
483
        bzr('ignore', self.info['filename'] + '*')
 
484
        txt = bzr('unknowns')
 
485
        self.assertEqual('', txt)
 
486
 
 
487